Используя C ++, как мне прочитать строку определенной длины из недвоичного файла? - PullRequest
1 голос
/ 07 декабря 2009

Пример cplusplus.com для чтения текстовых файлов показывает, что строку можно прочитать с помощью функции getline. Тем не менее, я не хочу получить всю строку; Я хочу получить только определенное количество символов. Как это можно сделать таким образом, чтобы сохранить кодировку символов?

Мне нужна функция, которая делает что-то вроде этого:

ifstream fileStream;
fileStream.open("file.txt", ios::in);
resultStream << getstring(fileStream, 10); // read first 10 chars
file.ftell(10); // move to the next item
resultStream << getstring(fileStream, 10); // read 10 more chars

Я думал о чтении в буфер символов, но не изменит ли это кодировку символов?

Ответы [ 4 ]

5 голосов
/ 07 декабря 2009

Я действительно подозреваю, что здесь есть некоторая путаница в отношении термина "персонаж". Судя по вопросу OP, он использует термин «символ» для обозначения char (в отличие от логического «символа», такого как многобайтовый символ UTF-8), и, таким образом, для чтения из в текстовом файле термин «символ» взаимозаменяем с «байтом».

Если это так, вы можете прочитать определенное количество байтов с диска, используя ifstream::read(), например,

ifstream fileStream;
fileStream.open("file.txt", ios::in);
char buffer[1024];
fileStream.read(buffer, sizeof(buffer));

Чтение в буфер char не повлияет на кодировку символов вообще. Точная последовательность байтов, хранящихся на диске, будет скопирована в буфер.

Однако это другая история, если вы используете многобайтовый набор символов, где каждый символ имеет переменную длину. Если символы не имеют фиксированного размера, невозможно прочитать в точности N символов с диска при считывании с одного диска. Это не ограничение C ++, это просто реальность работы с блочными устройствами (дисками). На самых низких уровнях вашей ОС блочные устройства адресуются в терминах блоков, которые в свою очередь состоят из байтов. Таким образом, вы всегда можете прочитать точное число байтов с диска , но вы не можете прочитать точное количество логических символов с диска, если каждый символ не является фиксированным числом байтов. Для наборов символов, таких как UTF-8, где каждый символ имеет переменную длину, вам придется либо читать весь файл, либо выполнять умозрительные чтения и анализировать буфер чтения после каждого чтения, чтобы определить, нужно ли читать больше.

2 голосов
/ 07 декабря 2009

Сам C ++ не имеет концепции кодировки символов. char s всегда имеют одинаковый размер, как wchar_t s. Так что, если вам нужно прочитать X char s из многобайтового набора символов (например, utf-8), то вам придется либо читать (один байт) char за один раз (например, используя getchar() - или X char s, умозрительно, используя istream::getline()) и самостоятельно протестируйте сигналы MBCS или используйте стороннюю библиотеку для этого.

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

1 голос
/ 07 декабря 2009

Как уже упоминалось, стандартные библиотеки C / C ++ не предоставляют ничего, что работает выше уровня байтов. Поэтому, если вы хотите сделать это, используя только основные библиотеки, у вас нет готовой опции.

Что оставляет либо проверку, предоставляют ли выбранные вами платформы другую библиотеку, которая реализует эту возможность, либо написание собственного анализатора для обработки кодировок символов, либо перфорирование чего-то вроде "c ++ utf8 library" или "posix unicode" в Google и взглянем на то, что появляется.

Возможные интересные хиты:

Я оставлю дальнейшее расследование читателю.

0 голосов
/ 07 декабря 2009

Я думаю, что вы можете использовать функцию-член sgetn для связанных потоков streambuf ...

char buf [32]; streamsize i = fileStream.rdbuf () -> sgetn (& buf [0], 10);

Который будет читать 10 символов в буфер (если есть 10 доступных для чтения), возвращая количество прочитанных символов.

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