Ifstream читает неверные символы из текстового файла - PullRequest
2 голосов
/ 12 января 2012

У меня есть следующий простой код, который считывает содержимое текстового файла в массив символов:

const char* name = "test.txt";
std::cout << "Loading file " << name << std::endl;
std::ifstream file;
file.open(name);
file.seekg (0, std::ios::end);
int length = file.tellg();
std::cout << "Size: " << length << " bytes" << std::endl;
file.seekg (0, std::ios::beg);
char* buffer = new char[length];
file.read(buffer,length);
file.close();
std::cout.write(buffer,length);

Однако, кажется, если поток читает неправильное количество символов из файла: 1 дополнительный символ для каждоголиния.Я искал в Интернете, и похоже, что в текстовых файлах win7 есть символ возврата каретки (\ r) в дополнение к символу новой строки (\ n) в конце каждой строки.Тем не менее, поток почему-то не видит эти \ r, но все еще использует исходное количество символов в файле, считывая дополнительные байты за пределами конца файла.Можно ли как-то решить эту проблему?

Если это поможет: я использую компилятор MinGW и Windows 7 64bit.

Ответы [ 3 ]

6 голосов
/ 12 января 2012

Возможно, вы захотите открыть файл в двоичном режиме:

file.open(name, ios_base::in | ios_base::binary);

В противном случае стандартная библиотека переводит каждую новую строку Windows (CR + LF) в один \n для вас.1005 *

Это означает, что количество символов, которые вы можете прочитать из файла, не совпадает с размером файла.Когда вы вызываете read(), он читает столько символов, сколько может.Если он не может прочитать количество запрошенных вами символов, он устанавливает поток failbit.

0 голосов
/ 12 января 2012

Вы исходите из некоторых очень ошибочных (но широко распространенных) мнений. file.tellg() не возвращает int; возвращает реализацию определенный объект типа streampos, который должен быть типом класса, и может или не может быть преобразован в целочисленный тип. И если это конвертируемый в целочисленный тип (и я не знаю о реализации где это не так, даже если это не требуется), нет никакой гарантии, что полученное целое число представляет собой нечто большее, чем волшебное печенье, которое позволит повторно искать в той же позиции.

На практике это, вероятно, не является большой проблемой для современных машин: Unix и Windows возвращают смещение в байтах от начала файла. В случае Unix это работает нормально, потому что отображение внутреннее представление внешнему один к одному. В этом случае в Windows происходит переопределение концов строк: в текстовом файле строка Окончание представляет собой двухбайтовую последовательность 0x0D, 0x0A, которая становится, когда читается, один символ '\n'. А streampos (преобразовано в целочисленный тип) дает смещение в байтах, где вы должны искать в файле, а не количество символов, которое вы должны прочитать, чтобы добраться до этой позиции. Для вещей как то, что вы, кажется, делаете, это не проблема; выделенный буфер может быть немного больше, чем необходимо, но он никогда не будет слишком маленький.

Имейте в виду, что это не может быть правдой на мэйнфреймах. Исторически, в по крайней мере, мэйнфреймы использовали блочно-ориентированные файлы, а интегральное значение streampos может легко быть чем-то разбитым на поля с определенное количество бит для номера блока и другие биты для байта смещение в блоке. В зависимости от того, как они изложены в слове, буфер, выделенный как вы, может легко быть на несколько порядков слишком большое или если смещение размещено в старших битах, слишком мало.

Единственный надежный способ получить нужный вам размер буфера зависит от системы, и в некоторых системах (включая Windows) могут быть нет другого способа, кроме как читать все символы и считать их.

(Причина, по которой streampos должен быть тип класса, заключается в том, что исторически многие старые многобайтовые кодировки имели состояние кодирования; вы не может правильно декодировать персонаж, не зная, какие символы предшествовал этому. Так что streampos должен содержать два разных информация: позиция для поиска в файле и информация о это состояние. Я не думаю, что есть какие-либо зависящие от состояния многобайтовые однако сегодня широко используются кодировки.)

0 голосов
/ 12 января 2012

Читайте об открытии файлов для binary чтения (Google или см. здесь ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...