Читать файл построчно c

Обновлено: 21.11.2024

В этой статье я покажу вам, как читать текстовый файл построчно на C, используя стандартную функцию C fgets и функцию POSIX getline. В конце статьи я напишу переносимую реализацию функции getline, которую можно использовать с любым стандартным компилятором C.

Чтение файла построчно — тривиальная проблема во многих языках программирования, но не в C. Стандартный способ чтения строки текста в C — использование функции fgets, которая Хорошо, если вы заранее знаете, какой длины может быть строка текста.

Вы можете найти все примеры кода и входной файл в репозитории GitHub для этой статьи.

Давайте начнем с простого примера использования fgets для чтения фрагментов из текстового файла. :

Для тестирования кода я использовал простой фиктивный файл lorem.txt. Это фрагмент вывода вышеуказанной программы на моей машине:

Код печатает содержимое массива chunk, заполненное после каждого вызова fgets, и строку маркера.

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

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

Давайте начнем с создания буфера строк, в котором будут храниться фрагменты текста. Изначально он будет иметь ту же длину, что и массив chunk:

Далее мы собираемся добавить содержимое массива фрагментов в конец строки строки, пока не найдем символ конца строки. При необходимости изменим размер буфера строки:

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

Это результат выполнения приведенного выше кода на моей машине. Для краткости я оставил только первые строки вывода:

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

Давайте изменим приведенный выше код, чтобы напечатать длину строки вместо фактического текста:

Это результат запуска измененного кода на моей машине:

В следующем примере я покажу вам, как использовать функцию getline, доступную в системах POSIX, таких как Linux, Unix и macOS. В Microsoft Visual Studio нет эквивалентной функции, поэтому вы не сможете легко протестировать этот пример в системе Windows. Однако вы сможете протестировать его, если используете Cygwin или подсистему Windows для Linux.

Обратите внимание, насколько проще использовать getline POSIX по сравнению с ручной буферизацией фрагментов строки, как в моем предыдущем примере. К сожалению, стандартная библиотека C не включает эквивалентную функцию.

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

Это результат выполнения приведенного выше примера getline на компьютере с Linux:

Интересно отметить, что в этом конкретном случае функция getline в Linux изменяет размер строкового буфера до максимального размера 960 байт. Если вы запускаете тот же код в macOS, размер строкового буфера изменяется до 1024 байт. Это связано с различными способами реализации getline в разных Unix-подобных системах.

Как упоминалось ранее, getline отсутствует в стандартной библиотеке C. Было бы интересно реализовать портативную версию этой функции. Идея здесь не в том, чтобы реализовать самую производительную версию getline, а в том, чтобы реализовать простую замену для систем, отличных от POSIX.

Мы возьмем приведенный выше пример и заменим POSIX-версию getline нашей собственной реализацией, скажем, my_getline. Очевидно, что если вы работаете в системе POSIX, вам следует использовать версию, предоставленную операционной системой, которая была протестирована бесчисленным количеством пользователей и оптимизирована для достижения оптимальной производительности.

Поскольку ssize_t также является типом, определенным в POSIX, обычно представляет собой 64-битное целое число со знаком, вот как мы собираемся объявить нашу версию:

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

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

Приведенный выше код дает те же результаты, что и код, использующий функцию POSIX getline:

Я также протестировал код с помощью компилятора Microsoft C и получил идентичные результаты для того же входного файла.

Если вы хотите узнать больше о C99/C11, я бы порекомендовал прочитать 21st Century C: C Tips from the New School Бена Клеменса:

В этой статье объясняется несколько методов чтения файла построчно с помощью fscanf в C.

Используйте функцию fscanf для чтения файла построчно в C

Функция fscanf является частью утилит форматированного ввода стандартной библиотеки C. Для различных источников ввода предусмотрено несколько функций, таких как scanf для чтения из стандартного ввода, sscanf для чтения из строки символов и fscanf для чтения из потока указателя FILE. Последний можно использовать для чтения обычного файла построчно и сохранения их в буфере.

fscanf использует спецификацию форматирования, аналогичную спецификаторам printf, и все они подробно перечислены на этой странице. В следующем примере мы открываем образец входного файла с помощью вызова функции fopen и выделяем память полного размера файла для сохранения в нем потока чтения. Строка формата "%[^\n]" указана для чтения файлового потока до тех пор, пока не встретится символ новой строки. fscanf возвращает EOF, когда достигнут конец ввода; таким образом, мы повторяем цикл while и печатаем каждую строку одну за другой.

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

Используйте функцию fscanf для чтения файла слово за словом в C

Еще один полезный случай использования функции fscanf – это просмотр файла и анализ каждой лексемы, разделенной пробелами. Обратите внимание, что единственное, что нужно изменить по сравнению с предыдущим примером, — это спецификатор формата на "%[^\n ]" . Системный вызов stat предназначен для получения размера файла, и значение используется для передачи в качестве аргумента malloc для выделения буфера. Этот метод может быть расточительным для некоторых сценариев, но он гарантирует, что даже самые большие однострочные файлы могут быть сохранены в буфере.

Статьи DelftStack написаны такими же фанатами программного обеспечения, как и вы. Если вы также хотите внести свой вклад в DelftStack, написав платные статьи, вы можете посетить страницу «Написать для нас».

Файлы являются очень важной частью повседневной жизни программистов, пользователей компьютеров и студентов при работе в любой операционной системе. Эти файлы помогают нам сохранять наши данные в различных форматах с безопасностью и избыточностью. Поэтому сегодня в этом простом руководстве мы обсудим примеры C++ для чтения данных из файла построчно в системе Ubuntu 20.04. Начнем с открытия терминала оболочки в системе Ubuntu 20.04 с помощью сочетания клавиш «Ctrl+Alt+t». Консоль появится на вашем экране. После его открытия нам нужно установить компилятор C++ с именем «g++» в вашей системе, так как мы делаем наш код на языке C++. Для этого мы будем использовать пакет apt в нашей оболочке с командой установки системы Ubuntu 20.04. Название «g++» будет использоваться в конце этой команды, добавленной ниже. Мы добавили наш пароль sudo после выполнения команды для установки и настройки компилятора g++.

Для продолжения установки требуется наше подтверждение. Итак, мы ввели «y» и использовали клавишу Enter для продолжения.

Поскольку компилятор g++ установлен, мы готовы реализовать наши примеры.

Мы использовали запрос «touch» в оболочке командной строки для создания нового файла C++ в нашей системе Ubuntu 20.04. Имя файла было указано как «read.cc». Этот файл можно открыть в любом редакторе, чтобы добавить в него код C++. Эти редакторы включают текстовый, vim и наноредактор. Мы рекомендуем использовать редактор nano, так как его можно открыть в терминале. Итак, мы использовали команду «nano», чтобы открыть файл «read.cc» в редакторе nano.

Пример 01:

Итак, пустой файл будет развернут в редакторе GNU. Мы начали наш код с включения некоторых важных и необходимых заголовочных файлов. Файлы заголовков включают поток ввода-вывода, строку и заголовочные файлы файлового потока. Код будет запущен без пространства имен. Итак, мы запустили основной метод() первым. В нашем первом примере мы использовали уже созданный файл для чтения текста из него построчно.Ключевое слово «std» будет использоваться для использования стандартного ввода и вывода в коде.

Итак, входной файловый поток используется для чтения файла «new.txt» из домашнего каталога с использованием файлового объекта, т. е. ReadF. Переменная строкового типа объявляется с именем «данные», чтобы просто сохранить в нее текст файла после чтения. Теперь здесь используется цикл while для использования функции C++ getline(). Эта функция принимает два аргумента: объект «ReadF» и строковую переменную «data». Функция getline() будет считывать текст из файла new.txt и сохранять его в переменной «data», пока файл не станет пустым. Хотя это условие верно, мы использовали оператор «cout» для отображения данных файла в оболочке. Сохраним код с помощью «Ctrl+S» и используем сочетание клавиш «Ctrl+X» для выхода из редактора nano.

Давайте скомпилируем новый реализованный код в терминале с помощью компилятора «g++». После этого запустите файл с инструкцией «./a.out». Вывод показывает данные файла построчно на терминале.

Пример 02:

Наш первый пример полностью посвящен считыванию данных из файла построчно и их отображению в оболочке. На этом рисунке мы будем записывать данные в файл, а затем читать их построчно. Итак, мы обновили тот же код, открыв файл «read.cc». Добавлены заголовки и пространство имен. В методе main() мы использовали объект потока выходного файла, т. е. «WriteF», для записи данных в файл new.txt. Пользователь добавил данные в файл с помощью объекта WriteF. Здесь объект WriteF принимает от пользователя одну строку ввода. Объект WriteF будет закрыт, а «данные» объявлены. Объект потока входного файла, то есть ReadF, используется для чтения текста из файла new.txt построчно. Пока файл не пустой, он будет продолжать сохранять данные в переменной «data» из файлового объекта ReadF с помощью метода getline. Оператор cout отображает данные построчно в оболочке.

Наконец-то объект потока входных файлов ReadF был закрыт. На этом программа заканчивается. Итак, давайте выполним его.

Сначала скомпилируйте обновленный код с помощью компилятора g++, а затем выполните его. После выполнения мы получили однострочный вывод, поскольку пользователь записывает 1 строку в файл new.txt.

Пример 03:

Итак, вот наш последний, но не менее важный пример чтения данных из файла построчно. Итак, мы открыли тот же файл read.cc и обновили его код, как показано ниже. Итак, мы начали с включения необходимых заголовочных файлов, то есть iostream, string и fstream, для обработки файлов. Затем перед запуском основной функции использовалось пространство имен. Этот сценарий немного отличается от двух приведенных выше примеров кода. Мы объявили объект «Файл» заголовочного файла «fstream» в начале функции main(). Этот объект будет использоваться для открытия, записи, чтения и закрытия файла. Во-первых, мы использовали объектный файл, чтобы открыть файл «new.txt». Стандартный пакет «ios» определяет тип потока, т. е. входной или выходной.

Как видите, мы указали его как выходной поток. Ключевое слово «out» будет использоваться для записи в файл после его открытия, а ключевое слово «in» будет использоваться для чтения из файла. Таким образом, мы использовали оператор «if», чтобы проверить, открыл ли объект «Файл» конкретный файл или нет. Для этого используется функция «is_open». Если файл недействителен, объект потока файлов введет 5 строк в файл, как показано. После этого объект File закроет поток вывода. Теперь мы открыли тот же файл new.txt с объектом Stream «File» через объявление «ios::in». Оператор «if» используется здесь для определения того, свободен файл или нет. Если это так, то объявляется переменная строкового типа «данные». Функция getline() в цикле while будет получать данные из объекта File построчно и сохранять их в переменной «data». Эта переменная «данные» будет использоваться для отображения строк в оболочке. В конце концов, файловый объект закрывается.

После компиляции и запуска этого файла мы получили строки файла new.txt строка за строкой на нашем экране, как показано ниже.

Вывод:

Мы проделали огромную работу по теме C++: чтение файла построчно в системе Ubuntu 20.04. Мы начали с этого простого примера чтения данных из уже созданного текстового файла. В послесловии мы также увидели, как использовать обработку файлов для записи данных в файл, чтения их из него и отображения в оболочке. Надеемся, вам понравится.

Об авторе

Акса Ясин

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

Читайте также: