tgodfrey
asked on
How to use TStream to read a binary file containing both integers and Cstrings?
I am trying to determine how to use TStream or descendents to read a binary file containing a mixture of integers, words, and null-terminated strings (Cstrings).
I can read any fixed size objects with the Tstream ReadBuffer method. This requires the object size known in advance, to provide as a parameter. TStringStreams support string types only, and has no means to read integers.
What is the easiest/best way to read both variable-size, null-terminated strings and integer values in an arbitrary mix, from the same stream?
Is there any approach better than brute force? (IE, creating a function that reads one byte at a time from the stream, copying them into a string, and ending on a zero byte)
I can read any fixed size objects with the Tstream ReadBuffer method. This requires the object size known in advance, to provide as a parameter. TStringStreams support string types only, and has no means to read integers.
What is the easiest/best way to read both variable-size, null-terminated strings and integer values in an arbitrary mix, from the same stream?
Is there any approach better than brute force? (IE, creating a function that reads one byte at a time from the stream, copying them into a string, and ending on a zero byte)
ASKER
To clarify, I do not control the format of the binary file. It is an existing file. I know the format, but my program does not write it, and I don't have the ability to change the program that generates the binary file.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I should have clarified the term "feasible" in the above comment.... By that I meant that if this file will always be less than a few MB of data (or whatever you consider reasonable to load directly into memory), then there should be no issues loading it directly into memory and accessing the data using a memory stream.
Now, if there is a chance that the file is larger than the user's (or yours) total "physical" memory, then loading it into memory is not really viable for you. At that point you will be stuck block reading the data and handling it that way. Eg, using a file stream, etc...
Russell
ASKER
Thanks Russell. I hadn't thought of accessing the file directly using a pointer to the in-memory version of the stream, and it works for the particular case I have where files are only a few Mbytes. As you note, you have add a lot of checks for the "unsafe" memory access, but performance of MoveMemory for long strings would be better than byte-at-a-time Tstream.ReadBuffer calls.
If the storage is not in any predefined format (eg a record structure), then a common technique is to use a byte type identifier that indicates the data that is to follow.
eg
#1 = Word data
[01 00 02 ...]
#2 = Integer data
[02 00 00 00 03 ...]
#3 = String data, with additional byte (or word, etc) indicating length of string plus null(eg "file")
[03 05 66 69 6C 65 00 ...]
This would allow you to read data in an efficient manner, and allow you to get string data in 3 read (data type, data size, data), vs reading byte by byte.
Regards,
Russell