Зчитування другого рядка текстового файлу c. Робота з текстовими файлами в C

Записувати інформацію до текстового файлу ми вже навчилися. – Якщо не навчилися, дивіться минулу статтю. Там розповідається та докладно описано

Але якщо файл вже існує і нам потрібно рахувати з нього інформацію для обробки? На щастя, це теж досить просто. Нагадую, що варіантів для реалізації цього завдання існує кілька, мною описаний лише один. Описаний той, який особисто мені чомусь здається найпростішим для сприйняття.

#include

int main()
{
char s1 //Змінна зчитуватиме рядок
ifstream in (“C:\FromC\myfile.txt”); //Відкриваємо файл для зчитування інформації
in >> s1; //зчитуємо рядок
in .close () //Закриваємо файл

cout<Виводимо значення s1на екран
return 0;
}

Ось найпростіша програма для зчитування першого рядка з текстового файлу, який знаходиться на шляху
C:\FromC\myfile.txt –
Так як це продовження минулої статті, то я вирішив використовувати файл, який ми там створювали. Проблем з цим, напевно, виникнути не повинно.
Але повернемось до коду. Спочатку ми відкриваємо файл для зчитування інформації, для цього використовуємо команду ifstream ,у дужках вказуємо або назву файлу, або шлях до файлу, як зроблено в мене. (“C:\FromC\myfile.txt”);
Коли ми відкрили файл, щоб рахувати щось із нього, ми оголосили одну змінну типу char –
char s1
Тепер нам залишилося лише присвоїти змінної значення рядка з файлу. Це ми робимо командою in
Звертаємо увагу на кутові дужки in >>
Власне, як має бути видно з коментарів до коду програми, то щоб змінна надала зчитуване значення, ми повинні написати її після in >>
in >> s1;

Ніяким особливо складним завданням це не представляється, особливо якщо ви вже чудово освоїли та навчилися використовувати матеріал минулої статті – все абсолютно аналогічно, тільки 2 команди інші

Створення файлу та запис у нього інформації С++

ofstream out (ім'я файлу );
out<< (Записуваний рядок);
out. close ();
=============================

Читання тексту з файлу та виведення тексту на екран C++

ifstream in (Ім'я файлу );
in>> (Зчитуємо рядок);
in. close ();(Закриваємо файл)
============================
Напишемо просту програму, яка зчитуватиме введення з клавіатури тексту та записуватиме його у файл:

#include
#include

int main()
{
\\ 3 майбутні рядки
clrscsr(); //Очищаємо екран

cout<<“Wwedi pervuu stroku” ; cin >>a; endl;
cout<<“Wwedi wtoruu stroku” ; cin >> b; endl;
cout<<“Wwedi tretuu stroku” ; cin >>c; endl;
clrscr(); //

/*Починаємо роботу з файлом*/
ofstream out (“C:\FromC\myfile.txt”); //Відкриваємо файл для запису
out<Записуємо перший рядок
out<Записуємо другий рядок
out<Записуємо третій рядок
out .close(); //Закриваємо файл

//Обнуляємо змінні

for (int i = 0; i<=255 ;i ++)
(a =*“” ; b =*“” ; c =*“” ;)


ifstream in ("C:\FromC\myfile.txt");
in >>a >>b >>c; //Зчитуємо кожну нову сходинку в нову змінну
in .close (); //Закриваємо файл

/* */

for (i = 0 ;a !=*“” ;i ++)
{
if (i >sizeof(a )) break;
cout<

}
cout<<“\n” ; \\

/* */


{
if (i > sizeof(b )) break;
cout<
}
cout<<“\n” ; \\ Перевели курсор на новий рядок

/* */

for (i = 0 ;с !=*“” ;i ++)
{
if (i > sizeof(c )) break;
cout<<с ;
}

return 0;
}
===================

У наведених вище прикладах є один такий ВЕЛИЧЕЗНИЙ нестача. Якщо ми намагатимемося ввести рядок, що містить прогалини, то програма спрацьовуватиме не так, як нам потрібно. Напевно, на цю помилку натрапив не лише я, а й багато інших людей. Тому я залишаю невірно наведений код, щоб було видно, з чим можна зіткнутися.

Оскільки книжок удома немає, я знову почав нишпорити в інтернеті і знайшов багато всякої складної нісенітниці. Але таки якось підібрав вирішення своєї проблеми.
Допомогло те, що читав про те, що coutпідтримує свої способи. І в інтернеті всі поради йдуть на використання функції getlineНа моє щастя, як використовувати цю функцію я знайшов дуже швидко і потім використовував її в коді.
Взагалі варто згадати і описати цю функцію, але поки що я не особливо її розумію, просто розумію, що її потрібно використовувати і розумію як, тому наводжу правильніший приклад нашої програми, що розробляється:

#include
#include

int main()
{
char a, b, c; \\ 3 майбутні рядки
clrscsr(); //Очищаємо екран

/* Вводимо значення для змінних*/

cout<<“Wwedi pervuu stroku” ; cin.getline(a,sizeof(a)); endl;
cout<<“Wwedi wtoruu stroku” ; cin.getline(a,sizeof(b)); endl;
cout<<“Wwedi tretuu stroku” ; cin.getline(a,sizeof(c)); endl;
clrscr(); //Після введення значень очистили екран

/*Починаємо роботу з файлом*/
ofstream out (“C:\FromC\myfile.txt”); //Відкриваємо файл для запису
out<
Записуємо перший рядок
out<Записуємо другий рядок
out<Записуємо третій рядок
out .close(); //Закриваємо файл

//Обнуляємо змінні

for (int i = 0; i<=255 ;i ++)
(a =*“” ; b =*“” ; c=*“” ;)

/*Продовжуємо роботу з файлом*/

if stream in ("C:\FromC\myfile.txt");
in.getline(a,sizeof(a));// а
in.getline(b,sizeof(b));// Зчитуємо рядок у змінну b
in.getline(c,sizeof(c)); // Зчитуємо рядок у змінну c
in .close (); //Закриваємо файл

/* Зчитуємо посимвольно перший рядок та виводимо його на екран */

for (i =0 ;a !=*“” ;i++)
{
if (i >sizeof(a )) break;
cout<

}
cout<<“\n” ; \\ Перевели курсор на новий рядок

/* Зчитуємо посимвольно другий рядок та виводимо його на екран */

for (i =0 ;b !=*“” ;i ++)
{
if (i > sizeof(b )) break;
cout<
}
cout<<“\n” ; \\ Перевели курсор на новий рядок

/* Зчитуємо посимвольно третій рядок та виводимо його на екран */

for (i =0 ;с !=*“” ;i++)
{
if (i>sizeof (c)) break;
cout<<с[i];
}

getch(); \\Очікуємо натискання клавіші Enter
return 0;
}
===================

У цьому матеріалі розібрано приклад посимвольного читання інформації. Так як я не описував роботу зі змінними типу char, то у початківців можуть виникнути деякі незручності сприйняття коду. Просто я не знав, що тип charмає якісь особливості та думав все простіше. Тому деякі незрозумілі моменти наведеної програми можна прочитати у наступній статті робота з charв C++ для початківців

В іншому, наведений приклад, як у C++ рахувати рядки з текстового файлу має бути доступним і цілком зрозумілим. Це зараз не оптимальний варіант реалізації, і я упустив деякі важливі моменти, але так як у нас початок вивчення мови C++, то цього поки що цілком достатньо. Пізніше я, напевно, дійду до втраченого, а зараз треба сприймати тільки найнеобхідніше.

Якщо ми разом з вами зрозуміли цей матеріал, значить просунулися на маленький крок до свого професіоналізму.

Примітка:
break;– Це команда, яка виконує вихід із циклу. У нас якщо лічильник циклу forстає більше ніж оголошений розмір змінної char,то ми примусово виходимо із циклу
!= – це поставлена ​​нами умова. Позначає таку умову нерівність
if(a !=b )- Читається як якщо aне дорівнює b

endl; -Це переведення курсору на новий рядок усередині консолі (наскільки я зрозумів)
Ця команда схожа на "\n"

Текстові файли

Розглянемо роботу з текстовим файлом Сі на прикладі. Створіть на диску текстовий файл з ім'ям TextFile.txt. Наберіть у цьому файлі такі рядки:

String_1 123 String_11, 456
String_2
String_3

Збережіть файл.

А це код програми на C, яка відкриває наш файл та зчитує з нього рядки:

/* *Author: @author Subbotin B.P..h> #include #define LEN 50 int main(void) ( puts("Text file operations"); char cArray; FILE *pTextFile = fopen("C:\\TextFile.txt", "r"); if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) while(fgets(cArray, LEN, pTextFile) != NULL) ( printf("%s", cArray); ) fclose(pTextFile); return EXIT_SUCCESS; )

Щоб відкрити текстовий файл у C використовуємо функцію fopen:

FILE *pTextFile = fopen("C:\TextFile.txt", "r");

перший аргумент функції fopen вказує на файл, а другий каже, що файл відкритий для його читання.

Рядки зчитуємо за допомогою функції fgets:

fgets(cArray, LEN, pTextFile);

перший аргумент функції fgets вказує на масив символів, в якому будуть збережені отримані рядки, другий аргумент – це максимальна кількість символів для зчитування, третій – наш файл.

Після завершення роботи з файлом, його потрібно закрити:

fclose(pTextFile);

Отримуємо:

Російські літери у рядках теж проходять.

До речі, цю програму я зробив у Eclipse. Як працювати з C/C++ в Eclipse можна переглянути .

Отже, ми відкрили та рахували дані з текстового файлу.

Тепер навчимося програмно створювати текстовий файл та записувати в нього дані.

/* Author: @author Subbotin B.P..h> #include int main(void) ( FILE *pTextFile = fopen("C:\\TextFileW.txt", "w"); char *cString = "This is a string"; char cNewLine = "\n"; int nVal = 123 ; if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) fprintf(pTextFile, "%s%c", cString, cNewLine); fprintf(pTextFile, "%d", nVal); ; )

Створюємо текстовий файл для запису даних:

FILE *pTextFile = fopen("C:\TextFileW.txt", "w");

якщо файл вже є, то він буде відкритий, і всі дані будуть видалені.

C-рядок cString і число nVal записуються програмою в текстовий файл. cNewLine – це просто перехід на новий рядок.

Записуємо дані до текстового файлу за допомогою функції fprintf:

fprintf(pTextFile, "%s%c", cString, cNewLine);

перший аргумент тут – наш файл, другий – форматний рядок, третій і більше – необхідна для цього формату кількість аргументів.

– порівняння виявлення рівності чи нерівності.

Практичне призначення перерахування – визначення безлічі символічних констант цілого типу, що відрізняються.

Приклад використання змінних типу:

mo = 1, tu, we, th, fr, sa, su) days;

puts(“ Введіть день тижня (від 1 до 7): ”); scanf(“%d”, &t_day);

w_day = su; start = mo;

end = w_day-t_day;

printf(“\n Понеділок - %d-й день тижня, \ зараз %d-й день. \n\

До кінця тижня %d днів (дня). ”, start, t_day, end);

Результат роботи програми: Введіть день тижня (від 1 до 7): 2

Понеділок – 1-й день тижня, зараз 2-й день. До кінця тижня – 5 днів (дня).

18. Файли у мові Сі

Файл – це набір даних, розміщений зовнішньому носії і аналізований у процесі обробки як єдине ціле. У файлах розміщуються дані, які призначені для тривалого зберігання.

Розрізняють два види файлів: текстові та бінарні. Текстові файли є послідовністю ASCII символів і можуть бути переглянуті та відредаговані за допомогою будь-якого текстового редактора.

Бінарні (двійкові) файли є послідовністю даних, структура яких визначається програмно.

У мові Сі є великий набір функцій для роботи з файлами, більшість яких знаходяться у бібліотеках stdio.h та iio.h.

18.1. Відкриття файлу

Кожному файлу надається внутрішнє логічне ім'я, яке використовується надалі при зверненні до нього. Логічне ім'я (ідентифікатор файлу) – це

покажчик на файл, тобто. область пам'яті, де міститься вся необхідна інформація про файл. Формат оголошення покажчика на файл наступний:

FILE * покажчик на файл;

FILE – ідентифікатор структурного типу, описаний у стандартній бібліотеці

stdio.h і містить таку інформацію:

type struct (

- Число непрочитаних байт, що залишилися в буфері;

Простий обсяг буфера – 512 байт; як тільки level = 0,

у буфер із файлу читається наступний блок даних;

- Прапор статусу файлу - читання, запис, доповнення;

- Дескриптор файлу, тобто. число, що визначає його но-

unsigned char hold;

- Непереданий знак, тобто. ungetc-символ;

- Розмір внутрішнього проміжного буфера;

unsigned char buffer;

– значення покажчика доступу всередині буфера, тобто.

задає початок буфера, початок рядка або поточне зна-

чення покажчика всередині буфера в залежності від реж-

ма буферизації;

unsigned char *curp;

– поточне значення вказівника для доступу всередині бу-

фера, тобто. задає поточну позицію в буфері для обме-

з програмою;

unsigned istemp;

- Прапор тимчасового файлу;

- Прапор під час роботи з файлом;

) FILE;

Перш ніж розпочати працювати із файлом, тобто. отримати можливість читання чи запису інформації у файл, його потрібно відкрити доступу. Для цього зазвичай використовується функція

FILE* fopen (char* ім'я_ файлу, char* режим);

вона бере зовнішнє уявлення – фізичне ім'я файлу на носії (дискета, вінчестер) і ставить йому у відповідність логічне ім'я.

фізичне ім'я, тобто. ім'я файлу та шлях до нього задається першим параметром

- рядком, наприклад, "a:Mas_dat.dat" - файл з ім'ям Mas_dat.dat, що знаходиться на дискеті, "d:\work\\Sved.txt" - файл з ім'ям Sved.txt, що знаходиться на вінчестері в каталозі work .

Увага! Зворотний сліш (\), як спеціальний символ, у рядку записується двічі.

При успішному відкритті функція fopen повертає покажчик на файл (надалі – покажчик файлу). При помилці повертається NULL. Ця ситуація зазвичай виникає, коли неправильно вказується шлях до файлу, що відкривається. Наприклад, якщо в дисплейному класі нашого університету вказати шлях, заборонений для запису (зазвичай дозволено d:\work\).

Другий параметр – рядок, в якому задається режим доступу до файлу:

w – файл відкривається для запису; якщо файлу із заданим ім'ям немає, він буде створено; якщо такий файл існує, перед відкриттям колишня інформація знищується;

r – файл відкривається лише читання; якщо такого файлу немає, виникає помилка;

a – файл відкривається додавання до кінця нової інформації;

r+ – файл відкривається для редагування даних – можливі запис, і читання інформації;

w+ – те саме, що й для r+;

a+ – те саме, що й для a, лише запис можна виконувати будь-яке місце файла; доступне та читання файлу;

t – файл відкривається у текстовому режимі; b – файл відкривається у двійковому режимі.

Текстовий режим відрізняється від двійкового тим, що при відкритті файлу як текстової пари символів "переклад рядка", "повернення каретки" замінюється на один символ: "переведення рядка" для всіх функцій запису даних у файл, а для всіх функцій виведення символ "переклад рядка" тепер замінюється на два символи: «переклад рядка», «повернення каретки».

За замовчуванням файл відкривається у текстовому режимі. Приклад: FILE * f; - Оголошується покажчик на файл f;

f = fopen ("d:\work\Dat_sp.cpp", "w"); – відкривається для запису файл із логічним ім'ям f, що має фізичне ім'я Dat_sp.cpp, що знаходиться на диску d, у каталозі work; або коротше

FILE *f = fopen ("d:\work\Dat_sp.cpp", "w");

18.2. Закриття файлу

Після роботи з файлом, доступ до нього необхідно закрити. Це виконує функція int fclose (покажчик файлу). Наприклад, із попереднього прикладу файл закривається так: fclose (f);

Для закриття кількох файлів введена функція, оголошена так: void fcloseall (void );

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

FILE * freopen (char * ім'я_файлу, char * режим, FILE * покажчик_файлу);

Ця функція спочатку закриває файл, оголошений вказівником_файлу(як це робить функція fopen ), а потім відкриває файл сименем_файла та правами доступу «режим».

У мові Сі є можливість роботи з тимчасовими файлами, які потрібні лише у процесі роботи програми. У цьому випадку використовується функція

FILE * tmpfile (void);

яка створює на диску тимчасовий файл з правами доступу w+b, після завершення роботи програми або після закриття тимчасового файлу він автоматично видаляється.

18.3. Запис – читання інформації

Усі дії з читання-запису даних у файл можна поділити на три групи: операції посимвольного введення-виводу; операції рядкового введення виводу; операції введення-виведення по блоках.

Розглянемо основні функції, що застосовуються у кожній із зазначених трьох груп операцій.

Посимвольне введення-виведення

У функціях посимвольного введення-виводу відбувається прийом одного символу з файлу або передача одного символу файл:

Порядкове введення-виведення

У функціях рядкового введення-виведення відбувається перенесення з файлу або в

Блокове введення-виведення

У функціях блокового введення-виведення робота відбувається з цілими блоками

інформації:

int fread (void*p, intsize,

– зчитує n блоків поsize байт кожен з фай-

int n, FILE *f)

ла f в область пам'яті з вказівником p (необхідно

int fwrite (void*p, intsize,

заздалегідь відвести пам'ять під зчитуваний блок);

– записує n блоків по size байт кожен з об-

int n, FILE *f)

ласті пам'яті з покажчиком p файл f.

Форматоване введення-виведення здійснюється функціями.

Останнє оновлення: 31.10.2015

Клас FileStreamпредставляє можливості зчитування з файлу та запису у файл. Він дозволяє працювати як із текстовими файлами, так і з бінарними.

Розглянемо найважливіші його властивості та методи:

    Властивість Length: повертає довжину потоку в байтах

    Властивість Position: повертає поточну позицію в потоці

    Метод Read: зчитує дані з файлу в масив байтів. Приймає три параметри: int Read(byte array, int offset, int count) та повертає кількість успішно лічених байтів. Тут використовуються такі параметри:

    • array - масив байтів, куди будуть поміщені дані, що зчитуються з файлу

      offset представляє зміщення в байтах у масиві array, в який лічені байти будуть поміщені

      count – максимальна кількість байтів, призначених для читання. Якщо у файлі знаходиться менша кількість байтів, то всі вони будуть прочитані.

    Метод long Seek(long offset, SeekOrigin origin): встановлює позицію в потоці зі зміщенням кількість байт, зазначених у параметрі offset.

    Метод Write: записує у файл дані з масиву байтів. Приймає три параметри: Write(byte array, int offset, int count)

    • array - масив байтів, звідки дані записуватимуться у файлі

      offset - зміщення в байтах у масиві array, звідки починається запис байтів у потік

      count - максимальна кількість байтів, призначених для запису

FileStream представляє доступ до файлів на рівні байтів, тому, наприклад, якщо вам треба рахувати або записати один або кілька рядків у текстовий файл, то масив байтів треба перетворити на рядки, використовуючи спеціальні методи. Тому для роботи з текстовими файлами використовуються інші класи.

У той же час при роботі з різними бінарними файлами, що мають певну структуру FileStream може бути дуже корисний для отримання певних порцій інформації та її обробки.

Подивимося на прикладі зчитування-запису до текстового файлу:

Console.WriteLine("Введіть рядок для запису у файл:"); string text = Console.ReadLine(); // запис у файл using (FileStream fstream = new FileStream(@"C:\SomeDir\noname\note.txt", FileMode.OpenOrCreate)) ( // Перетворимо рядок на байти byte array = System.Text.Encoding.Default. GetBytes(text);// запис масиву байтів у файл fstream.Write(array, 0, array.Length);Console.WriteLine("Текст записаний у файл"); OpenRead(@"C:\SomeDir\noname\note.txt")) ( // перетворюємо рядок в байти byte array = new byte; // зчитуємо дані fstream.Read(array, 0, array.Length); // декодуємо байти в рядок string textFromFile = System.Text.Encoding.Default.GetString(array); Console.WriteLine("Текст із файлу: (0)", textFromFile);

Розберемо цей приклад. І під час читання, і під час запису використовується оператор using . Не треба плутати цей оператор з директивою using, яка підключає простору імен на початку файлу коду. Оператор using дозволяє створювати об'єкт у блоці коду, по завершенню якого викликається метод Dispose цього об'єкта, і, таким чином, об'єкт знищується. В даному випадку як такий об'єкт служить змінна fstream.

Об'єкт fstream створюється двома різними способами: через конструктор і один із статичних методів класу File.

Тут у конструктор передається два параметри: шлях до файлу та перерахування FileMode. Цей перелік вказує на режим доступу до файлу і може приймати такі значення:

    Append : якщо файл існує, текст додається в кінець файл. Якщо файлу немає, він створюється. Файл відкривається лише для запису.

    Create: створюється новий файл. Якщо такий файл вже існує, він перезаписується

    CreateNew: створюється новий файл. Якщо такий файл вже існує, він додаток викидає помилку

    Open: відкриває файл. Якщо файл не існує, викидається виняток

    OpenOrCreate: якщо файл існує, він відкривається, якщо ні – створюється новий

    Truncate : якщо файл існує, він перезаписується. Файл відкривається лише для запису.

Статичний метод OpenRead класу File відкриває файл для читання та повертає об'єкт FileStream.

Конструктор класу FileStream також має ряд перевантажених версій, що дозволяє більш точно налаштувати об'єкт, що створюється. Всі ці версії можна переглянути на msdn.

І під час запису, і під час читання застосовується об'єкт кодування Encoding.Default з місця імен System.Text . В даному випадку ми використовуємо два його методи: GetBytes для отримання масиву байтів з рядка та GetString для отримання рядка з масиву байтів.

У результаті введений нами рядок записується у файл note.txt. По суті це бінарний файл (не текстовий), хоча якщо ми в нього запишемо тільки рядок, то зможемо подивитися у вигляді, що легко читається, цей файл, відкривши його в текстовому редакторі. Однак якщо ми в нього запишемо випадкові байти, наприклад:

Fstream.WriteByte(13); fstream.WriteByte(103);

То в нас можуть виникнути проблеми із його розумінням. Тому для роботи безпосередньо з текстовими файлами призначені окремі класи - StreamReader та StreamWriter.

Довільний доступ до файлів

Нерідко бінарні файли представляють певну структуру. І, знаючи цю структуру, ми можемо взяти з файлу потрібну порцію інформації або навпаки записати в певному місці файлу певний набір байтів. Наприклад, у wav-файлах безпосередньо звукові дані починаються з 44 байти, а до 44 байти йдуть різні метадані - кількість каналів аудіо, частота дискретизації тощо.

За допомогою методу Seek() ми можемо керувати положенням курсора потоку, починаючи з якого здійснюється зчитування або запис файлу. Цей метод приймає два параметри: offset (зміщення) та позиція у файлі. Позиція у файлі описується трьома значеннями:

    SeekOrigin.Begin : початок файлу

    SeekOrigin.End : кінець файлу

    SeekOrigin.Current: поточна позиція у файлі

Курсор потоку, з якого починається читання або запис, зміщується вперед на значення offset щодо позиції, зазначеної як другий параметр. Зміщення може негативним, тоді курсор зсувається назад, якщо позитивне – то вперед.

Розглянемо з прикладу:

Using System.IO; використовуючи System.Text; class Program ( static void Main(string args) ( string text = "hello world"; // запис у файл using (FileStream fstream = new FileStream(@"D:\note.dat", FileMode.OpenOrCreate)) ( // перетворюємо рядок на байти byte input = Encoding.Default.GetBytes(text); // запис масиву байтів у файл fstream.Write(input, 0, input.Length); Console.WriteLine("Текст записаний у файл"); переміщуємо покажчик в кінець файлу, до кінця файлу-п'ять байт fstream.Seek(-5, SeekOrigin.End);// мінус 5 символів з кінця потоку // зчитуємо чотири символи з поточної позиції byte output = new byte; output, 0, output.Length);// декодуємо байти в рядок string textFromFile = Encoding.Default.GetString(output); у файлі слово world на слово house string replaceText = "house";fstream.Seek(-5, SeekOrigin.End); // мінус 5 символів з кінця потоку , 0, input.Length); // зчитуємо весь файл // Повертаємо покажчик на початок файлу fstream.Seek(0, SeekOrigin.Begin); output=new byte; fstream.Read(output, 0, output.Length); // декодуємо байти рядок textFromFile = Encoding.Default.GetString(output); Console.WriteLine("Текст із файлу: (0)", textFromFile); // hello house) Console.Read(); )

Консольний висновок:

Текст записано у файл Текст із файлу: worl Текст із файлу: hello house

Виклик fstream.Seek(-5, SeekOrigin.End) переміщує курсор потоку в кінець файлів назад на п'ять символів:

Тобто, після запису в новий файл рядка "hello world" курсор стоятиме на позиції символу "w".

Після цього зчитуємо чотири байти, починаючи з символу "w". У цьому кодуванні 1 символ представлятиме 1 байт. Тому читання 4 байтів буде еквівалентне читання чотирьох сивол: "worl".

Потім знову ж таки переміщуємося в кінець файлу, не доходячи до кінця п'ять символів (тобто знову ж таки з позиції символу "w"), і здійснюємо запис рядка "house". Таким чином, рядок "house" замінює рядок "world".

Закриття потоку

У прикладах вище для закриття потоку застосовується конструкція using . Після того, як всі оператори і вирази в блоці, які використовуються, відпрацюють, об'єкт FileStream знищується. Однак ми можемо вибрати інший спосіб:

FileStream fstream = null; try (fstream = new FileStream(@"D:\note3.dat", FileMode.OpenOrCreate); // операції з потоком) catch(Exception ex) () finally (if (fstream! = null) fstream.Close(); )

Якщо ми не використовуємо конструкцію using, то нам треба явно викликати метод Close() : fstream.Close()

Механізм введення-виводу, розроблений, не відповідає загальноприйнятому сьогодні стилю об'єктно-орієнтованого програмування, крім того, він активно використовує операції з покажчиками, які вважаються потенційно небезпечними в сучасних захищених середовищах виконання коду. Альтернативою розробки прикладних додатків є механізм стандартних класів вводу-вывода, наданий стандартом мови C++.

Відкриття файлів

Найчастіше застосовуються класи ifstream для читання, ofstream для запису і fstream для модифікації файлів.

Усі потокові класи введення-виведення є непрямими похідними від загального предка ios, повністю успадковуючи його функціональність. Так, режим відкриття файлів задає член даних типу open_mode, що визначається таким чином:

Enum open_mode (app, binary, in, out, trunc, ate);

Нижче наведено можливі значення прапорів та їх призначення.

Наприклад, щоб відкрити файл з ім'ям test.txt для читання даних у бінарному вигляді, слід написати:

Ifstream file; file.open ("test.txt", ios:: in | ios:: binary);

Оператор логічного АБО (|) дозволяє скласти режим з будь-яким поєднанням прапорів. Так, щоб, відкриваючи файл із запису, випадково не затерти існуючий файл із тим самим ім'ям, треба використовувати таку форму:

Ofstream file; file.open ("test.txt", ios::out | ios::app);

Передбачається, що до проекту підключено відповідний заголовний файл:

#include

Для перевірки того, чи вдалося відкрити файл, можна застосовувати конструкцію

If (!file) ( //Обробка помилки відкриття файлу )

Оператори включення та вилучення

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

File<< "Это строка текста";

Можна також записувати текстовий рядок частинами:

File<< "Это " << "строка " << "текста";

Оператор endl завершує введення рядка символом "повернення каретки":

File<< "Это строка текста" << endl;

За допомогою оператора включення нескладно записувати у файл значення змінних або елементів масиву:

Ofstream file ("Temp.txt"); char buff = "Текстовий масив містить змінні"; int vx = 100; float pi = 3.14159; file<< buff << endl << vx << endl << pi << endl;

В результаті виконання коду утворюється три рядки текстового файлу Temp.txt:

Текстовий масив містить змінні 100 3.14159

Зауважте, що числові значення записуються у файл у вигляді текстових рядків, а не двійкових значень.

Оператор вилучення(>>)здійснює зворотні дії. Здавалося б, щоб отримати символи з файлу Temp.txt , записаного раніше, потрібно написати код на кшталт наступного:

Ifstream file ("Temp.txt"); char buff; int vx; float pi; file >> buff >> vx >> pi;

Однак оператор вилучення зупиниться на першому розділі, що попався (символі пробілу, табуляції або нового рядка). Таким чином, при розборі речення "Текстовий масив містить змінні" тільки слово "Текстовий" запишеться в масив buff, пробіл ігнорується, а слово "масив" стане значенням цілої змінної vx і виконання коду "піде врознос" з неминучим порушенням структури даних. Далі при обговоренні класу ifstream буде показано, як правильно організувати читання файлу з попереднього прикладу.

Клас ifstream: читання файлів

Як випливає із розшифровки назви, клас ifstream призначений для введення файлового потоку. Далі наведено основні методи класу. Більшість їх успадкована від класу istream і перевантажена з розширенням батьківської функціональності. Наприклад, функція get , залежно від параметра виклику, здатна зчитувати як одиночний символ, а й символьний блок.

Тепер зрозуміло, як потрібно модифікувати попередній приклад, щоб використання оператора отримання даних давало очікуваний результат:

Ifstream file("Temp.txt"); char buff; int vx; float pi; file.getline(buff, sizeof(buff)); file >> vx >> pi:

Метод getline прочитає перший рядок файлу до кінця, а оператор >> надасть значення змінним.

Наступний приклад показує додавання даних до текстового файлу з наступним читанням всього файлу. Цикл while (1) використовується замість while(!file2.eof()) з причин, які обговорювалися в .

#include #include using namespace std; int main() ( ofstream file; file.open("test.txt",ios::out|ios::app); if (!file) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >> a; if (file2.eof()) break; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

У наступному прикладі показаний цикл зчитування рядків із файлу test.txt та їх відображення на консолі.

#include #include using namespace std; int main() ( ifstream file; // створити потоковий об'єкт file file.open("test.txt"); // відкрити файл на читання if (!file) return 1; // повернення помилково відкриття char str; // статичний буфер рядка // Зчитувати і відображати рядки в циклі, доки eof while (!file.getline(str, sizeof(str)).eof()) cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Цей код під ОС Windows також залежить від наявності в останньому рядку файлу символу перекладу рядка, надійніше було б зробити так:

While (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

Явні виклики методів open і close не є обов'язковими. Дійсно, виклик конструктора з аргументом дозволяє відразу ж, у момент створення потокового об'єкта file відкрити файл:

Ifstream file("test.txt");

Замість методу close можна використовувати оператор delete, який автоматично викличе деструктор об'єкта file та закриє файл. Код циклу while забезпечує належну перевірку ознаки кінця файлу.

Клас ofstream: запис файлів

Клас ofstream призначений для виведення даних із файлового потоку. Далі перелічені основні методи цього класу.

Описаний раніше оператор увімкнення зручний для організації запису в текстовий файл:

Ofstream file ("temp.txt"); if (! file) return; for (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Бінарні файли

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

Перший параметр методів write і read (адреса блоку запису/читання) повинен мати тип символьного покажчика char*, тому необхідно зробити явне перетворення типу адреси структури void*. Другий параметр вказує на те, що бінарні блоки файлу мають постійний розмір байтів незалежно від фактичної довжини запису. Наступний додаток дає приклад створення та відображення даних найпростішого записника. Потім записи файлу послідовно зчитуються та відображаються на консолі.

#include #include #include using namespace std; struct Notes ( // структура даних записника char Name; // П.І.Б. char Phone; // телефон int Age; // вік ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1= ( "Грозний Іван Васильович", "не встановлений", 60); Notes Note2= ( "Годунов Борис Федорович ", "095-111-2233 ", 30 ); (Notes));// 1-й блок ofile.write((char*)&Note2, sizeof(Notes));// 2-й блок ofile.write((char*)&Note3, sizeof(Notes)); / 3-й блок ofile.close(); // закрити записаний файл ifstream ifile("Notebook.dat", ios::binary); Notes Note; // структурована змінна char str; відображати рядки в циклі, поки не eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tТіл: %s\tВік: %d") , Note.Name, Note.Phone, Note.Age);<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

В результаті виконання цього коду утворюється бінарний файл Notebook.dat із трьох блоків розміром по 80 байт кожен (за умови, що символи – однобайтові). Звичайно, ви можете використовувати інші потокові методи та виконувати будь-які операції над полями певної структури даних.

Клас fstream: довільний доступ до файлу

Припустимо, що в нашій записнику накопичилося 100 записів, а ми хочемо вважати 50-ю. Звичайно, можна організувати цикл та прочитати всі записи з першої по задану. Очевидно, що більш цілеспрямоване рішення - встановити покажчик позиціонування файлу pos прямо на запис 50 і вважати її:

Ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Notes); ifile.seekg(pos); // Пошук 50-го запису Notes Note; //Notes - описана вище структура "запис" ifile.read((char*)&Note, sizeof(Notes));

Подібні операції пошуку ефективні, якщо файл складається із записів відомого та постійного розміру. Щоб замінити вміст довільного запису, потрібно відкрити потік виводу як модифікації:

Ofstream ofilе ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile seekp(pos); // Пошук 50-го запису Notes Note50 = ("Єльцин Борис Миколайович", "095-222-3322", 64); ofile.write((char*)&Note, sizeof(Notes)); // Заміна

Якщо не вказати прапорець ios::ate (або ios::app), то при відкритті бінарного файлу Notebook.dat його попередній вміст буде стертий!

Зрештою, можна відкрити файл одночасно для читання/запису, використовуючи методи, успадковані потоковим класом fstream від своїх попередників. Оскільки клас fstream вироблений від istream та ostream (батьків ifstream і ofstream відповідно), всі згадані раніше методи стають доступними у додатку.

У наступному прикладі показано перестановку першої та третьої записів файлу Notebook.dat.

#include #include #include using namespace std; struct Notes ( char Name; char Phone; int Age; ); int main() ( setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Відкрити файл на читання/запис одночасно fstream file("Notebook.dat", ios::binary | ios::in | ios:: out);file.seekg(2 * sizeof(Notes));// знайти і рахувати Note3 file.read((char*)&Note1, sizeof(Notes));file.seekg(0); // Note1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

У конструкторі об'єкта file треба вказати прапори ios::in та ios::out , дозволяючи одночасне виконання операцій читання та запису. В результаті виконання цього коду перший та третій записи бінарного файлу Notebook.dat поміняються місцями.

Додаткові приклади на тему є .