vectorchar to int

Started by
13 comments, last by jflanglois 19 years, 4 months ago
Alright, again this feels like a stupid question but I can't think of the right way to do it. I've got a vector<char> buffer, and I'm reading binary data into it from a file. This data is structured, some of it consisting of bytes, but other parts consisting of words and dwords. Whats the best way to read an int out of a particular point in this vector? For example:

vector<char> buffer;
unsigned int stringsize;

// file is read into the buffer here...

stringsize = buffer[28];
I know the last line is incorrect, but thats the sort of idea I'm trying to get at, I'm sure there's a better way to do it than something like this:

stringsize = (buffer[29] << 8) | buffer[28];
Advertisement
This should work for basic types on an x86, but don't assume it to be portable:

template<typename Type>const std::vector<char>& operator>>(const std::vector<char>& buf, Type& out){    out = (Type*)&vector.at(offset);    return buf;}void test(){    std::vector<char> buffer;    // fill the buffer    int value;    buffer >> value;}
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
Hmm. That seems almost as bad as doing it manually. And portability is a pretty high priority. Pointers are a definite option, since vectors are contiguous I could use it as a char array and interpret it as anything, but I was hoping to avoid that.

Also, pulling an int out of the vector was just one case, there are several other data types I need to pull out, such as strings (preferably std::string).

One option was to read it as a struct vector instead of char vector, but the data contains variable-length text strings, which makes that just as complex.

I suppose I could always do something like:

vector<char> buffer;int *data = &buffer[28];int value = *data;


But it seems very round-about. Is there no standard way of doing this?
I would suggest that you fill the appropriate variables when reading in your file, instead of reading it all to a vector and then trying to parse the vector.

You might also want to look at the section on settings in the Enginuity series here, if you don't like the previous suggestion.
[edit] What is it you are trying to do, exactly, before I send you in the wrong direction?

Note: joanusdmentia's code seems like it confuses istream and vector; it needs offset defined. Also, vector.at should read buf.at

Regards,
jflanglois

[Edited by - jflanglois on December 4, 2004 9:50:32 PM]
Reading individual values might be the best idea, I was just trying to minimize disk access.

What I'm doing right now is parsing zip files, reading the tables to locate the compressed file headers and read out the file info and names.
Quote:Original post by Nairou
Reading individual values might be the best idea, I was just trying to minimize disk access.


Don't try (not in this way, anyway); the stream object does this for you (by reading a "page" of the file at a time and maintaining an internal buffer).
What are you using to read you file? ifstream? CreateFile? fopen?
With ifstream, it would look like this:

#include <iostream>#include <fstream>using namespace std;int main() {  ifstream fin( "test.zip", ios::binary );  // Find the number of files in this record  fin.seekg( -22, ios_base::end );  // Find the begining of the central directory of this record  unsigned sig;  fin.read( reinterpret_cast < char * > ( &sig ), 4 );  while ( sig != 0x06054b50 ) {    fin.seekg( -5, ios_base::cur );    fin.read( reinterpret_cast < char * > ( &sig ), 4 );  }  // go to number of files  fin.seekg( 6, ios_base::cur );  // get number of files  short numfiles;  fin.read( reinterpret_cast < char * > ( &numfiles ), sizeof( numfiles ) );  // get length of name of first element  fin.seekg( 26 );  short strlength;  fin.read( reinterpret_cast < char * > ( &strlength ), sizeof( strlength ) );  // get name of first element  char *filename = new char[strlength + 1];  fin.seekg( 2, ios_base::cur );  fin.read( filename, strlength );  filename[strlength] = '\0';  cout << "First file: \"" << filename << "\"" << endl;  delete [] filename;  cin.get();  return 0;}


Output:
Quote:First file: "sorcerers.txt"


What spec are you using?
Quote:Original post by Zahlman
Quote:Original post by Nairou
Reading individual values might be the best idea, I was just trying to minimize disk access.


Don't try (not in this way, anyway); the stream object does this for you (by reading a "page" of the file at a time and maintaining an internal buffer).


I don't understand what you mean by this. The ifstream will keep a cursor on the file. How does that mean that it is not a good idea to read individual values from the file instead of the whole file to a buffer, and then trying to parse that?
Thanks jflanglois, that clears it up a lot. I'm using ifstream (via boost::filesystem), I just didn't want to assume the read calls were being buffered in advance. :)

I'm using the PKZip specs off the pkware site, and its all working well now. I went ahead and have it reading the bulk of the header directly into a struct now, then directly reading the variable parts (like filenames) as I need them afterwards.

You're welcome. That's the spec I used as well. Make sure you don't read the central directory for file headers because according to the site the CD can be compressed (unless of course you have code to decompress it).

This topic is closed to new replies.

Advertisement