Как изменить данные в файле c
Обновлено: 21.11.2024
Данные хранятся в файлах, чтобы при необходимости их можно было извлечь для обработки. Команды для чтения данных из файла (по большей части) очень похожи на команды, используемые для чтения данных с клавиатуры. Однако здесь описаны некоторые важные различия.
Чтобы ваша программа могла читать из файла, вы должны:
- включить заголовочный файл fstream с помощью std::ifstream;
- объявить переменную типа ifstream
- открыть файл
- проверить наличие ошибки открытия файла
- читать из файла
- после каждого чтения проверять наличие конца файла с помощью функции-члена eof()
- закрыть файл, когда доступ больше не нужен (необязательно, но рекомендуется)
В этом примере переменная indata объявлена как тип ifstream. Он используется так же, как cin используется для ввода с клавиатуры. Оператор indata >> num; читает символы из файла и преобразует их в значение данных соответствующего типа — в данном случае целое число. При этом пробельные символы пропускаются; такое же действие происходит в случае чтения в переменную типа char, float или double. (Пробелы включают пробел, табуляцию, новую строку). Несколько значений могут быть прочитаны с использованием одного и того же оператора ввода. Например: данные >> число1 >> число2 >> число3;
При открытии файла всегда следует проверять его успешность, прежде чем продолжить. ! оператор для имени файла возвращает true, если файл не может быть открыт. Значение indata.eof() равно true, если самая последняя попытка чтения значения была неудачной (т. е. данных больше нет).
В следующем примере показано, как читать по одному символу за раз.
Приведенный выше пример считывает и отображает символы из файла до тех пор, пока не встретится буква Q, после чего программа останавливается. Обратите внимание, что пробелы (пробелы) пропускаются и не отображаются в выводе — фактически считываются только 6 символов.
В следующем примере показано, как прочитать всю строку с помощью оператора >>.
При чтении символьных значений в строковую переменную с помощью >> символы считываются до тех пор, пока не встретится пробел. Программист несет ответственность за то, чтобы строковая переменная была достаточно большой для хранения всех прочитанных символов. Таким образом, для INPUT1 символы 'ab123' считываются и сохраняются в переменном слове. Пробел между «3» и «5» завершает операцию чтения. Во втором примере программист допустил ошибку, так как в строке есть место только для 10 символов, но компьютер продолжил чтение до буквы «p». Фактический результат в этой ситуации будет зависеть от используемого компьютера.
В некоторых ситуациях желательно прочитать всю строку ввода, включая пробелы. Например: чтобы прочитать имя, такое как «Джо Студент», в одну строковую переменную. Это можно сделать с помощью функции-члена getline.
В этом примере функция getline будет считывать символы из файла, помещая их в слово массива, пока не будут прочитаны 9 символов (оставляя один пробел для символа NULL) или пока не будет прочитан разделитель '\n'. Если в строке более 9 символов, то эти «лишние» символы остаются во входном буфере. Если имеется 8 или менее символов, считывается вся строка, а разделитель удаляется из буфера. Обратите внимание, что если символов ровно 9, разделитель не удаляется из буфера.
Функция peek() используется для чтения одного символа из входного потока, оставляя символ в буфере. Символ будет прочитан со следующим оператором ввода. Функция putback() используется для возврата последнего прочитанного символа во входной поток.
В нашей прошлой статье мы объяснили, как добавить новые данные в файл на диске. В этом уроке мы объясним, как изменить данные существующего файла на диске. Для этого язык C предоставляет нам структуру под названием FILE, которая определена в заголовочном файле. Структура FILE позволяет нам создавать, читать, записывать/изменять файл на диске.
Структура FILE предоставляет нам функцию с именем fopen(), с помощью которой мы можем указать расположение файла, хранящегося на диске, а в ответ (если файл найден), функция fopen() открывает файл и дает нам указатель, который указывает либо на положение первого символа, либо на положение последнего символа в файле, в зависимости от режим, в котором мы открываем этот файл. Давайте прочитаем режим файла, используемый для изменения содержимого файла.
Синтаксис функции fopen()
Изменение содержимого файла в режиме r+
Теперь давайте попробуем записать и добавить данные в этот файл, взяв ввод из уже инициализированного массива char[]. Этот файл будет искаться в текущем каталоге (тот же каталог, куда мы идем для сохранения предстоящей программы C.).
Вывод
Выполнение этой программы прочитает файл с именем File2.txt в текущем каталоге и изменит его содержимое, например -
Анализ программы
Как видно из вывода кода, программа ищет файл с именем File2.txt в текущем каталоге, где хранится эта программа на C, и, если файл найден, считывает его содержимое и модифицирует его. Для этого -
- файл — указатель на объект ФАЙЛ.
- смещение — количество байтов для смещения от исходника.
- источник — позиция, от которой добавляется смещение.
Источник может принимать одно из следующих значений макроса:
В: Зачем использовать функцию fseek()?
Использование fseek() имеет первостепенное значение при работе с файлом в режиме r+, поскольку в этом режиме мы можем не только читать файл, но также изменять его старое содержимое и записывать новое содержимое. Следовательно, когда вы переключаетесь между режимами чтения, изменения и записи, вы должны использовать функцию позиционирования файла, fseek().
Как видите, я хочу отредактировать abc.txt таким образом, чтобы i заменялся в нем на a.
Программа работает нормально, но когда я открываю abc.txt извне, он кажется неотредактированным.
Возможная причина для этого?
Почему в этом случае символ после i не заменяется на a , как следует из ответов?
fgetc() возвращает int, а не char; он должен возвращать каждое допустимое значение char плюс отдельное значение, EOF. Как написано, вы не можете надежно обнаружить EOF. Если char является беззнаковым типом, вы никогда не найдете EOF; если char является знаковым типом, вы ошибочно идентифицируете какой-либо допустимый символ (часто ÿ, y-umlaut, U+00FF, СТРОЧНУЮ ЛАТИНСКУЮ БУКВУ Y С DIAERESIS) как EOF.
3 ответа 3
Анализ
Есть несколько проблем:
fgetc() возвращает int, а не char; он должен возвращать каждое допустимое значение char плюс отдельное значение, EOF. Как написано, вы не можете надежно обнаружить EOF. Если char является беззнаковым типом, вы никогда не найдете EOF; если char является знаковым типом, вы ошибочно идентифицируете какой-либо допустимый символ (часто ÿ, y-umlaut, U+00FF, СТРОЧНУЮ ЛАТИНСКУЮ БУКВУ Y С DIAERESIS) как EOF.
Если вы переключаетесь между вводом и выводом в файле, открытом для режима обновления, вы должны использовать операцию позиционирования файла ( fseek() , rewind() , номинально fsetpos() ) между чтением и записью; и вы должны использовать операцию позиционирования или fflush() между записью и чтением.
Рекомендуется закрывать то, что вы открываете (теперь это исправлено в коде).
Если бы ваша запись работала, вы бы перезаписали символ после i с помощью .
Синтез
Эти изменения приводят к:
Есть место для дополнительной проверки ошибок.
Экзегетика
Ввод, за которым следует вывод, требует поиска
fseek(ft, 0, SEEK_CUR); оператор требуется стандартом C.
ISO/IEC 9899:2011 §7.21.5.3 Функция fopen
¶7 Когда файл открывается в режиме обновления ('+' в качестве второго или третьего символа в приведенном выше списке значений аргумента режима), как ввод, так и вывод могут выполняться для связанного потока. Однако за выводом не должен непосредственно следовать ввод без промежуточного вызова функции fflush или функции позиционирования файла (fseek, fsetpos или rewind), а за вводом не должен непосредственно следовать вывод без промежуточного вызова функция позиционирования файла, если только операция ввода не встречает конец файла. Открытие (или создание) текстового файла в режиме обновления может вместо этого открыть (или создать) двоичный поток в некоторых реализациях.
< /цитата>fgetc() возвращает целое число
Цитаты из ISO/IEC 9899:2011, текущего стандарта C.
§7.21 Ввод/вывод
§7.21.1 Введение
EOF, который расширяется до целочисленного постоянного выражения с типом int и отрицательным значением, которое возвращается несколькими функциями для указания конца файла, т. е. прекращения ввода из потока;
§7.21.7.1 Функция fgetc
int fgetc(FILE *stream);
¶2 Если индикатор конца файла для входного потока, на который указывает stream, не установлен и присутствует следующий символ, функция fgetc получает этот символ как unsigned char, преобразованный в int, и продвигает ассоциированный индикатор позиции файла для потока (если он определен).
Возвращает
¶3 Если установлен индикатор конца файла для потока или если поток в конце файла устанавливается индикатор конца файла для потока, и функция fgetc возвращает EOF. В противном случае функция fgetc возвращает следующий символ из входного потока, на который указывает stream. Если возникает ошибка чтения, для потока устанавливается индикатор ошибки, и функция fgetc возвращает EOF. 289)
289) Конец файла и ошибку чтения можно отличить с помощью функций feof и ferror.
Итак, EOF — это отрицательное целое число (обычно это -1, но стандарт этого не требует). Функция fgetc() либо возвращает EOF, либо значение символа в виде беззнакового символа (в диапазоне от 0 до 0).UCHAR_MAX, обычно 0..255).
§6.2.5 Типы
¶3 Объект, объявленный как тип char, достаточно велик, чтобы хранить любой член базового набора символов выполнения. Если член базового набора символов выполнения хранится в объекте char, его значение гарантированно неотрицательно. Если любой другой символ хранится в объекте char, результирующее значение определяется реализацией, но должно находиться в пределах диапазона значений, которые могут быть представлены в этом типе.
¶5 Объект, объявленный как подписанный тип char занимает тот же объем памяти, что и ''простой'' объект char.
§6 Для каждого из целочисленных типов со знаком существует соответствующий (но другой) целочисленный тип без знака (обозначаемый ключевым словом unsigned ), который использует тот же объем памяти (включая информацию о знаках) и имеет те же требования к выравниванию.
§15 Три типа char , signed char и unsigned char вместе называются символьными типами. Реализация должна определить char так, чтобы он имел тот же диапазон, представление и поведение, что и подписанный char или unsigned char. 45)
45) CHAR_MIN , определенный в , будет иметь одно из значений 0 или SCHAR_MIN , и это можно использовать для различения двух параметров. Независимо от сделанного выбора, тип char отличается от двух других и не совместим ни с одним из них.
Это оправдывает мое утверждение о том, что обычный char может быть подписанным или неподписанным типом.
Если ваши данные действительно ASCII (7-битные данные), то все символы находятся в диапазоне 0..127, и вы не столкнетесь с проблемой неправильной интерпретации ÿ. Однако, если ваш тип char не имеет знака, у вас все еще есть проблема «не удается обнаружить EOF», поэтому ваша программа будет работать в течение длительного времени. Если вам нужно учитывать переносимость, вы примете это во внимание. Это проблемы профессионального уровня, с которыми вы должны справляться как программист на C. Вы можете относительно легко и без учета всех этих нюансов проложить себе путь к программам, которые работают на вашей системе для ваших данных. Но ваша программа не будет работать на чужих системах.
Язык C был разработан в 1970-х годах для операционной системы UNIX Деннисом Ритчи и Кеном Томпсоном. Это стандартный язык программирования, который был (и до сих пор остается) чрезвычайно популярным для широкого круга приложений, особенно во встраиваемых системах. Вы можете ознакомиться с этим курсом, который покажет вам, как создавать приложения для iOS с помощью C
Язык C актуален сегодня, потому что это родной язык для всех языков программирования — почти все современные языки программирования основаны на C. Надежная основа этого языка позволяет быстрее осваивать другие новые языки.
В сегодняшней статье мы покажем вам, как открыть файл в C и как вы можете использовать некоторые основные операции с файлами для чтения, изменения и записи файла. Вы должны иметь базовые практические знания C. Новичкам не нужно бояться. Этот специальный курс поможет вам быстро встать на ноги и научиться программировать на C.
Дескриптор файла в C
C позволяет обрабатывать большие блоки данных, которые могут быть числами, текстом или любой другой информацией, в виде файлов. C имеет специальные дескрипторы, используемые для указания на файлы, а также множество специально разработанных библиотечных функций для обработки практически любого возможного типа файловых транзакций. Чтобы получить доступ к файлу в C, вам нужно использовать дескриптор файла или указатель. Синтаксис для этого
Здесь начальное слово «Файл» указывает тип указателя, а file_ptr — это имя переменной указателя.
Открытие файла
Итак, теперь, когда у вас есть дескриптор файла, как на самом деле открыть файл? C имеет специальную библиотечную функцию «fopen», которая позволяет вам сделать это легко. Вот синтаксис
- char *filename: это имя файла, который вы хотите открыть, на простом английском языке. Скорее это указатель на символ, указывающий на имя файла, хранящегося в массиве символов.
- char *mode: это указатель строки C (опять же указатель символа), который определяет режим доступа к файлу. У вас есть довольно много вариантов режимов, которые позволяют вам выбрать способ открытия файла.
Обратите внимание, что здесь возвращаемое значение имеет тип «файл *». На самом деле это дескриптор файла, о котором мы говорили ранее. Вы должны безопасно сохранить этот дескриптор файла в переменной. Он понадобится вам для доступа к файлу для любых будущих операций чтения или записи.
Пример: открытие и запись в файл
В этом примере мы открываем файл «file1.txt», а затем используем функции fprintf для записи в этот файл. Обратите внимание, что мы должны передать этой функции дескриптор файла «file_ptr». Вот как он узнает, в какой файл записывать. Строки в двойных кавычках — это текст, который нужно записать в этот файл. Итак, что мы сделали в основном? Мы фактически создали файл «file1.txt» и вписали в него следующий текст
Чтобы узнать больше о таких функциях, как fprintf, вы можете ознакомиться с этим курсом C здесь.
Пример: открытие и чтение из файла
Что мы здесь сделали? Мы открываем файл «file1.txt», как в предыдущем примере. Затем в цикле while() мы читаем каждый символ из файла и выводим его на экран. Мы повторяем это, пока не дойдем до конца файла. Довольно просто, не так ли?
Другие операции с файлами
Как вы видели в приведенных выше примерах, в C есть множество других функций, которые вам понадобятся для чтения из файла или записи в файл. Давайте быстро пробежимся по наиболее полезным из них.
- Fclose(): это противоположность fopen(). Вы должны всегда вызывать это после того, как закончите работу с файлом, или, по крайней мере, когда вы выходите из своей программы. Если вы оставите дескриптор файла незакрытым, вы в конечном итоге съедите свою системную память.
- Fprintf(): вы, вероятно, помните обычную функцию printf(). Fprintf() — это скромный родственник, который вы должны использовать для записи в файлы.
- Fgetc() . Опять же, как и функция getc(), эта функция используется для получения или чтения символа из файла.
- Feof(): эта функция возвращает значение true, как только вы достигаете конца файла. Обратите внимание, что вы должны использовать это в цикле, чтобы фактически пройти файл до конца.
В этом руководстве мы рассмотрели только самые основные операции с файлами. Еще многое предстоит изучить. Вам, вероятно, следует посетить наш средний курс C и попробовать несколько примеров для себя!
В этом руководстве вы узнаете об обработке файлов в C. Вы научитесь обрабатывать стандартный ввод-вывод в C с помощью функций fprintf(), fscanf(), fread(), fwrite(), fseek() и т. д. помощь примеров.
Файл — это контейнер на компьютерных запоминающих устройствах, используемый для хранения данных.
Зачем нужны файлы?
- При завершении программы все данные теряются. Сохранение в файле сохранит ваши данные, даже если программа завершит работу.
- Если вам нужно ввести большое количество данных, ввод их всех займет много времени.
Однако, если у вас есть файл, содержащий все данные, вы можете легко получить доступ к содержимому файла с помощью нескольких команд на языке C. - Вы можете легко перенести свои данные с одного компьютера на другой без каких-либо изменений.
Типы файлов
При работе с файлами необходимо знать два типа файлов:
1. Текстовые файлы
Текстовые файлы — это обычные файлы .txt. Вы можете легко создавать текстовые файлы с помощью любых простых текстовых редакторов, таких как Блокнот.
Когда вы откроете эти файлы, вы увидите все содержимое файла в виде обычного текста. Вы можете легко редактировать или удалять содержимое.
Они требуют минимальных усилий для обслуживания, легко читаются, обеспечивают наименьшую безопасность и занимают больше места для хранения.
2. Бинарные файлы
Двоичные файлы — это в основном файлы .bin на вашем компьютере.
Вместо того, чтобы хранить данные в виде обычного текста, они хранят их в двоичной форме (0 и 1).
Они могут содержать больший объем данных, их нелегко читать, и они обеспечивают более высокий уровень безопасности, чем текстовые файлы.
Операции с файлами
В C вы можете выполнять четыре основные операции с файлами, текстовыми или двоичными:
- Создание нового файла
- Открытие существующего файла
- Закрытие файла
- Чтение и запись информации в файл
Работа с файлами
При работе с файлами необходимо объявить указатель типа файл. Это объявление необходимо для связи между файлом и программой.
Открытие файла — для создания и редактирования
Открытие файла выполняется с помощью функции fopen(), определенной в заголовочном файле stdio.h.
Синтаксис открытия файла в стандартном вводе-выводе:
- Предположим, что файл newprogram.txt не существует в папке E:\cprogram. Первая функция создает новый файл с именем newprogram.txt и открывает его для записи в соответствии с режимом 'w'.
Режим записи позволяет создавать и редактировать (перезаписывать) содержимое файла. - Теперь предположим, что второй двоичный файл oldprogram.bin существует в папке E:\cprogram. Вторая функция открывает существующий файл для чтения в бинарном режиме 'rb'.
Режим чтения позволяет только читать файл, вы не можете записывать в файл.
Закрытие файла
Файл (как текстовый, так и двоичный) должен быть закрыт после чтения/записи.
Закрытие файла выполняется с помощью функции fclose().
Здесь fptr — это указатель файла, связанный с файлом, который нужно закрыть.
Чтение и запись в текстовый файл
Для чтения и записи в текстовый файл мы используем функции fprintf() и fscanf().
Это просто версии файлов printf() и scanf() .Единственное отличие состоит в том, что fprintf() и fscanf() ожидают указатель на структуру FILE.
Пример 1. Запись в текстовый файл
Эта программа получает номер от пользователя и сохраняет его в файле program.txt .
После того, как вы скомпилируете и запустите эту программу, вы увидите текстовый файл program.txt, созданный на диске C вашего компьютера. Когда вы откроете файл, вы увидите введенное целое число.
Пример 2. Чтение из текстового файла
Эта программа считывает целое число из файла program.txt и выводит его на экран.
Если вы успешно создали файл из примера 1, запустив эту программу, вы получите введенное целое число.
Другие функции, такие как fgetchar() , fputc() и т. д., можно использовать аналогичным образом.
Чтение и запись в двоичный файл
Функции fread() и fwrite() используются для чтения и записи в файл на диске соответственно в случае двоичных файлов.
Запись в двоичный файл
Для записи в двоичный файл необходимо использовать функцию fwrite(). Функции принимают четыре аргумента:
- адрес данных для записи на диск
- размер данных для записи на диск
- количество таких данных
- указатель на файл, в который вы хотите записать.
Пример 3. Запись в двоичный файл с помощью fwrite()
В этой программе мы создаем новый файл program.bin на диске C.
Мы объявляем структуру threeNum с тремя числами — n1, n2 и n3 и определяем ее в основной функции как num.
Теперь внутри цикла for мы сохраняем значение в файле с помощью fwrite() .
Первый параметр принимает адрес num, а второй параметр принимает размер структуры threeNum .
Поскольку мы вставляем только один экземпляр num , третий параметр равен 1 . И последний параметр *fptr указывает на файл, в котором мы сохраняем данные.
Наконец, мы закрываем файл.
Чтение из двоичного файла
Функция fread() также принимает 4 аргумента, как и функция fwrite(), описанная выше.
Пример 4. Чтение из двоичного файла с помощью функции fread()
В этой программе вы читаете один и тот же файл program.bin и перебираете записи одну за другой.
Проще говоря, вы читаете одну запись threeNum размера threeNum из файла, на который указывает *fptr, в структуру num .
Вы получите те же записи, что и в примере 3.
Получение данных с помощью fseek()
Если у вас есть много записей в файле и вам нужно получить доступ к записи в определенной позиции, вам нужно пройтись по всем записям перед этим, чтобы получить запись.
Это приведет к потере большого количества памяти и рабочего времени. Более простой способ получить необходимые данные можно с помощью fseek() .
Как следует из названия, fseek() ищет курсор для данной записи в файле.
Синтаксис fseek()
Первый поток параметров — это указатель на файл. Второй параметр — это позиция искомой записи, а третий параметр указывает место, где начинается смещение.
Откуда | Значение |
---|---|
SEEK_SET | Начинает смещение с начала файла. |
SEEK_END | Начинает смещение от конца файла. |
SEEK_CUR | Начинает смещение от текущего положения курсора в файле. |