Функция unistd.h read (): Как читать файл построчно? - PullRequest
8 голосов
/ 27 февраля 2010

Что мне нужно сделать, это использовать функцию чтения из unistd.h, чтобы прочитать файл построчно. У меня есть на данный момент:

n = read(fd, str, size);

Однако, это читает до конца файла, или до размера числа байтов. Есть ли способ, чтобы я мог читать по одной строке за раз, останавливаясь на новой строке? Все строки имеют переменную длину.

Мне разрешены только эти два заголовочных файла:

#include <unistd.h>
#include <fcntl.h>

Смысл упражнения заключается в том, чтобы читать файл в строке построчно, и выводить каждую строку в том виде, в котором она прочитана. По сути, имитировать fgets () и функции fputs ().

Ответы [ 7 ]

7 голосов
/ 27 февраля 2010

Вы можете читать символ за символом в буфер и проверять наличие символов разрыва строки (\r\n для Windows и \n для систем Unix).

4 голосов
/ 27 февраля 2010

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

По сути, каждый раз, когда вас вызывают для новой строки, вы сканируете текущую позицию буфера в поисках маркера конца строки. Если вы найдете один, хорошо, это ваша линия. Обновите указатели буфера и верните.

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

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

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

1 голос
/ 26 июля 2010

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

Если вам действительно не нужно избегать превышения (что иногда важно, если вы хотите, чтобы другой процесс / программа унаследовал файловый дескриптор и были в состоянии взять чтение там, где вы остановились), я бы предложил использовать stdio функции или Ваша собственная система буферизации. Использование read для линейного или побайтового ввода-вывода очень болезненно и трудно сделать правильный выбор.

1 голос
/ 27 февраля 2010

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

0 голосов
/ 27 февраля 2010

Ну, он будет читать построчно с терминала.

Есть несколько вариантов:

  • Напишите функцию, которая использует чтение, когда у нее заканчиваются данные, но возвращает только одну строку за раз вызывающей стороне
  • Используйте функцию в библиотеке, которая делает именно это: fgets().
  • Читайте только один байт за раз, чтобы не заходить слишком далеко.
0 голосов
/ 27 февраля 2010

Если вы откроете файл в текстовом режиме, Windows "\ r \ n" будет автоматически переведена в "\ n" при чтении файла.

Если вы работаете в Unix, вы можете использовать нестандартную функцию 1 gcc 'getline ()'.


1 Функция getline () является стандартной в POSIX 2008.

0 голосов
/ 27 февраля 2010

Это хороший вопрос, но использование только функции чтения не помогает! : P

Зацикливайте вызовы чтения, чтобы получить фиксированное число байтов, и ищите символ '\ n', затем возвращайте часть строки (до '\ n') и сохраняйте остальные (кроме '\ n') перейти к следующему фрагменту файла символов.

Использовать динамическую память.

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

...

Или просто установите максимальную длину строки и используйте fgets, если вам нужно быстро ...

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