Чтение до новой строки - PullRequest
       1

Чтение до новой строки

1 голос
/ 28 декабря 2010

Привет. Моя программа читает файл CSV.Поэтому я использовал fgets для чтения по одной строке за раз.Но теперь спецификация интерфейса говорит, что в нескольких столбцах можно найти символы NULL.Поэтому мне нужно заменить fgets другой функцией для чтения из файла. Есть предложения?

Ответы [ 3 ]

3 голосов
/ 28 декабря 2010

Если ваш текстовый поток имеет символ NUL (ascii 0), вам нужно обработать ваш файл как двоичный файл и использовать fread для чтения файла. Есть два подхода к этому.

  1. Считать весь файл в память. Длина файла может быть получена с помощью fseek(fp, 0, SEEK_END) и последующего вызова ftell. После этого вы можете выделить достаточно памяти для всего файла. Раз в памяти анализ файла должен быть относительно простым. Этот подход действительно подходит только для небольших файлов (возможно, не более 50 МБ). Для получения бонусных отметок посмотрите на функцию mmap.

  2. Чтение файла побайтно и добавление символов в буфер до тех пор, пока не будет найдена новая строка.

  3. Чтение и анализ по частям. Создайте буфер, который больше, чем ваша самая большая строка, и заполните его содержимым из вашего файла. Затем вы анализируете и извлекаете столько строк, сколько можете. Добавьте остаток в начало нового буфера и прочитайте следующий бит. Использование большего буфера поможет минимизировать копирование.

1 голос
/ 28 декабря 2010

fgets отлично работает со встроенными нулевыми байтами. Предварительно заполните ваш буфер \n (используя memset), а затем используйте memchr(buf, '\n', sizeof buf). Если memchr возвращает NULL, ваш буфер был слишком мал, и вам нужно увеличить его, чтобы прочитать оставшуюся часть строки. В противном случае вы можете определить, является ли найденная вами новая строка концом строки или заполнением, которым вы предварительно заполнили буфер, проверяя следующий байт. Если найденная вами новая строка находится в конце буфера или имеет другую новую строку сразу после нее, это от заполнения, а предыдущий байт - это нулевой терминатор, вставленный fgets (не нуль из файла). В противном случае найденная вами новая строка имеет нулевой байт после него (терминатор вставляется fgets, и это перевод строки в конце строки.

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

1 голос
/ 28 декабря 2010

используйте fread, а затем сканируйте блок на наличие разделителя

Проверьте функцию int T_fread(FILE *input) при http://www.mrx.net/c/source.html

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