§ 9. Текстові файли
MatLab пропонує досить універсальні способи зчитування даних з текстових файлів і запису даних в необхідному вигляді в текстовий файл. Розглянемо спочатку оперування з числовими даними, представленими матрицями і векторами. Нехай в текстовому файлі vec.dat в стовпчик записані числа відповідно до правил MatLab, тобто для відділення десяткових знаків використовується точка, а для запису числа в експоненційному вигляді застосовується символ e. Функціяloadпозволяет занести вміст файлу vec.dat в числовий масив. Файл, укладену в апострофи, вказується у вхідному аргументеload, а в вихідному аргументі повертається вектор-стовпець 1:
Зворотна операція - запис значень вектор-стовпця в файл - проводиться за допомогою команди save, аргументами якої є: ім'я файлу, змінна, і додатковий параметр -ascii, що означає запис в текстовому вигляді:
»Save 'vec2.dat' v2 -ascii
Якщо числа в текстовому файлі розташовані в рядок і розділені пробілами, то результатом зчитування буде вектор-рядок. Вірно і зворотне, запис значень вектор-рядка призведе до занесення їх в рядок в текстовому файлі.
Запис матриці командою saveпріводіт до утворення текстового файлу з таблицею чисел. Текстовий файл, в кожному рядку якого знаходиться однакова кількість чисел, відокремлених один від одного пробілами, зчитується в двовимірний масив функціейload.
Команди loadіsaveпредназначени тільки для найпростішого введення-виведення числових даних. Розберемо тепер більш складний випадок, коли прочитується або записується інформація містить не тільки числа, а й текст. Робота з текстовими файлами складається з трьох етапів:
зчитування або запис даних;
Для відкриття файлу служить функція fopen, яка викликається з двома вхідними аргументами: ім'ям файлу і рядком, що задає спосіб доступу до файлу. Вихідним аргументомfopenявляется ідентифікатор файлу, тобто змінна, яка згодом використовується при будь-якому зверненні до файлу. Функціяfopenвозвращает -1, якщо при відкритті файлу виникла помилка. Існує чотири основних способів відкриття файлу:
f = fopen ( 'myfile.dat', 'rt') - відкриття текстового файлу myfile.dat тільки для читання з нього;
f = fopen ( 'myfile.dat', 'rt +') - відкриття текстового файлу myfile.dat для читання і запису даних;
f = fopen ( 'myfile.dat', 'wt') - створення порожнього текстового файлу myfile.dat тільки для запису даних;
f = fopen ( 'myfile.dat', 'wt +') - створення порожнього текстового файлу myfile.dat для запису і читання даних.
При використанні двох останніх варіантів слід дотримуватися обережності - якщо файл myfile.dat вже існує, то його вміст буде знищено. Після відкриття файлу з'являється можливість зчитувати з нього інформацію, або заносити її в файл. Після закінчення роботи з файлом необхідно закрити його за допомогою fclose (f).
Порядкове зчитування інформації з текстового файлу здійснюється за допомогою функції fgetl. Вхідним аргументом fgetl є ідентифікатор файлу, а вихідним - поточна рядок. Кожен виклик fgetl призводить до зчитування одного рядка і перекладу поточної позиції у файлі на початок наступного рядка. Команди, наведені на лістингу 9.1, послідовно зчитують з файлу myfile.dat перші три рядки в рядкові змінні str1, str2, str3.
Лістинг 9.1. Зчитування трьох перших рядків з текстового файлу
При послідовному зчитуванні рано чи пізно буде досягнуто кінець файлу, при цьому функція fgetlвернет мінус 1. Найкраще перед зчитуванням перевіряти, чи не є поточна позиція у файлі останньої. Для цього призначена функціяfeof, яка викликається від ідентифікатора файлу і повертає одиницю, якщо поточна позиція остання і нуль, в іншому випадку. Зазвичай послідовне зчитування організовується за допомогою ціклаwhile. Лістинг 9.2 містить файл-функціюviewfile, яка зчитує рядки файлу, і виводить їх в командне вікно.
Лістинг 9.2. Файл-функція viewfile
Виклик viewfile ( 'viewfile.m') призводить до відображення тексту самої файл-функції в командному вікні.
Рядки записуються в текстовий файл за допомогою функції fprintf, її першим вхідним аргументом є ідентифікатор файлу, а другим - додається рядок. Символ \ nслужіт для перекладу рядка. Якщо помістити його в кінець додається рядки, то наступна командаfprintfбудет здійснювати вивід в файл з нового рядка, а якщо \ nнаходітся на початку, то поточна командаfprintfвиведет текст з нового рядка. Наприклад, послідовність команд (лістинг 9.3) призведе до появи в файлі my.txt тексту з двох рядків (лістинг 9.4).
Лістинг 9.3. Висновок рядків в текстовий файл
fprintf (f, 'а цей текст з нового рядка');
Лістинг 9.4. Результат роботи операторів лістингу 9.3
текст ще текст
а цей текст з нового рядка
Аналогічного результату можна домогтися, перемістивши \ n з кінця рядка другої функції fprintf в початок рядка третьої функції fprintf. Аргументом fprintf може бути не тільки рядок, а й строкова змінна. В цьому випадку для забезпечення виведення з нового рядка її слід зчепити з рядком '\ n'.
Рядок, призначена для виведення в текстовий файл, може містити як текст, так і числа. Часто потрібно виділити певну кількість позицій під число і вивести його в експоненційному вигляді або з плаваючою точкою і з заданою кількістю цифр після десяткової точки. Тут не обійтися без форматного виведення за допомогою fprintf, звернення до якої має вигляд:
fprintf (ідентифікатор файлу, 'формати', список змінних)
У списку змінних можуть бути як числові змінні (або числа), так і рядкові змінні (або рядка). Другий аргумент є рядком спеціального виду з форматами, в яких будуть виводиться все елементи зі списку. Кожен формат починається зі знака відсотка. Для виведення рядків використовується формат s, а для виведення чисел - f (з плаваючою точкою) або e (експонентний). Число перед s вказує кількість позицій, що відводяться під висновок рядка. При виведенні значень числових змінних перед f або e ставиться два числа, між якими ставиться крапка. Перше з них означає кількість позицій, що виділяються під всі значення змінної, а друге - кількість знаків після десяткового дробу. Таким чином, під кожен з елементів списку відводиться поле певної довжини, вирівнювання в якому за замовчуванням проводиться по правому краю. Для вирівнювання по лівому краю слід після знака відсотка поставити знак мінус. Нижче наведені варіанти виклику fprintf і результати, незаповнені позиції після виведення (з пробілами) позначені символом ○.
fprintf (f, '% 14.4e', exp (-5)) ○○○ 6.7379e-003
fprintf (f, '% - 14.4e', exp (-5)) 6.7379e-003 ○○○
fprintf (f, '% 8s', 'текст') ○○○ текст
fprintf (f, '% - 8s', 'текст') текст ○○○
У разі, коли зарезервованого поля не вистачає під виведену рядок або число, MatLab автоматично збільшує довжину поля 1. наприклад:
fprintf (f, '% 5.4e', exp (-5)) 6.7379e-003
При одночасному виведенні чисел і тексту прогалини можуть з'являтися через неповністю заповнених полів, виділених як під числа, так і під рядки. Наведені нижче оператори і результат їх виконання демонструють розташування полів в рядку текстового файлу. Хвилястою лінією підкреслені поля, виділені під числа, а прямий - під рядки, символ ○ як і раніше позначає прогалини.
Форматний висновок зручний при формуванні файлу з таблицею результатів. Припустимо, що необхідно записати в файл f.dat таблицю значень функції
для заданого чіслаn значень, віддалених один від одного на однакову відстань. Файл з таблицею значень повинен мати таку структуру, як показано на лістингу 9.5.Лістинг 9.5. Текстовий файл з таблицею значень функції
Очевидно, що слід організувати цикл від початкового значення аргументу до кінцевого з кроком, відповідним заданому числу точок, а всередині циклу викликати fprintfс відповідним списком виведення і форматами. Символ \ n, призначений для перекладу рядка, поміщається в кінець рядка з форматами (див. Лістинг 9.6).
Лістинг 9.6. Файл-функція tab, що виводить таблицю значень функції
Звернемося тепер до зчитування даних з текстового файлу. Функція fscanfосуществляет зворотну дію по відношенню кfprintf. Кожен визовfscanfпріводіт до занесення даних, що починаються з поточної позиції, в змінну. Тип змінної визначається заданим форматом. У загальному випадку, звернення кfscanfімеет вид:
a = fscanf (ідентифікатор файлу, 'формат', число зчитувальних елементів)
Для зчитування рядків використовується формат% s, для цілих чисел -., А для речових -% g.
Припустимо, що файл exper.dat містить текст, наведений на лістингу 9.7. Дані відокремлені один від одного пробілами. Потрібно вважати дату проведення експерименту (число, місяць і рік) в відповідні змінні, а результати занести в числові массівиTIMEіDAT.
Лістинг 9.7. Файл з даними exper.dat
t = 0.1 0.2 0.3 0.4 0.5
G = 3.02 3.05 2.99 2.84 3.11
Лістинг 9.8. Застосування fscanf для зчитування даних
Інформація в текстовому файлі може бути представлена у вигляді таблиці. Для зчитування такої інформації слід використовувати масив структур з відповідним набором полів. Зчитування всієї інформації реалізується в циклі while, в умові якого проводиться перевірка на досягнення кінця файлу за допомогою функцііfeof.
Функція fscanf надає можливість зчитувати числа з текстового файлу не тільки в вектор-стовпець, а й масив заданих розмірів. Розташування чисел по рядках в файлі не має значення. Розміри формованого масиву вказуються в векторі в третьому вхідному аргументі fscanf. Розглянемо зчитування числових даних з файлу matr.txt (лістинг 9.9).
Лістинг 9.9. Текстовий файл matr.txt з матрицею
Функція fscanfформірует стовпець матриці, послідовно зчитуючи числа з файлу (т. Е. Через підрядник). Отже, для заповнення матриці з трьома рядками і чотирма стовпцями, необхідно вважати дані з файлу в масив чотири на три, а потім транспонувати його (лістинг 9.10).
Лістинг 9.10. Зчитування матриці з текстового файлу
Зверніть увагу, що масив може мати розміри не тільки 3 на 4. Оскільки дані зчитуються поспіль, то вони можуть бути занесені і в масив 2 на 6, і 4 на 3 і т. Д.
Завдання для самостійної роботи
Написати файл-функцію для зчитування даних з файлу в структуру або масив структур з відповідними полями.
1. Алексєєв Сергій 1980 5 4 4 5 3 5
Іванов Костянтин 1981 3 4 3 4 3 5
Петров Олег 1980 5 5 5 4 4 5
3. 195251 СПб Політехнічна 29
195256 СПб Науки 49
195256 СПб Науки 24
4. Результати спостережень
Time = 0.0 0.1 0.2 0.3 0.4 0.5 0.6
2.1 2.3 2.3 1.9 1.8 2.4
0.8 0.7 0.5 1.1 3.2 0.3
5. Алексєєв Іван 121-22-04
Сидоров Микола 101-21-99
Тимофєєв Сергій 570-00-03
Завдання для самостійної роботи
Вважати матриці і вектора з файлу в підходящі за розміром масиви. Зверніть увагу, що в файлах міститься поруч дві або три матриці або вектора, їх слід занести в різні масиви.
2. 1.399 2.001 9.921 3.21 0.12
0.129 1.865 8.341 9.33 8.01
9.136 8.401 7.133 3.12 3.22
3. 1 2 3 4 99 80
4. 10 20 40 50 12 19 21 32 44
6 7 8 9 0.1 0.2 0.3 0.4 200
0.5 0.6 0.7 0.8 300
1Файл з даними повинен знаходиться в поточному каталогеMatLab, інакше потрібно вказати повне ім'я файлу.
1Лучше уникати такі ситуації і заздалегідь розраховувати довжину поля виведення, інакше, наприклад, при виведенні таблиці може порушитися структура даних у файлі.
1Заметьте, що слова заносяться в строкову змінну без пробілу між ними. Для отримання рядки зі словами, розділеними прогалиною, необхідно вважати їх окремо в різні рядкові змінні і зчепити їх.