Write\Read Structure()
-
- Enthusiast
- Posts: 665
- Joined: Fri Sep 12, 2003 10:40 pm
- Location: Tallahassee, Florida
Write\Read Structure()
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
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
Code: Select all
!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
-
- Enthusiast
- Posts: 665
- Joined: Fri Sep 12, 2003 10:40 pm
- Location: Tallahassee, Florida
no one? not anyone would like to see this? wow, am i out in left field or what here.
Code: Select all
!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
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.
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.
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.
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.
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
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 <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
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
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
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....
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.
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)
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.
For such structure, you can use:
The structure should not contain any regular strings (.s)
Code: Select all
WriteData(#File, Variable.YourStruct, @SizeOf(YourStruct)
This is true only if you don't need to modify in any following version. For exemple the 1st version of the structure is :Fred wrote:For such structure, you can use:
The structure should not contain any regular strings (.s)Code: Select all
WriteData(#File, Variable.YourStruct, @SizeOf(YourStruct)
Code: Select all
Structure Student
Fornames.s{30}
Surname.s{25}
DOB_DD.s{2}
DOB_MM.s{2}
DOB_YY.s{2}
EndStructure
Code: Select all
Structure Student
Fornames.s{60}
Surname.s{50}
DOB_DD.s{6}
DOB_MM.s{6}
DOB_YY.s{6}
EndStructure
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 <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Guimauve