Как вернуться в начало файла си
Операция чтения-записи всегда производится с текущей позиции в потоке. При открытии потока в режимах r и w указатель текущей позиции устанавливается на начальный байт потока. При открытии в режиме a указатель устанавливается на конец файла сразу за конечным байтом. И при выполнении операции чтения-записи указатель в потоке перемещается на новую позиции в соответствии с числом прочитанных или записанных байтов.
Однако вполне возможно, что нам потребуется считывать или записывать с какой-то определенной позиции в файле. Например, в айдиофайле в формате wav собственно звуковые данные расположены, начиная с 44 байта. И если, к примеру, мы хотим распознать звук из файла, что-то с ним сделать, то нам при считывании данных надо переместить указатель на соответствующую позицию.
В языке Си для управления позицией указателя в потоке применяется функция fseek() , которая имеет следующий синтаксис:
Второй параметр этой функции — смещение представляет числовое значение типа long , которое указывает, на какое количество байт надо переместить указатель. Это значение может быть отрицательным, если необходимо в потоке вернуться назад на некоторое количество байт.
Третий параметр — начало_отсчета задает начальную позицию, относительно которой идет смещение. В качестве этого параметра мы можем использовать одну из встроенных констант, определенных в файле stdio.h :
SEEK_SET : имеет значение 0 и представляет начало файла
SEEK_CUR : имеет значение 1 и представляет текущую позицию в потоке
SEEK_END : имеет значение 2 и представляет конец файла
Если перемещение указателя было успешно выполнено, то функция fseek() возвращает 0, иначе она возвращает ненулевое значение.
Кроме функции fseek() мы можем использовать для управления позицией указателя еще пару функций:
long ftell(FILE *) : получает текущую позицию указателя
void rewind(FILE *) : указатель устанавливается на начало потока
Применим функцию fseek в программе:
Здесь функция save() записывает в файл строку «Hello METANIT.COM!». Далее функция load() считывет данные из этой строки. Но считывает не сначала, а с позиции, которая передается через параметр position :
Поскольку третий аргумент равен SEEK_SET , то указатель файла смещается к байту с индексом position. Соответственно далее функция fgets() будет считывать данные не с самого начала файла, а с позиции position:
Поскольку в данном случае в качестве позиции передается число 6, то в тексте файла будут пропущены первые 6 символов, и будет считана подстрока «METANIT.COM!»
Считывание определенной структуры из файла
Рассмотрим более сложный пример:
С помощью функции save в файл сохраняется массив структур. Затем в функции load считываем одну из структур по введенному номеру.
Для поиска нужной структуры вычисляем позицию:
Исходя из записи мы знаем, что первые 4 байта в файле отводятся под хранение количества структур, соответственно при чтении нам надо пропустить эти 4 байта.
Например, мы хотим получить первую структуру. По формуле получаем (index-1) * n + 4 = 4. То есть первая структура будет располагаться после 4-го байта. Аналогично вторая структура будет располагаться после n+4 байт, где n — это размер структуры.
Получив позицию, передаем ее в функцию fseek() , перемещаемся в потоке и считываем после этого n байт.
При последующей операции чтения с помощью функции getc() :
эта функция будет считывать данные с позиции pos , по которой располагается структура с номером index.
Результат работы программы:
Стоит отметить, что для большей краткости здесь убрана проверка на наличие структуры по введенному номеру, так как пользователь может ввести число, которое превышает количество
Функция fseek
Функция fseek перемещает указатель позиции в потоке. Устанавливает внутренний указатель положения в файле, в новую позицию, которая определяются путем добавления смещения к исходному положению.
Внутренний индикатор конца файла EOF очищается после вызова этой функции, и все эффекты от предыдущих вызовов функции ungetc удаляются.
При использовании функции fseek в текстовых файлах со смещением на величину значения, отличного от нуля или значения, полученного функцией ftell , имейте в виду, что на некоторых платформах, в связи с нестандартным форматом преобразования текстовых файлов, может возникнуть ситуация с некорректного позиционирования указателя.
Для потоков, открытых в режиме обновления (чтения + записи), вызов функции fsetpos позволяет переключаться между режимами чтения и записи.
Параметры:
- filestream
Указатель на объект типа FILE , идентифицируемый поток. - offset
Количество байт для смещения, относительно некоторого положения указателя. - origin
Позиция указателя, относительно которой будет выполняться смещение. Такая позиция задаётся одной из следующих констант, определённых в заголовочном файле <cstdio> :
Возвращаемое значение
В случае успеха, функция возвращает нулевое значение.
В противном случае, она возвращает ненулевое значение.
С++ — Способы вернуться на начало файла, кроме input.seekg()
Какие есть способы вернуться на начало файла, кроме input.seekg(0, input.beg) ?
![]()
1) Вариация к Вашему коду (предпочитаю ios:: ):
2) Осуществлять побайтовый сдвиг назад до начала файла;
3) Закрыть и открыть файл заново;
Примечание: перед seekg() надо вроде сбросить состояние потока stream_fin.clear() , проверьте этот момент.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.3.11.43304
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
C Language
Файлы и потоки ввода-вывода
Модификации режима в fopen() и freopen() могут быть одним из следующих значений:
- "r" : открыть файл в режиме только для чтения, при этом курсор установлен в начало файла.
- "r+" : открыть файл в режиме чтения-записи, при этом курсор установлен в начало файла.
- "w" : открыть или создать файл в режиме только для записи, при этом его содержимое обрезается до 0 байтов. Курсор установлен в начало файла.
- "w+" : открыть или создать файл в режиме чтения-записи, при этом его содержимое обрезается до 0 байтов. Курсор установлен в начало файла.
- "a" : открыть или создать файл в режиме только записи, при этом курсор установлен в конец файла.
- "a+" : открыть или создать файл в режиме чтения-записи, при этом указатель чтения установлен в начало файла. Выход, однако, всегда будет добавлен в конец файла.
Каждый из этих файловых режимов может иметь b добавленный после начальной буквы (например, "rb" или "a+b" или "ab+" ). b означает, что файл следует рассматривать как двоичный файл вместо текстового файла в тех системах, где есть разница. Это не влияет на Unix-подобные системы; это важно для систем Windows. (Кроме того, Windows fopen позволяет явному t вместо b указывать «текстовый файл» и множество других параметров для конкретной платформы.)
- "wx" : создать текстовый файл в режиме только для записи. Файл может не существовать .
- "wbx" : создать двоичный файл в режиме только для записи. Файл может не существовать .
x , если присутствует, должен быть последним символом в строке режима.
Открыть и записать в файл
Эта программа открывает файл с именем, указанным в аргументе main, по output.txt для output.txt если аргумент не указан. Если файл с тем же именем уже существует, его содержимое отбрасывается, и файл рассматривается как новый пустой файл. Если файлы еще не существуют, создается вызов fopen() .
Если по какой-либо причине вызов fopen() завершился с ошибкой, он возвращает значение NULL и устанавливает значение глобальной переменной errno . Это означает, что программа может проверить возвращаемое значение после вызова fopen() и использовать perror() если fopen() терпит неудачу.
Если вызов fopen() завершается успешно, он возвращает действительный указатель FILE . Этот указатель затем может использоваться для ссылки на этот файл до тех пор, пока на нем не будет fclose() .
Функция fputs() записывает данный текст в открытый файл, заменяя любое предыдущее содержимое файла. Аналогично функции fopen() функция fputs() также устанавливает значение errno если она терпит неудачу, хотя в этом случае функция возвращает EOF для указания отказа (иначе он возвращает неотрицательное значение).
Функция fclose() сбрасывает любые буферы, закрывает файл и освобождает память, на которую указывает FILE * . Возвращаемое значение указывает на завершение так же, как и fputs() (хотя при успешном завершении возвращает «0»), снова также устанавливая значение errno в случае сбоя.
fprintf
Вы можете использовать fprintf в файле так же, как на консоли с printf . Например, чтобы отслеживать выигрыши игр, потери и связи, которые вы могли бы написать
Замечание: некоторые системы (печально, Windows) не используют то, что большинство программистов назвали бы «нормальными» окончаниями строк. Хотя UNIX-подобные системы используют \ n для завершения строк, Windows использует пару символов: \ r (возврат каретки) и \ n (строка). Эта последовательность обычно называется CRLF. Однако при использовании C вам не нужно беспокоиться об этих деталях, зависящих от платформы. AC-компилятор необходим для преобразования каждого экземпляра \ n в правильную конечную строку платформы. Поэтому компилятор Windows будет конвертировать \ n в \ r \ n, но компилятор UNIX сохранит его как есть.
Выполнить процесс
Эта программа запускает процесс ( netstat ) через popen() и считывает весь стандартный вывод процесса и выводит его на стандартный вывод.
Примечание: popen() не существует в стандартной библиотеке C , но это скорее часть POSIX C )
Получить строки из файла с помощью getline ()
Библиотека POSIX C определяет функцию getline() . Эта функция выделяет буфер для хранения содержимого строки и возвращает новую строку, количество символов в строке и размер буфера.
Пример программы, которая получает каждую строку из example.txt :
Входной файл example.txt
Выход
В этом примере getline() изначально вызывается без выделенного буфера. Во время этого первого вызова getline() выделяет буфер, считывает первую строку и помещает содержимое строки в новый буфер. При последующих вызовах getline() обновляет один и тот же буфер и перераспределяет буфер только тогда, когда он больше не достаточно большой, чтобы соответствовать всей строке. Затем временный буфер освобождается, когда мы закончили с файлом.
Другой вариант — getdelim() . Это то же самое, что и getline() за исключением указания символа окончания строки. Это необходимо, только если последний символ строки для вашего типа файла не является \ n. getline() работает даже с текстовыми файлами Windows, потому что с завершением многобайтовой строки ( "\r\n") '\ n'` по-прежнему остается последним символом в строке.
Пример реализации getline()
Открыть и записать в двоичный файл
Эта программа создает и записывает текст в двоичной форме через функцию fwrite в файл output.bin .
Если файл с тем же именем уже существует, его содержимое отбрасывается, и файл рассматривается как новый пустой файл.
Бинарный поток представляет собой упорядоченную последовательность символов, которая может прозрачно записывать внутренние данные. В этом режиме байты записываются между программой и файлом без какой-либо интерпретации.
Чтобы записывать целые числа переносимым образом, необходимо знать, ожидает ли формат файла их в формате большой или малой длины, а также размер (обычно 16, 32 или 64 бита). Бит-сдвиг и маскирование могут затем использоваться для записи байтов в правильном порядке. Целые числа в C не гарантируют наличие двух дополняющих представлений (хотя почти все реализации выполняются). К счастью, преобразование в беззнаковый гарантированно использовать двойки комплемента. Поэтому код для записи знакового целого в двоичный файл немного удивителен.
Другие функции следуют одному и тому же шаблону с незначительными изменениями для размера и порядка байтов.
fscanf ()
Предположим, у нас есть текстовый файл, и мы хотим прочитать все слова в этом файле, чтобы выполнить некоторые требования.
file.txt :
Это основная функция:
Чтение строк из файла
Заголовок stdio.h определяет функцию fgets() . Эта функция считывает строку из потока и сохраняет ее в указанной строке. Функция прекращает чтение текста из потока, когда считывается n — 1 символ, читается символ новой строки ( '\n' ) или заканчивается конец файла (EOF).
Вызов программы с аргументом, который представляет собой путь к файлу, содержащему следующий текст:
Результатом будет следующий вывод:
Этот очень простой пример позволяет фиксированную максимальную длину строки, так что более длинные строки будут эффективно считаться двумя строками. Функция fgets() требует, чтобы вызывающий код предоставлял память, которая будет использоваться в качестве адресата для прочитанной строки.
POSIX делает доступной функцию getline() которая вместо этого внутренне выделяет память, чтобы увеличить буфер, если необходимо, для линии любой длины (при условии, что имеется достаточная память).