Link to home
Start Free TrialLog in
Avatar of tgodfrey
tgodfreyFlag for United States of America

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)

Avatar of Russell Libby
Russell Libby
Flag of United States of America image


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

Avatar of tgodfrey

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
Avatar of Russell Libby
Russell Libby
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial

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
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.