Samuel Grenon Samuel Grenon - 4 years ago 70
C++ Question

I am trying to read a binary file with strings and integers... And print out the integers corresponded to the string

Im trying to read a binary file with strings and integers and print out the integer corresponding to the string aka its on the same line. I know how to read integers from a binary file such as read(buffer, 4) but i have never read strings before. I actually have no idea how big these strings are.. 100bytes reads most of the file but not all of it.... The file format looks something like this.

jcake 567
sgrenon 17

im trying to grab the numbers after the name, and print them into an iostream. I understand how to read int's because there usually 4 bytes. I just never read a binary file with strings in it.

while (readfile.good())
{

char*buffer = new char[100];
readfile.read(buffer, 100);
if (readfile.eof())
{
delete[] buffer;
break;
}

cout << buffer << endl;

Dai Dai
Answer Source

There are many different ways to serialize strings in binary files. The most common ways are:

  1. A length-prefixed byte sequence, the length is stored as an integer value and is typically either 1, 2 or 4 bytes in length, followed by the data itself, e.g. 0x04 0x46 0x4F 0x4F 0x44 (0x04 = 4 bytes, 46,4F,4F,44 == "FOOD"). Because the length is declared there is no need for a sentinel marker, this also allows for zero-bytes to be used within the string. 1.1. Sometimes a variable-length integer is used, but that's an advanced technique.
  2. A sentinel marker value is used, typically the NULL '\0' character, e.g. 0x46 0x4F 0x4F 0x44 0x00.
  3. Or the file format specifies a string has a fixed length, in which case neither an in-band length declaration nor sentinel is required, though sometimes a specification will say that if a string's actual length is less than the fixed length, then null '\0' bytes may be used as padding.

Your question did not reference any specification which would hint as to which format you're using.

Note that if you just want to read an entire file into memory, you should use a memory-mapped file for better performance, though this requires platform support. You can do this with Boost: http://www.boost.org/doc/libs/1_50_0/libs/iostreams/doc/classes/mapped_file.html

If you still want to load the file into a buffer, you need to allocate a buffer large enough to contain the file, you won't want to use a statically-allocated buffer (new char[100] because it's inefficient if the file is less than 100 bytes big, and too small if it's more than 100 bytes.

If you're using ifstream then use the tellg() method to get the file length, then allocate a buffer for it:

using namespace std;

// ...

ifstream in( fileName, ifstream::ate | ifstream::binary );
streamsize length = in.tellg();
if( length <= 0 ) throw ...

size_t bufferLength = static_cast<size_t>( length );
char* buffer = new char[ bufferLength ];

in.read( buffer, bufferLength );

// do stuff with `buffer`

delete[] buffer;
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download