чтение файла windows; _stat возвращает неверное значение - PullRequest
0 голосов
/ 01 ноября 2011

В моей школе мне дали небольшую библиотеку для выполнения некоторых проектов. Библиотека была написана с учетом потребностей Linux, поэтому я пытаюсь изменить некоторые вещи для работы с моим компилятором MinGW. Одна конкретная программа предназначена для чтения файлов по URL. Мне пришлось изменить stat на _stat, чтобы он работал правильно. Открытие файла работает нормально, но _stat, похоже, возвращает неправильное значение. Я включу соответствующий код ниже:

#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());
}

Если вы хотите просмотреть всю библиотеку, вы можете получить их из здесь . Я понимаю, что код выглядит грубо; Я просто пытаюсь забить рабочую версию Windows. Эта вещь отлично работает в Linux; проблема заключается в том, что когда я читаю файл в Windows, размер равен 1 сокращению для каждой новой строки, которую я использую во входном файле, так что если у меня есть файл, который выглядит следующим образом:

 text

Работает нормально, но с:

text\r\n

Он ломается, и вывод выглядит так:

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

Это прерывается, потому что IsDone () ложно возвращает false (без каламбура), и программа пытается прочитать после конца файла. Любые предложения о том, почему _stat возвращает неправильный номер, когда есть новая строка?

Ответы [ 2 ]

2 голосов
/ 01 ноября 2011

То, что возвращается _stat, совершенно правильно.Windows использует «\ r \ n» для обозначения конца строки, но при открытии файла в текстовом режиме он будет преобразован в один символ новой строки при чтении потока.

Есливы хотите, чтобы поток, который вы читали, соответствовал внешней длине, вместо этого откройте файл в двоичном режиме.

Если вы простите мое высказывание, то, как только вы закончите с этим, мой совет будет бросить этозакодируйте код и измените свое имя, чтобы, если кто-то увидит ваш пост, он не обвинит вас в этом.Здесь у вас много кода, который, по крайней мере, мне кажется, делает простую задачу значительно более сложной и трудной.

1 голос
/ 01 ноября 2011

Похоже, вы должны открыть файл в двоичном режиме.Не знаю, зачем вам нужно использовать stat для чтения файла, а в версии кода для Windows вы вызываете _stat, а затем снова stat.

В Windows есть несколько способов сделать это.Мое личное предпочтение - использовать что-то вроде:

char strBuffer[1024];

FILE *fp = fopen (file,"rb");  // Binary read mode
while (!feof (fp))
   fread (strBuffer,1,sizeof (strBuffer),fp);

fclose (fp);
...