Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

istream_iterator for raw bytes?

Started by scottdewald 11 replies 1.8k views
Original Post
scottdewald
scottdewald
Is there not a way to read the raw bytes of a file using an istream_iterator? I would like to be able to read the raw bytes, modify them, and then write them to another file. I tried this, but it skips white space

typedef unsigned char uchar_t;

vector<uchar_t> data;
ifstream in("in_file.txt", ios_base::in | ios_base::binary);
ofsteram out("out_file.txt", ios_base::out | ios_base::binary);

// read the raw bytes from the file
copy(istream_iterator<uchar_t>(in), istream_iterator<uchar_t>(), back_inserter(data));

// transform the raw bytes
transform(data.begin(), data.end(), data.begin(), some_func);

// write the raw bytes to another file
copy(data.begin(), data.end(), ostream_iterator<uchar_t>(out));

ToohrVyk
ToohrVyk
Initialize the vector to the size of the file and use istream::read to read the binary data in one sweep. It's faster, and requires less code.
scottdewald
scottdewald
Quote:
Original post by ToohrVyk
Initialize the vector to the size of the file and use istream::read to read the binary data in one sweep. It's faster, and requires less code.


istream::read() takes a char*, not a vector<T>::iterator
mldaalder
mldaalder
The following snippit is from this thread:
http://www.gamedev.net/community/forums/topic.asp?topic_id=355078


inline std::string loadtext(char * filename) {    std::ifstream fin(filename);    return std::string((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());}


I admit, it doesn't load it into a vector, but if I know my STL good enough, you shouldn't no problem replacing std::string with std::vector<char>
This function preserves whitespace and all the other bytes.
ToohrVyk
ToohrVyk
Quote:
Original post by scottdewald
Quote:
Original post by ToohrVyk
Initialize the vector to the size of the file and use istream::read to read the binary data in one sweep. It's faster, and requires less code.


istream::read() takes a char*, not a vector<T>::iterator


std::vector guarantees that its storage is contiguous. Therefore, you can use &(*vector.begin()) as an argument to istream::read() (applying any required reinterpret casting if the type of the vector is not compatible with char*).
scottdewald
scottdewald
mldaalder, that's it! Thank you sir.
scottdewald
scottdewald
Quote:
Original post by ToohrVyk
Quote:
Original post by scottdewald
Quote:
Original post by ToohrVyk
Initialize the vector to the size of the file and use istream::read to read the binary data in one sweep. It's faster, and requires less code.


istream::read() takes a char*, not a vector<T>::iterator


std::vector guarantees that its storage is contiguous. Therefore, you can use &(*vector.begin()) as an argument to istream::read() (applying any required reinterpret casting if the type of the vector is not compatible with char*).


I've always read that vector does not guarantee contiguous storage, however, most libraries implement it that way. If I am wrong, could you please point me to the section in the standard that states that it used contiguous memory?
raz0r
raz0r
Quote:

vector - standard library template providing contiguous storage, re-sizing and the useful push_back() functions for adding elements at the end. Vector is the default container. See also: map, multimap, list, deque. TC++PL 3.7.1, 16.3.

I think that this guy knows! =)
Bregma
Bregma
Quote:
Original post by scottdewald
Is there not a way to read the raw bytes of a file using an istream_iterator?


No. An istream is a formatter that lies on top of a stream. What you want is an istreambuf_iterator. That's just what it's designed for.
Stephen M. Webb
Professional Free Software Developer
ToohrVyk
ToohrVyk
Quote:
Original post by scottdewald
I've always read that vector does not guarantee contiguous storage, however, most libraries implement it that way. If I am wrong, could you please point me to the section in the standard that states that it used contiguous memory?


Quote:
23.2.4 [lib.container.adaptors], paragraph 1:
The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().


It's been there since the 2003 Technical Corrigendum.
scottdewald
scottdewald
Thanks for the clearing me up on vector being contiguous.

Are istreambuf_iterator's extremely slow? I ran some simple tests by reading in a file with istreambuf_iterator's and writing them out with ostream_iterator's vs. using fread() and fwrite() with a single char, and the latter was 5x faster. Is there any way to speed up iterators?
Zahlman
Zahlman
Check your compiler settings. If you're using (certain versions of) MSVC, iterators are "checked" by default, even in release mode, but you can disable that.
scottdewald
scottdewald
Quote:
Original post by Zahlman
Check your compiler settings. If you're using (certain versions of) MSVC, iterators are "checked" by default, even in release mode, but you can disable that.

Thanks. I didn't realize it, but with my compiler, I had to explicitly turn on inlining. After doing that and turning on optimizations (-O), I got much better performance.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.