Контакты

Работа с данными из файла c. Работа с текстовыми файлами. Чтение из двоичного файла и запись в него

Работа файлового ввода/вывода в C++ почти аналогична работе обычных (но с небольшими нюансами).

Классы файлового ввода/вывода

Есть три основных класса файлового ввода/вывода в C++ :

ofstream (является дочерним классу );

fstream (является дочерним классу iostream).

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

В отличие от потоков cout, cin, cerr и clog, которые сразу же можно использовать, файловые потоки должны быть явно установлены программистом. То есть, чтобы открыть файл для чтения и/или записи, нужно создать объект соответствующего класса файлового ввода/вывода, указав имя файла в качестве параметра. Затем, с помощью операторов вставки (<<) или извлечения (>>), можно записывать данные в файл или читать содержимое файла. После этого финал — нужно закрыть файл: явно вызвать метод close() или просто позволить файловой переменной ввода/вывода выйти из области видимости ( файлового класса ввода/вывода закроет этот файл автоматически вместо нас).

Файловый вывод

Для записи в файл используется класс ofstream . Например:

#include #include #include // для использования exit() int main() { using namespace std; // ofstream используется для записи данных в файл // Создаём файл SomeText.txt ofstream outf("SomeText.txt"); // Если мы не можем открыть этот файл для записи данных в него if (!outf) { // То выводим сообщение об ошибке и выполняем exit() cerr << "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } // Записываем в файл следующие две строчки outf << "See line #1!" << endl; outf << "See line #2!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#include

#include

#include // для использования exit()

int main ()

using namespace std ;

// ofstream используется для записи данных в файл

// Создаём файл SomeText.txt

ofstream outf ("SomeText.txt" ) ;

// Если мы не можем открыть этот файл для записи данных в него

if (! outf )

// То выводим сообщение об ошибке и выполняем exit()

cerr << << endl ;

exit (1 ) ;

// Записываем в файл следующие две строчки

outf << "See line #1!" << endl ;

outf << "See line #2!" << endl ;

return 0 ;

// Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл

Если вы загляните в каталог вашего проекта (ПКМ по вкладке с названием вашего.cpp файла в Visual Studio > «Открыть содержащую папку» ), то увидите файл с именем SomeText.txt, в котором находятся следующие строчки:

See line #1!
See line #2!

Обратите внимание, мы также можем использовать метод put() для записи одного символа в файл.

Файловый ввод

#include #include #include #include // для использования exit() int main() { using namespace std; // ifstream используется для чтения содержимого файла // Попытаемся прочитать содержимое файла SomeText.txt ifstream inf("SomeText.txt"); // Если мы не можем открыть этот файл для чтения его содержимого if (!inf) { cerr << "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть данные, которые мы можем прочитать while (inf) { // То перемещаем эти данные в строку, которую затем выводим на экран string strInput; inf >> strInput; cout << strInput << endl; } return 0; }

#include

#include

#include

#include // для использования exit()

int main ()

using namespace std ;

// ifstream используется для чтения содержимого файла

// Если мы не можем открыть этот файл для чтения его содержимого

if (! inf )

// То выводим следующее сообщение об ошибке и выполняем exit()

cerr << << endl ;

exit (1 ) ;

// Пока есть данные, которые мы можем прочитать

while (inf )

// То перемещаем эти данные в строку, которую затем выводим на экран

string strInput ;

inf >> strInput ;

cout << strInput << endl ;

return 0 ;

// Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл

See
line
#1!
See
line
#2!

Хм, это не совсем то, что мы хотели. Как мы уже знаем из предыдущих уроков, оператор извлечения работает с «отформатированными данными», т.е. он игнорирует все пробелы, символы табуляции и символ новой строки. Чтобы прочитать всё содержимое как есть, без его разбивки на части (как в примере выше), нам нужно использовать метод getline() :

#include #include #include #include // для использования exit() int main() { using namespace std; // ifstream используется для чтения содержимого файлов // Мы попытаемся прочитать содержимое файла SomeText.txt ifstream inf("SomeText.txt"); // Если мы не можем открыть файл для чтения его содержимого if (!inf) { // То выводим следующее сообщение об ошибке и выполняем exit() cerr << "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть, что читать while (inf) { // То перемещаем то, что можем прочитать, в строку, а затем выводим эту строку на экран string strInput; getline(inf, strInput); cout << strInput << endl; } return 0; // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл }

#include

#include

#include

#include // для использования exit()

int main ()

using namespace std ;

// ifstream используется для чтения содержимого файлов

ifstream inf ("SomeText.txt" ) ;

// Если мы не можем открыть файл для чтения его содержимого

if (! inf )

// То выводим следующее сообщение об ошибке и выполняем exit()

cerr << "Uh oh, SomeText.txt could not be opened for reading!" << endl ;

exit (1 ) ;

while (inf )

string strInput ;

getline (inf , strInput ) ;

cout << strInput << endl ;

return 0 ;

// Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл

Результат выполнения программы выше:

Буферизованный вывод

Вывод в C++ может быть буферизован. Это означает, что всё, что выводится в файловый поток, не может сразу же быть записанным на диск (в конкретный файл). Это сделано, в первую очередь, по соображениям производительности. Когда данные буфера записываются на диск, то это называется очисткой буфера . Одним из способов очистки буфера является закрытие файла. В таком случае всё содержимое буфера будет перемещено на диск, а затем файл будет закрыт.

Буферизация вывода обычно не является проблемой, но, при определённых обстоятельствах, она может вызвать проблемы у неосторожных новичков. Например, когда в буфере хранятся данные и программа преждевременно завершает своё выполнение (либо в результате сбоя, либо путём вызова ). В таких случаях деструкторы классов файлового ввода/вывода не выполняются, файлы никогда не закрываются, буферы не очищаются и наши данные теряются навсегда. Вот почему хорошей идеей является явное закрытие всех открытых файлов перед вызовом exit().

Также буфер можно очистить вручную, используя метод ostream::flush() или отправив std::flush в выходной поток. Любой из этих способов может быть полезен для обеспечения немедленной записи содержимого буфера на диск в случае сбоя программы.

Интересный нюанс : Поскольку std::endl; также очищает выходной поток, то его чрезмерное использование (приводящее к ненужным очисткам буфера) может повлиять на производительность программы (так как очистка буфера в некоторых случаях может быть затратной операцией). По этой причине программисты, которые заботятся о производительности своего кода, часто используют \n вместо std::endl для вставки символа новой строки в выходной поток, дабы избежать ненужной очистки буфера.

Режимы открытия файлов

Что произойдёт, если мы попытаемся записать данные в уже существующий файл? Повторный запуск программы выше (самая первая) показывает, что исходный файл полностью перезаписывается при повторном запуске программы. А что, если нам нужно добавить данные в конец файла? Оказывается, файлового потока принимают необязательный второй параметр, который позволяет указать программисту способ открытия файла. В качестве этого параметра можно передавать следующие флаги (которые находятся в классе ios):

app - открывает файл в режиме добавления;

ate - переходит в конец файла перед чтением/записью;

binary - открывает файл в бинарном режиме (вместо текстового режима);

in - открывает файл в режиме чтения (по умолчанию для ifstream);

out - открывает файл в режиме записи (по умолчанию для ofstream);

trunc - удаляет файл, если он уже существует.

Можно указать сразу несколько флагов путём использования .

ifstream по умолчанию работает в режиме ios::in;

ofstream по умолчанию работает в режиме ios::out;

fstream по умолчанию работает в режиме ios::in ИЛИ ios::out, что означает, что вы можете выполнять как чтение содержимого файла, так и запись данных в файл.

Теперь давайте напишем программу, которая добавит две строки в ранее созданный файл SomeText.txt:

#include #include // для использования exit() #include int main() { using namespace std; // Передаём флаг ios:app, чтобы сообщить fstream, что мы собираемся добавить свои данные к уже существующим данным файла, // мы не собираемся перезаписывать файл. Нам не нужно передавать флаг ios::out, // поскольку ofstream по умолчанию работает в режиме ios::out ofstream outf("SomeText.txt", ios::app); // Если мы не можем открыть файл для записи данных if (!outf) { // То выводим следующее сообщение об ошибке и выполняем exit() cerr << "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } outf << "See line #3!" << endl; outf << "See line #4!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#include

#include // для использования exit()

#include

int main ()

using namespace std ;

// Передаём флаг ios:app, чтобы сообщить fstream, что мы собираемся добавить свои данные к уже существующим данным файла,

// мы не собираемся перезаписывать файл. Нам не нужно передавать флаг ios::out,

// поскольку ofstream по умолчанию работает в режиме ios::out

ofstream outf ("SomeText.txt" , ios :: app ) ;

// Если мы не можем открыть файл для записи данных

if (! outf )

// То выводим следующее сообщение об ошибке и выполняем exit()

cerr << "Uh oh, SomeText.txt could not be opened for writing!" << endl ;

exit (1 ) ;

Файлы позволяют пользователю считывать большие объемы данных непосредственно с диска, не вводя их с клавиатуры. Существуют два основных типа файлов: текстовые и двоичные .

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

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

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

В программах на C++ при работе с текстовыми файлами необходимо подключать библиотеки iostream и fstream .

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

  1. описать переменную типа ofstream .
  2. open .
  3. вывести информацию в файл.
  4. обязательно закрыть файл.

Для считывания данных из текстового файла, необходимо:

  1. описать переменную типа ifstream .
  2. открыть файл с помощью функции open .
  3. считать информацию из файла, при считывании каждой порции данных необходимо проверять, достигнут ли конец файла.
  4. закрыть файл.

Запись информации в текстовый файл

Как было сказано ранее, для того чтобы начать работать с текстовым файлом, необходимо описать переменную типа ofstream . Например, так:

ofstream F;

Будет создана переменная F для записи информации в файл. На следующим этапе файл необходимо открыть для записи. В общем случае оператор открытия потока будет иметь вид:

F .open («file» , mode );

Здесь F - переменная, описанная как ofstream , file - полное имя файла на диске, mode - режим работы с открываемым файлом. Обратите внимание на то, что при указании полного имени файла нужно ставить двойной слеш. Для обращения, например к файлу accounts.txt, находящемуся в папке sites на диске D , в программе необходимо указать: D:\\sites\\accounts .txt .

Файл может быть открыт в одном из следующих режимов:

  • ios::in - открыть файл в режиме чтения данных; режим является режимом по умолчанию для потоков ifstream ;
  • ios::out - открыть файл в режиме записи данных (при этом информация о существующем файле уничтожается); режим является режимом по умолчанию для потоков ofstream ;
  • ios::app - открыть файл в режиме записи данных в конец файла;
  • ios::ate - передвинуться в конец уже открытого файла;
  • ios::trunc - очистить файл, это же происходит в режиме ios::out;
  • ios::nocreate - не выполнять операцию открытия файла, если он не существует;
  • ios::noreplace - не открывать существующий файл.

Параметр mode может отсутствовать, в этом случае файл открывается в режиме по умолчанию для данного потока.

После удачного открытия файла (в любом режиме) в переменной F будет храниться true , в противном случае false . Это позволит проверить корректность операции открытия файла.

Открыть файл (в качестве примера возьмем файл D:\\sites\\accounts .txt ) в режиме записи можно одним из следующих способов:

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

Если вы хотите открыть существующий файл в режиме дозаписи, то в качестве режима следует использовать значение ios::app .

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

Например, для записи в поток F переменной a , оператор вывода будет иметь вид:

F<

Для последовательного вывода в поток G переменных b , c , d оператор вывода станет таким:

G<

Закрытие потока осуществляется с помощью оператора:

F.close();

В качестве примера рассмотрим следующую задачу.

Задача 1

Создать текстовый файл D:\\sites \\accounts .txt и записать в него n вещественных чисел.

Решение

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include «stdafx.h»
#include
#include
#include
using namespace std;
int main()
{

int i, n;
double a;
//описывает поток для записи данных в файл
ofstream f;
//открываем файл в режиме записи,
//режим ios::out устанавливается по умолчанию
f.open («D:\\ sites\\ accounts.txt» , ios:: out ) ;
//вводим количество вещественных чисел
cout << «n=» ; cin >> n;
//цикл для ввода вещественных чисел
//и записи их в файл
for (i= 0 ; i< n; i++ )
{
cout << «a=» ;
//ввод числа
cin >> a;
f<< a<< «\t « ;
}
//закрытие потока
f.close () ;
system («pause» ) ;
return 0 ;
}

Чтение информации из текстового файла

Для того чтобы прочитать информацию из текстового файла, необходимо описать переменную типа ifstream . После этого нужно открыть файл для чтения с помощью оператора open . Если переменную назвать F , то первые два оператора будут такими:

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

Например, для чтения данных из потока F в переменную a , оператор ввода будет выглядеть так:

F>>a;

Два числа в текстовом редакторе считаются разделенными, если между ними есть хотя бы один из символов: пробел, табуляция, символ конца строки. Хорошо, когда программисту заранее известно, сколько и какие значения хранятся в текстовом файле. Однако часто известен лишь тип значений, хранящихся в файле, при этом их количество может быть различным. Для решения данной проблемы необходимо считывать значения из файла поочередно, а перед каждым считыванием проверять, достигнут ли конец файла. А поможет сделать это функция F.eof() . Здесь F - имя потока функция возвращает логическое значение: true или false , в зависимости от того достигнут ли конец файла.

Следовательно, цикл для чтения содержимого всего файла можно записать так:

Для лучшего усвоения материала рассмотрим задачу.

Задача 2

В текстовом файле D:\\game\\accounts.txt хранятся вещественные числа, вывести их на экран и вычислить их количество.

Решение

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include «stdafx.h»
#include
#include
#include
#include
using namespace std;
int main()
{
setlocale (LC_ALL, «RUS» ) ;
int n= 0 ;
float a;
fstream F;
//открываем файл в режиме чтения
F.open («D:\\ sites\\ accounts.txt» ) ;
//если открытие файла прошло корректно, то
if (F)
{
//цикл для чтения значений из файла; выполнение цикла прервется,
//когда достигнем конца файла, в этом случае F.eof() вернет истину.
while (! F.eof () )
{
//чтение очередного значения из потока F в переменную a
F>> a;
//вывод значения переменной a на экран
cout << a<< «\t « ;
//увеличение количества считанных чисел
n++ ;
}
//закрытие потока
F.close () ;
//вовод на экран количества считанных чисел
cout << «n=» << n<< endl;
}
//если открытие файла прошло некорректно, то вывод
//сообщения об отсутствии такого файла
else cout << » Файл не существует» << endl;
system («pause» ) ;
return 0 ;
}

На этом относительно объемный урок по текстовым файлам закончен. В следующей статье будут рассмотрены методы манипуляции, при помощи которых в C++ обрабатываются .

Последнее обновление: 31.10.2015

Для работы с каталогами в пространстве имен System.IO предназначены сразу два класса: Directory и DirectoryInfo .

Класс Directory

Класс Directory предоставляет ряд статических методов для управления каталогами. Некоторые из этих методов:

    CreateDirectory(path) : создает каталог по указанному пути path

    Delete(path) : удаляет каталог по указанному пути path

    Exists(path) : определяет, существует ли каталог по указанному пути path. Если существует, возвращается true , если не существует, то false

    GetDirectories(path) : получает список каталогов в каталоге path

    GetFiles(path) : получает список файлов в каталоге path

    Move(sourceDirName, destDirName) : перемещает каталог

    GetParent(path) : получение родительского каталога

Класс DirectoryInfo

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

    Create() : создает каталог

    CreateSubdirectory(path) : создает подкаталог по указанному пути path

    Delete() : удаляет каталог

    Свойство Exists : определяет, существует ли каталог

    GetDirectories() : получает список каталогов

    GetFiles() : получает список файлов

    MoveTo(destDirName) : перемещает каталог

    Свойство Parent : получение родительского каталога

    Свойство Root : получение корневого каталога

Посмотрим на примерах применение этих классов

Получение списка файлов и подкаталогов

string dirName = "C:\\"; if (Directory.Exists(dirName)) { Console.WriteLine("Подкаталоги:"); string dirs = Directory.GetDirectories(dirName); foreach (string s in dirs) { Console.WriteLine(s); } Console.WriteLine(); Console.WriteLine("Файлы:"); string files = Directory.GetFiles(dirName); foreach (string s in files) { Console.WriteLine(s); } }

Обратите внимание на использование слешей в именах файлов. Либо мы используем двойной слеш: "C:\\" , либо одинарный, но тогда перед всем путем ставим знак @: @"C:\Program Files"

Создание каталога

string path = @"C:\SomeDir"; string subpath = @"program\avalon"; DirectoryInfo dirInfo = new DirectoryInfo(path); if (!dirInfo.Exists) { dirInfo.Create(); } dirInfo.CreateSubdirectory(subpath);

Вначале проверяем, а нету ли такой директории, так как если она существует, то ее создать будет нельзя, и приложение выбросит ошибку. В итоге у нас получится следующий путь: "C:\SomeDir\program\avalon"

Получение информации о каталоге

string dirName = "C:\\Program Files"; DirectoryInfo dirInfo = new DirectoryInfo(dirName); Console.WriteLine($"Название каталога: {dirInfo.Name}"); Console.WriteLine($"Полное название каталога: {dirInfo.FullName}"); Console.WriteLine($"Время создания каталога: {dirInfo.CreationTime}"); Console.WriteLine($"Корневой каталог: {dirInfo.Root}");

Удаление каталога

Если мы просто применим метод Delete к непустой папке, в которой есть какие-нибудь файлы или подкаталоги, то приложение нам выбросит ошибку. Поэтому нам надо передать в метод Delete дополнительный параметр булевого типа, который укажет, что папку надо удалять со всем содержимым:

String dirName = @"C:\SomeFolder"; try { DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Каталог удален"); } catch (Exception ex) { Console.WriteLine(ex.Message); }

String dirName = @"C:\SomeFolder"; Directory.Delete(dirName, true);

Перемещение каталога

string oldPath = @"C:\SomeFolder"; string newPath = @"C:\SomeDir"; DirectoryInfo dirInfo = new DirectoryInfo(oldPath); if (dirInfo.Exists && Directory.Exists(newPath) == false) { dirInfo.MoveTo(newPath); }

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

Для удобства обращения информация в запоминающих устройствах хранится в виде файлов.

Файл – именованная область внешней памяти, выделенная для хранения массива данных. Данные, содержащиеся в файлах, имеют самый разнообразный характер: программы на алгоритмическом или машинном языке; исходные данные для работы программ или результаты выполнения программ; произвольные тексты; графические изображения и т. п.

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

Файловой системой называется функциональная часть операционной системы, обеспечивающая выполнение операций над файлами. Примерами файловых систем являются FAT (FAT – File Allocation Table, таблица размещения файлов), NTFS, UDF (используется на компакт-дисках).

Существуют три основные версии FAT: FAT12, FAT16 и FAT32. Они отличаются разрядностью записей в дисковой структуре, т.е. количеством бит, отведённых для хранения номера кластера. FAT12 применяется в основном для дискет (до 4 кбайт), FAT16 – для дисков малого объёма, FAT32 – для FLASH-накопителей большой емкости (до 32 Гбайт).

Рассмотрим структуру файловой системы на примере FAT32.

Файловая структура FAT32

Устройства внешней памяти в системе FAT32 имеют не байтовую, а блочную адресацию. Запись информации в устройство внешней памяти осуществляется блоками или секторами.

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

Кластер – объединение нескольких секторов, которое может рассматриваться как самостоятельная единица, обладающая определёнными свойствами. Основным свойством кластера является его размер, измеряемый в количестве секторов или количестве байт.

Файловая система FAT32 имеет следующую структуру.

Нумерация кластеров, используемых для записи файлов, ведется с 2. Как правило, кластер №2 используется корневым каталогом, а начиная с кластера №3 хранится массив данных. Сектора, используемые для хранения информации, представленной выше корневого каталога, в кластеры не объединяются.
Минимальный размер файла, занимаемый на диске, соответствует 1 кластеру.

Загрузочный сектор начинается следующей информацией:

  • EB 58 90 – безусловный переход и сигнатура;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 – количество байт в секторе (обычно 512);
  • 1 байт – количество секторов в кластере;
  • 2 байта – количество резервных секторов.

Кроме того, загрузочный сектор содержит следующую важную информацию:

  • 0x10 (1 байт) – количество таблиц FAT (обычно 2);
  • 0x20 (4 байта) – количество секторов на диске;
  • 0x2С (4 байта) – номер кластера корневого каталога;
  • 0x47 (11 байт) – метка тома;
  • 0x1FE (2 байта) – сигнатура загрузочного сектора (55 AA ).

Сектор информации файловой системы содержит:

  • 0x00 (4 байта) – сигнатура (52 52 61 41 );
  • 0x1E4 (4 байта) – сигнатура (72 72 41 61 );
  • 0x1E8 (4 байта) – количество свободных кластеров, -1 если не известно;
  • 0x1EС (4 байта) – номер последнего записанного кластера;
  • 0x1FE (2 байта) – сигнатура (55 AA ).

Таблица FAT содержит информацию о состоянии каждого кластера на диске. Младшие 2 байт таблицы FAT хранят F8 FF FF 0F FF FF FF FF (что соответствует состоянию кластеров 0 и 1, физически отсутствующих). Далее состояние каждого кластера содержит номер кластера, в котором продолжается текущий файл или следующую информацию:

  • 00 00 00 00 – кластер свободен;
  • FF FF FF 0F – конец текущего файла.
  • 8 байт – имя файла;
  • 3 байта – расширение файла;

Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:

В случае работы с длинными именами файлов (включая русские имена) кодировка имени файла производится в системе кодировки UTF-16. При этого для кодирования каждого символа отводится 2 байта. При этом имя файла записывается в виде следующей структуры:

  • 1 байт последовательности;
  • 10 байт содержат младшие 5 символов имени файла;
  • 1 байт атрибут;
  • 1 байт резервный;
  • 1 байт – контрольная сумма имени DOS;
  • 12 байт содержат младшие 3 символа имени файла;
  • 2 байта – номер первого кластера;
  • остальные символы длинного имени.

Работа с файлами в языке Си

Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода . Выводимая информация записывается в поток, вводимая информация считывается из потока.

Когда поток открывается для ввода-вывода, он связывается со стандартной структурой типа FILE , которая определена в stdio.h . Структура FILE содержит необходимую информацию о файле.

Открытие файла осуществляется с помощью функции fopen() , которая возвращает указатель на структуру типа FILE , который можно использовать для последующих операций с файлом.

FILE *fopen(name, type);


name – имя открываемого файла (включая путь),
type — указатель на строку символов, определяющих способ доступа к файлу:
  • "r" - открыть файл для чтения (файл должен существовать);
  • "w" - открыть пустой файл для записи; если файл существует, то его содержимое теряется;
  • "a" - открыть файл для записи в конец (для добавления); файл создается, если он не существует;
  • "r+" - открыть файл для чтения и записи (файл должен существовать);
  • "w+" - открыть пустой файл для чтения и записи; если файл существует, то его содержимое теряется;
  • "a+" - открыть файл для чтения и дополнения, если файл не существует, то он создаётся.

Возвращаемое значение — указатель на открытый поток. Если обнаружена ошибка, то возвращается значение NULL .

Функция fclose() закрывает поток или потоки, связанные с открытыми при помощи функции fopen() файлами. Закрываемый поток определяется аргументом функции fclose() .

Возвращаемое значение: значение 0, если поток успешно закрыт; константа EOF , если произошла ошибка.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include
int main() {
FILE *fp;
char name = "my.txt" ;
if ((fp = fopen(name, "r" )) == NULL )
{
printf("Не удалось открыть файл" );
getchar();
return 0;
}
// открыть файл удалось
... // требуемые действия над данными
fclose(fp);
getchar();
return 0;
}

Чтение символа из файла :

char fgetc(поток);


Аргументом функции является указатель на поток типа FILE . Функция возвращает код считанного символа. Если достигнут конец файла или возникла ошибка, возвращается константа EOF .

Запись символа в файл :

fputc(символ,поток);

Аргументами функции являются символ и указатель на поток типа FILE . Функция возвращает код считанного символа.

Функции fscanf() и fprintf() аналогичны функциям scanf() и printf() , но работают с файлами данных, и имеют первый аргумент - указатель на файл.

fscanf(поток, "ФорматВвода" , аргументы);



Понравилась статья? Поделитесь ей