Juha Nieminen <nos...@thanks.invalid> writes:
>Luca Risolia <
luca.r...@studio.unibo.it> wrote:
>> int main(int argc, char** argv) {
>> ifstream f(argv[1], ifstream::in | ifstream::binary);
>> istreambuf_iterator<char > i(f), eof;
>> string s(i, eof);
>> cout << s;
>> }
>
>Note that this is not the fastest possible way of reading a large file
>because reading one byte at a time from a C++ stream is pretty slow.
>
>If maximum reading speed is required, the best compromise between speed
>and relative ease of usage is to use std::fread() instead. It would go
>something like this:
>
> std::FILE* inFile = std::fopen(argv[1], "rb");
> if(!inFile) { std::perror(argv[1]); return 1; }
> std::fseek(inFile, 0, SEEK_END);
> std::string s(std::ftell(inFile), ' ');
> std::rewind(inFile);
> std::fread(&s[0], 1, s.length(), inFile);
> std::fclose(inFile);
If I was really aiming for the fastest way to make an in-memory
string of a file, I'd use mmap:
int fd, diag;
struct stat st;
fd = ::open(argv[1], O_RDONLY, 0);
if (fd == -1) throw exception(errno);
diag = ::fstat(fd, &st);
if (diag == -1) { close (fd); throw exception(errno); }
void *base = ::mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, (off_t)0);
if (base == MAP_FAILED) { close(fd); throw exception(errno); }
So now, base points to the first byte of the string, which is st.st_size
bytes in length.
Unfortunatly, there is no std::string constructor that takes a pointer and length
and makes _it_ the string (rather than copy it).
This method will also defer the disk access until the page containing the string
is accessed for the first time, so for sparse access is much more efficient.
This method will not allow a string larger than the available virtual address
space (which is around 2GB or so on 32-bit systems, basically unlimited on 64-bit).
This method does not consume backing store (e.g. swap or paging file space).
There are equivalent API's (OpenFileMapping/MapViewOfFile) available for windows.
scott