I was given a little library by my school to do some projects in. The library was written with linux in mind, so I’m trying to change some things to work with my MinGW compiler. One particular program is for reading files given a URL. I had to change stat to _stat to make it work properly. Opening a file works fine but _stat seems to return the incorrect value. I’ll include the relevant code below:
#ifdef WIN32
#define stat _stat
#endif
//return true if the number of chars read is the same as the file size
bool IsDone() const
{
cout << "checking if numRead " << numRead << " is fileSize " << fileSize << endl;
return (numRead == fileSize);
}
char Read()
{
if (IsDone())
throw IllegalStateException("stream is done");
else
{
char c;
file.get(c);
cout << "reading: " << c << endl;
if (file.fail())
throw FileException(std::string("error reading from file ") + fileName);
++numRead;
return c;
}
}
void OpenFile(string fileName)
{
struct stat buf;
#ifdef WIN32
if (_stat(fileName.c_str(), &buf) < 0){
switch (errno){
case ENOENT:
throw FileException(std::string("Could not find file ") + name);
case EINVAL:
throw FileException(std::string("Invalid parameter to _stat.\n"));
default:
/* Should never be reached. */
throw FileException(std::string("Unexpected error in _stat.\n"));
}
}
#else
if (stat(fileName.c_str(), &buf) < 0)
throw FileException(std::string("could not determine size of file ") + fileName);
#endif
fileSize = buf.st_size;
file.open(fileName.c_str());
}
If you would like to see the entire library, you can get them from here. I understand that the code is gross looking; I’m just trying to cludge a working windows version. This thing works fine on Linux; the problem is that when I read in a file on Windows, the size is 1 short for every newline that I use in the input file, so that if I have a file that looks like this:
text
It works fine, but with:
text\r\n
It breaks, and the output looks like this:
checking if numRead 0 is fileSize 6
checking if numRead 0 is fileSize 6
reading: t
checking if numRead 1 is fileSize 6
checking if numRead 1 is fileSize 6
reading: e
checking if numRead 2 is fileSize 6
checking if numRead 2 is fileSize 6
reading: x
checking if numRead 3 is fileSize 6
checking if numRead 3 is fileSize 6
reading: t
checking if numRead 4 is fileSize 6
checking if numRead 4 is fileSize 6
reading:
checking if numRead 5 is fileSize 6
checking if numRead 5 is fileSize 6
reading:
File Error: error reading from file H:/test/data/stuff.txt
It breaks because IsDone() falsely returns false (no pun intented), and the program tries to read past the end of the file. Any suggestions on why _stat is returning an incorrect number when there’s a newline?
What
_statis returning is quite correct. Windows uses “\r\n” to signal the end of a line, but when you open a file in text mode, that will be converted to a single new-line character as you read the stream.If you want the stream you read to match the external length, open the file in binary mode instead.
If you’ll pardon my saying so, once you’re done with that, my advice would be to throw this code away, and change your name so if somebody sees your post, they won’t blame you for it. What you have here is a lot of code that seems, at least to me, to make a simple task considerably more complex and difficult.