I am trying to build a small opensource webserver and this bit of code works for big text files like http://norvig.com/big.txt but not for .mp3s / .flac / binary ( I tried sending "cat" )
std::ifstream file;file.open(filepath.c_str(), std::ifstream::binary | std::ios::in);
if(file.is_open() == true)
{
struct stat stat_buf;
int rc = stat(filepath.c_str(), &stat_buf);
long int a = stat_buf.st_size;
std::ostringstream tempLen;
tempLen << stat_buf.st_size;
setHeader("Content-Length", tempLen.str().c_str());
setHeader("Content-Type", getMimeType(filepath.c_str()));
long int chunkSize = 1024; // <1MB
do {
char *buffer = new char[chunkSize];
file.read(buffer, chunkSize - 1);
std::cout << "Chars in buffer: " std::string(buffer).length() << std::endl;
//send(buffer);
std::cout << "Chars read by ifstream: " << file.gcount() << "\n\n";
delete[] buffer;
} while(!file.eof());
file.close();
The output of this command is:
ACCESS [26/9/2014:0:14:44] Client requested using "GET" "/cat"
Chars in buffer: 7
Chars read by ifstream: 1023
Chars in buffer: 0
Chars read by ifstream: 1023
Chars in buffer: 1
Chars read by ifstream: 1023
Chars in buffer: 5
Chars read by ifstream: 1023
Chars in buffer: 12
Chars read by ifstream: 1023
Chars in buffer: 12
Chars read by ifstream: 1023
...
and so on.
std::string(buffer).length()
doesn't make sense for a buffer of binary data. The string object will only copy the data up to the first zero byte (since it considers that the be the null terminator of character data). Consequently, calling length
will only measure that portion of the data.
So your buffer has actually been filled with the amount of data indicated by gcount
. You just need to work with it in ways that are not string-based.
And, in addition to what the first answer has said, even with text files, it looks like your program's behavior is undefined. You are allocating a 1024-byte char buffer, and reading 1023 chars into it.
You are not guaranteed that the last character in the buffer is going to be '\0'. As such, even with text files, occasionally your new[]
operator might recycle some previously-used memory, have something else in the 1024th character, and std::string
's constructor will happily continue scanning ahead, until it finds a '\0' character, interpreting everything up to that point as a part of the file you're trying to copy.