[UDF] marshal.au3 : encore les fichiers binaires
Posté : ven. 07 janv. 2011 18:38
par poke123
voila un UDF qui permet de sauvegarder des infos sous forme binaire plutôt que sous forme de texte avec filewrite ou iniwrite par exemple et de les récupérer dans l'ordre le tout ayant pour but de prendre moins de place sur le disque dur
ceci fonctionne pour les array, les structures et les valeurs seule
le nom marshal viens d'une classe qui doit être en LUA du même nom
l'exemple présent dans l'UDF est:
ceci fonctionne pour les array, les structures et les valeurs seule
le nom marshal viens d'une classe qui doit être en LUA du même nom
► Afficher le textemarshal.au3
Code : Tout sélectionner
#include <memory.au3>
#include <string.au3>
#include-once
; #FUNCTION# ====================================================================================================================
; Name...........: MarshalRead
; Description ...: lit le prochain array typé, la prochaine structure ou bien la prochaine donnée typé dans un fichier binaire
; Syntax.........: marshalRead($marshal, $type, $lenght, $Element)
; Parameters ....: $marshal: valeur retourné par la fonction marshal
; $type: type de donnée accepté par les dllstruct d'autoit ou bien texte d'une dllstruct
; $lenght: longueur des données à lire en octets
; $Element: -le nombre d'élément à lire pour un array
; -"struct" pour une structure
; -default pour une valeur seule
;
; Return values .: Success - valeur/array/structure demandé
; Failure - string null ""
; Author ........: Poke123
; Remarks .......: en demandant un array, on donne dans $type et dans $lenght l'équivalent d'un élément de l'array
; ===============================================================================================================================
func marshalRead(byref $marshal, $type, $lenght, $Element = -1)
if $Element <> -1 and $Element<>"struct" then
local $return[$Element]
for $i = 0 to $Element - 1
$s = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, "")
$dest = DllStructCreate($type)
if @error then Return SetError(2, 0, "")
DllStructSetData($s, 1, StringToBinary(stringright(FileRead($marshal[0], $lenght + $marshal[1]), $lenght)))
if @error then Return SetError(3, 0, "")
$marshal[1] += $lenght
_MemMoveMemory(DllStructGetPtr($s), DllStructGetPtr($dest), $lenght)
$return[$i] = DllStructGetData($dest,1)
$s = 0
$dest = 0
Next
return $return
Elseif $Element="struct" Then
$s = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, "")
$dest = DllStructCreate($type)
if @error then Return SetError(2, 0, "")
DllStructSetData($s, 1, StringToBinary(stringright(FileRead($marshal[0], $lenght + $marshal[1]), $lenght)))
if @error then Return SetError(3, 0, "")
$marshal[1] += $lenght
_MemMoveMemory(DllStructGetPtr($s), DllStructGetPtr($dest), $lenght)
$s = 0
return $dest
Else
$s = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, "")
$dest = DllStructCreate($type)
if @error then Return SetError(2, 0, "")
DllStructSetData($s, 1, StringToBinary(stringright(FileRead($marshal[0], $lenght + $marshal[1]), $lenght)))
if @error then Return SetError(3, 0, "")
$marshal[1] += $lenght
_MemMoveMemory(DllStructGetPtr($s), DllStructGetPtr($dest), $lenght)
$s = 0
return DllStructGetData($dest,1)
EndIf
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: MarshalWrite
; Description ...: écrit des données à la fin d'un fichier binaire
; Syntax.........: marshalWead($marshal, $type, $lenght, $Data)
; Parameters ....: $marshal: valeur retourné par la fonction marshal
; $type: type de donnée accepté par les dllstruct d'autoit ou bien texte d'une dllstruct
; $lenght: longueur des données à lire en octets
; $Data: valeur à écrire (array, strucuture ou valeur seule)
; Return values .: Success - 1
; Failure - 0
; Author ........: Poke123
; Remarks .......: la lecture se fait au curseur mais l'écriture se fait toujours à la fin du fichier
; ===============================================================================================================================
func marshalWrite($marshal,$type,$lenght,$data)
if IsArray($data) then
for $i = 0 to UBound($data) - 1
$dest = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, 0)
$s = DllStructCreate($type)
if @error then Return SetError(2, 0, 0)
DllStructSetData($s, 1, $data[$i])
_MemMoveMemory(DllStructGetPtr($s), DllStructGetPtr($dest), $lenght)
FileWrite($marshal[0], BinaryToString(DllStructGetData($dest,1)))
$dest = 0
$s = 0
Next
Elseif IsDllStruct($data) Then
$dest = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, 0)
_MemMoveMemory(DllStructGetPtr($data), DllStructGetPtr($dest), $lenght)
FileWrite($marshal[0], BinaryToString(DllStructGetData($dest,1)))
$dest = 0
Else
$dest = DllStructCreate("byte["&$lenght&"]")
if @error then Return SetError(1, 0, 0)
$s = DllStructCreate($type)
if @error then Return SetError(2, 0, 0)
DllStructSetData($s, 1, $data)
_MemMoveMemory(DllStructGetPtr($s), DllStructGetPtr($dest), $lenght)
FileWrite($marshal[0], BinaryToString(DllStructGetData($dest,1)))
$dest = 0
$s = 0
EndIf
return 1
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: Marshal
; Description ...: creer une variable marshal utilisable dans les fonctions marshalread et marshalwrite
; Syntax.........: marshal($file, $start)
; Parameters ....: $file: fichier à ouvrir
; $start: position de départ du curseur de lecture (l'écriture se fait toujours à la fin du fichier)
; Return values .: Success - une variable marshal utilisable
; Failure - une variable marshal qui ne marche pas (nan mais pour rater son coup il faut le faire exprès quoi ...)
; Author ........: Poke123
; Remarks .......: aucune
; ===============================================================================================================================
func marshal($file,$start = 0)
local $marshal[2]
$marshal[0] = $file
$marshal[1] = $start
return $marshal
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: MarshalCursor
; Description ...: obtient ou défini la position du curseur
; Syntax.........: marshal($marshal, $value)
; Parameters ....: $marshal: valeur retourné par la fonction marshal
; $value: nouvelle position du curseur (pour changer, sinon laisser default)
; Return values .: Success - la position du curseur
; Failure - impossible sans le vouloir
; Author ........: Poke123
; Remarks .......: aucune
; ===============================================================================================================================
func MarshalCursor(byref $marshal, $value = -1)
if $value >= 0 and IsInt($value) then $marshal[1] = $value
return $marshal[1]
EndFunc
;exemple d'utilisation de marshal
func marshalExemple()
;si test.a existe on le supprime
;on créer un nouveau marshal sur le fichier test.a
FileDelete("test.a")
$m = marshal("test.a")
;on écrit un float et un int (je sais que les variable typé on a pas l'habitude en autoit mais c'est obligatoire ici)
marshalWrite($m, "float", 4, 0.41254) ;sizeof(float) = 4
marshalWrite($m, "int", 4, 475414) ;sizeof(int) = 4
;on fait de même avec un array d'entier
;que l'on stock sous forme de byte pour économiser de la place (facteur de 4)
local $int5[5] = [1,2,3,4,5]
marshalWrite($m, "byte", 1, $int5)
;on fait une structure avec un nom et un age pour stocker une personne par exemple (ne pas utiliser les nom d'élément, utiliser leurs index en 1 based)
$dll = DllStructCreate("char[10]; byte")
DllStructSetData($dll, 1, "dupont")
DllStructSetData($dll, 2, 45)
marshalWrite($m, "char[10]; byte", 10 + 1, $dll) ;sizeof(char) = 1 et sizeof(byte) = 1
;puis on lit ce qu'on a stocker un par un dans la console
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : marshalRead($m, "float", 4) = ' & marshalRead($m, "float", 4) & @crlf & '>Error code: ' & @error & @crlf)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : marshalRead($m, "int", 4) = ' & marshalRead($m, "int", 4) & @crlf & '>Error code: ' & @error & @crlf)
;pour l'array on affiche toutes les entrée une par une
$a = marshalRead($m, "byte", 1, 5)
for $i = 0 to ubound($a) - 1
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $a[$i] = ' & $a[$i] & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
Next
;et on affiche aussi la personne
$dll = marshalRead($m, "char[10]; byte", 10 + 1, "struct")
ConsoleWrite("nom: "&DllStructGetData($dll, 1)&@crlf&"age: "&DllStructGetData($dll, 2)&@crlf)
;enfin on affiche le contenu binaire du fichier
ConsoleWrite( "contenu binaire du fichier:"& @crlf &fileread(FileOpen("test.a", 16))&@crlf)
EndFunc
► Afficher le texteexemple
Code : Tout sélectionner
;si test.a existe on le supprime
;on créer un nouveau marshal sur le fichier test.a
FileDelete("test.a")
$m = marshal("test.a")
;on écrit un float et un int (je sais que les variable typé on a pas l'habitude en autoit mais c'est obligatoire ici)
marshalWrite($m, "float", 4, 0.41254) ;sizeof(float) = 4
marshalWrite($m, "int", 4, 475414) ;sizeof(int) = 4
;on fait de même avec un array d'entier
;que l'on stock sous forme de byte pour économiser de la place (facteur de 4)
local $int5[5] = [1,2,3,4,5]
marshalWrite($m, "byte", 1, $int5)
;on fait une structure avec un nom et un age pour stocker une personne par exemple (ne pas utiliser les nom d'élément, utiliser leurs index en 1 based)
$dll = DllStructCreate("char[10]; byte")
DllStructSetData($dll, 1, "dupont")
DllStructSetData($dll, 2, 45)
marshalWrite($m, "char[10]; byte", 10 + 1, $dll) ;sizeof(char) = 1 et sizeof(byte) = 1
;puis on lit ce qu'on a stocker un par un dans la console
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : marshalRead($m, "float", 4) = ' & marshalRead($m, "float", 4) & @crlf & '>Error code: ' & @error & @crlf)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : marshalRead($m, "int", 4) = ' & marshalRead($m, "int", 4) & @crlf & '>Error code: ' & @error & @crlf)
;pour l'array on affiche toutes les entrée une par une
$a = marshalRead($m, "byte", 1, 5)
for $i = 0 to ubound($a) - 1
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $a[$i] = ' & $a[$i] & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
Next
;et on affiche aussi la personne
$dll = marshalRead($m, "char[10]; byte", 10 + 1, "struct")
ConsoleWrite("nom: "&DllStructGetData($dll, 1)&@crlf&"age: "&DllStructGetData($dll, 2)&@crlf)
;enfin on affiche le contenu binaire du fichier
ConsoleWrite( "contenu binaire du fichier:"& @crlf &fileread(FileOpen("test.a", 16))&@crlf)