Page 1 of 1
Write\Read Structure()
Posted: Mon Feb 13, 2006 9:41 pm
by localmotion34
i use structures for a ton of stuff, and it would be nice to be able to just pass the address of a structured variable and have PB write the data to the file. then be able to open the file, and read the structure data and have it reassembeld into a working structured variable.
like:
structure test
long.l
string.s
nested.l[30]
another.q
float.d
endstructure
variable.test
variabe\float=0.90909033
variabe\string=getgadgettext(#gadget_editor)
writestructure(#file_0,location)
the procedure could return 0 for an error, but if successful, return the location that you are now in the file.
now: readstructure(#file_0,location, newvariable.test)
debug newvariabe\string
Posted: Tue Feb 14, 2006 9:31 pm
by localmotion34
no one? not anyone would like to see this? wow, am i out in left field or what here.
Posted: Tue Feb 14, 2006 10:19 pm
by Shannara
I could of sworn on these forums, someone had a 3.8x(?) version of code that will step through the members of a structure and write them to file, automatically .. much like your doing. But it may have been lost between the many forum post wipes.
I really dont know if it's possible in PB any more. It would definately ease the read/writing to/from files tremendously in PB.
Posted: Tue Feb 14, 2006 11:09 pm
by Guimauve
All interpreted language, like MatLAB, can do this.
Personnally I prefer to control how my structure is "Write" and "Read" on file. But I agree this task must be done for each Structure you create.
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure definition >>>>>
Structure Test
long.l
string.s
nested.l[30]
another.q
float.d
EndStructure
; <<<<<<<<<<<<<<<<<<<<
; <<<<< Mutators >>>>>
Procedure SetTestlong(*ObjectA.Test, long.l)
*ObjectA\long = long
EndProcedure
Procedure SetTeststring(*ObjectA.Test, string.s)
*ObjectA\string = string
EndProcedure
Procedure SetTestnested(*ObjectA.Test, Index, Value.l)
*ObjectA\nested[Index] = Value
EndProcedure
Procedure SetTestanother(*ObjectA.Test, another.q)
*ObjectA\another = another
EndProcedure
Procedure SetTestfloat(*ObjectA.Test, float.d)
*ObjectA\float = float
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Observators >>>>>
Procedure.l GetTestlong(*ObjectA.Test)
ProcedureReturn *ObjectA\long
EndProcedure
Procedure.s GetTeststring(*ObjectA.Test)
ProcedureReturn *ObjectA\string
EndProcedure
Procedure.l GetTestnested(*ObjectA.Test, Index)
ProcedureReturn *ObjectA\nested[Index]
EndProcedure
Procedure.q GetTestanother(*ObjectA.Test)
ProcedureReturn *ObjectA\another
EndProcedure
Procedure.d GetTestfloat(*ObjectA.Test)
ProcedureReturn *ObjectA\float
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read & Write Binary String <<<<<
Procedure WriteBinaryString(FileID.l, string.s)
Length.l = Len(string)
WriteLong(FileID, Length)
WriteData(FileID, @string, Length)
EndProcedure
Procedure.s ReadBinaryString(FileID.l)
Length.l = ReadLong(FileID)
string.s = Space(Length)
ReadData(FileID, @string, Length)
ProcedureReturn string
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read Binary file >>>>>
Procedure ReadTest(FileID.l, *ObjectA.Test)
SetTestlong(*ObjectA, ReadLong(FileID))
SetTeststring(*ObjectA, ReadBinaryString(FileID))
For Index = 0 To 29
SetTestnested(*ObjectA, Index, ReadLong(FileID))
Next
SetTestanother(*ObjectA, ReadQuad(FileID))
SetTestfloat(*ObjectA, ReadDouble(FileID))
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Write Binary file >>>>>
Procedure WriteTest(FileID.l, *ObjectA.Test)
WriteLong(FileID, GetTestlong(*ObjectA))
WriteBinaryString(FileID, GetTeststring(*ObjectA))
For Index = 0 To 29
WriteLong(FileID, GetTestnested(*ObjectA, Index))
Next
WriteQuad(FileID, GetTestanother(*ObjectA))
WriteDouble(FileID, GetTestfloat(*ObjectA))
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 31 ms <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Also, if you wish to save a mixed field type structure, like in your exemple, an implicit information must be written to the file (the string lenght). This is why I have created these following procedures.
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read & Write Binary String <<<<<
Procedure WriteBinaryString(FileID.l, string.s)
Length.l = Len(string)
WriteLong(FileID, Length)
WriteData(FileID, @string, Length)
EndProcedure
Procedure.s ReadBinaryString(FileID.l)
Length.l = ReadLong(FileID)
string.s = Space(Length)
ReadData(FileID, @string, Length)
ProcedureReturn string
EndProcedure
Other wise you will not be able to read the string from the file.
Anyways If Fred can achieve the goal to generate a procedure to Write and Read any Structure on binary file it can be greate.
Best Regards
Guimauve
Posted: Sat May 20, 2006 6:59 pm
by jonljacobi
I'd love this as well.
Cheers, Jon
Posted: Tue Jun 05, 2007 2:22 pm
by Prof
I second that. I have already e-mailed this request to Fred.
I think what is required is a GET & PUT command to read and create records in a file. The FileSeek command could be used as an index to the pointer in the file. Or maybe even a RECORDSEEK command to jump from record to record withough having to keep tabs on the file pointer with the Fileseek command.
example....
Code: Select all
Structure Student
Fornames.s{30}
Surname.s{25}
DOB_DD.s{2}
DOB_MM.s{2}
DOB_YY.s{2}
EndStructure
Dim Student_Array.Student(100)
Index=0
Student_Array(0)=Get(FileID,Index)
Would read a structure (one record) from FILEID at point INDEX and load it straight into the structure in the Student_Array at element 0.
This would be really handy to have but would only probably work with fixed length records (which I only use anyway).
I am currently trying to create my own workaround for the time being.
Posted: Tue Jun 05, 2007 6:15 pm
by Fred
For such structure, you can use:
Code: Select all
WriteData(#File, Variable.YourStruct, @SizeOf(YourStruct)
The structure should not contain any regular strings (.s)
Posted: Wed Jun 06, 2007 3:13 am
by Guimauve
Fred wrote:For such structure, you can use:
Code: Select all
WriteData(#File, Variable.YourStruct, @SizeOf(YourStruct)
The structure should not contain any regular strings (.s)
This is true only if you don't need to modify in any following version. For exemple the 1st version of the structure is :
Code: Select all
Structure Student
Fornames.s{30}
Surname.s{25}
DOB_DD.s{2}
DOB_MM.s{2}
DOB_YY.s{2}
EndStructure
But the 2nd version of the structure is :
Code: Select all
Structure Student
Fornames.s{60}
Surname.s{50}
DOB_DD.s{6}
DOB_MM.s{6}
DOB_YY.s{6}
EndStructure
After this update you will not be able to load the old version anymore with ReadData().
Anyway if you are sure about your structure definition you can use Read/Write Data without any problems. But in my point of view it's not a safe way to save string in a binary file.
If you need to have a regular string (.s) in your stucture the only way to do the gob it's something like this :
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<
Structure Student
Fornames.s
Surname.s
DOB_DD.s
DOB_MM.s
DOB_YY.s
EndStructure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Read binary file operator <<<<<
Procedure ReadStudent(FileID.l, *StudentA.Student)
*StudentA\Fornames = Space(ReadLong(FileID))
ReadData(FileID, @*StudentA\Fornames, Len(*StudentA\Fornames))
*StudentA\Surname = Space(ReadLong(FileID))
ReadData(FileID, @*StudentA\Surname, Len(*StudentA\Surname))
*StudentA\DOB_DD = Space(ReadLong(FileID))
ReadData(FileID, @*StudentA\DOB_DD, Len(*StudentA\DOB_DD))
*StudentA\DOB_MM = Space(ReadLong(FileID))
ReadData(FileID, @*StudentA\DOB_MM, Len(*StudentA\DOB_MM))
*StudentA\DOB_YY = Space(ReadLong(FileID))
ReadData(FileID, @*StudentA\DOB_YY, Len(*StudentA\DOB_YY))
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Write binary file operator <<<<<
Procedure WriteStudent(FileID.l, *StudentA.Student)
WriteLong(FileID, Len(*StudentA\Fornames))
WriteData(FileID, @*StudentA\Fornames, Len(*StudentA\Fornames))
WriteLong(FileID, Len(*StudentA\Surname))
WriteData(FileID, @*StudentA\Surname, Len(*StudentA\Surname))
WriteLong(FileID, Len(*StudentA\DOB_DD))
WriteData(FileID, @*StudentA\DOB_DD, Len(*StudentA\DOB_DD))
WriteLong(FileID, Len(*StudentA\DOB_MM))
WriteData(FileID, @*StudentA\DOB_MM, Len(*StudentA\DOB_MM))
WriteLong(FileID, Len(*StudentA\DOB_YY))
WriteData(FileID, @*StudentA\DOB_YY, Len(*StudentA\DOB_YY))
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Regards
Guimauve