Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c#_theoretical_2.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
750.08 Кб
Скачать

Символьний ввід-вивід у файл

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

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

Елемент класу TextReader

Призначення

public virtual int Peek();

Повертає ціле число, яке представляє наступний символ, читання якого потрібно здійснити, або значення -1, якщо доступних символів немає.

public virtual int Read();

Зчитує дані із вхідного потока.

public virtual int ReadBlock(char[] buffer, int index, int count);

Зчитує із потоку count символів, починаючи із позиції index, та записує їх у buffer.

public virtual string ReadLine();

Зчитує рядок із потоку. Порожній рядок (null) означає кінець файлу.

public virtual string ReadToEnd();

Зчитує всі символи до кінця потоку, починаючи із поточної позиції, та повертає зчитані дані як один рядок.

public override void Close();

Закриває файл та звільняє пов’язані із ним ресурси. При цьому буфер автоматично очищується.

Із власних елементів класу StreamReader відмітимо наступні:

Елемент класу StreamReader

Призначення

public StreamReader(Stream stream);

Цей варіант конструктора дозволяє створити символьний потік, ставши оболочкою для базового байтового потоку stream. Як правило, у якості цього параметра використовують об’єкт класу FileStream. При цьому базовий потік stream має бути створений у режимі доступу для читання. Якщо параметр stream виявляється порожнім, те генерується виняткова ситуація ArgumentNullException. А якщо потік, заданий параметром stream, не був відкритий для зчитування даних, то генерується виняткова ситуація ArgumentException.

public StreamReader(string path);

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

public virtual Stream BaseStream { get; }

Повертає базовий потік, з яким працює об’єкт класу StreamReader.

public bool EndOfStream { get; }

Повертає значення true, якщо показчик у потоці знаходиться у кінці цього потоку, інакше − false.

public override void Close();

Закриває потік. При цьому закривається і базовий потік.

Особливості роботи із класом символьного потоку StreamReader розглянемо на прикладі програмної реалізації наступної задачі.

Нехай задано текстовий файл. Визначити рядок найбільшої довжини.

class Program

{

public static void maxLengthLine(string FileName)

{

// пробуємо створити символьний потік для зчитування

try

{

StreamReader f = new StreamReader(FileName);

// довжина максимального рядка

int maxLength = -1;

// рядок максимальної довжини

string longestS = null;

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

while (!f.EndOfStream)

{

// зчитуємо черговий рядок із файлу

string s = f.ReadLine();

// дивимось, чи зчитаний рядок не є довшим за найдовший зчитаний до цього

if (s.Length > maxLength)

{

maxLength = s.Length;

longestS = s;

}

}

// дивимось, можливо, текстовий файл був порожнім

if (longestS != null)

Console.WriteLine(longestS);

else

Console.WriteLine("Файл порожній.");

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

f.Close();

}

catch (Exception e)

{

Console.WriteLine("Помилка: {0}", e.Message);

}

catch (FileNotFoundException e)

{

Console.WriteLine(e.Message);

Console.WriteLine("Не правильно вказано ім'я файлу.");

}

}

}

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

Елемент класу TextWriter

Призначення

public virtual void Close()

Закриває файл та звільняє пов’язані із ним ресурси. При цьому буфер автоматично очищується.

public virtual void Flush()

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

public virtual string NewLine { get; set; }

Повертає або задає ознаку кінця рядка.

Write

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

WriteLine

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

Із власних елементів класу StreamWriter відмітимо наступні:

Елемент класу StreamWriter

Призначення

public StreamWriter(Stream stream);

Цей варіант конструктора дозволяє створити символьний потік, ставши оболочкою для базового байтового потоку stream. Як правило, у якості цього параметра використовують об’єкт класу FileStream. При цьому базовий потік stream має бути створений у режимі доступу для запису. Якщо параметр stream виявляється порожнім, те генерується виняткова ситуація ArgumentNullException. А якщо потік, заданий параметром stream, не був відкритий для зчитування даних, то генерується виняткова ситуація ArgumentException.

public StreamWriter(string path);

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

public StreamWriter(string path, bool append);

Цей варіант конструктора дає можливість відкрити існуючий текстовий файл для дописування у нього даних. При цьому, якщо файл існує та значення параметра append дорівнює false, то файл перезаписується.Якщо файл існує та значення параметра append дорівнює true, то у файл додаються дані. Інакше − створюється новий файл.

public virtual Stream BaseStream { get; }

Повертає базовий потік, з яким працює об’єкт класу StreamWriter.

public override void Close();

Закриває потік. При цьому закривається і базовий потік.

Особливості роботи із класом символьного потоку StreamReader розглянемо на прикладі програмної реалізації наступної задачі.

Нехай задано текстовий файл, у якому слова розділені пробілами. Перенести у новий файл всі рядки, які містять задане слово.

class Program

{

public static void MoveAllLines(string word, string fromFile, string toFile)

{

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

try

{

StreamReader sr = new StreamReader(fromFile);

StreamWriter sw = new StreamWriter(toFile);

// організовуємо цикл для зчитування рядків із заданого текстового файлу

while (!sr.EndOfStream)

{

// зчитуємо черговий рядок із файлу

string s = sr.ReadLine();

// дивимось, чи зчитаний рядок містить задане слово

if (s.IndexOf(word)>=0)

{

// записуємо зчитаний рядок у новий файл

sw.WriteLine(s);

}

}

// закриваємо відповідні символьні потоки

sr.Close();

sw.Close();

}

catch (FileNotFoundException e)

{

Console.WriteLine(e.Message);

Console.WriteLine("Не правильно вказано ім'я файлу.");

}

catch (Exception e)

{

Console.WriteLine("Помилка: {0}", e.Message);

}

}

}

Часто текстові файли використовуються для збереження матриць. Тому на завершення цього параграфу наведемо приклад реалізації класу IntMatrix цілочислових прямокутних матриць, в якому наводиться приклад реалізації зчитування прямокутної цілочислової матриці із текстового файлу (метод LoadFromFile) та збереження прямокутної цілочислової матриці у текстовому файлі (метод SaveToFile).

class IntMatrix

{

// кількість рядків матриці

int RowCount;

// кількість стовпців матриці

int ColCount;

// масив елементів матриці

int[,] array;

// метод зчитування наступного цілого числа у заданому символьному потоці зчитування

int ReadNextInt(StreamReader sr)

{

// рядкове представлення цілого числа

string tmp = null;

// змінна, у яку буде зчитуватися наступний символ із потоку

char c;

// проопускаємо всі пробіли перед черговим числом

do

{

c = (char)sr.Read();

}

while (c == ' ');

// поки не досягнуто наступного пробілу і не досягнуто кінець рядка \r\n

while (c != ' ' & c != '\r' & c != '\n')

{

// додаємо зчитану цифру до поточного рядкового представлення числа

tmp += c;

// зчитуємо наступну цифру

c = (char)sr.Read();

}

// на основі сформованого рядкового представлення числа повертаємо це число

if(tmp!=null)

return int.Parse(tmp);

return 0;

}

public void LoadFromFile(string fileName)

{

// пробуємо створити символьний потік для зчитування

try

{

StreamReader f = new StreamReader(fileName);

// зчитуємо кількість рядків матриці

RowCount = ReadNextInt(f);

// зчитуємо кількість стовпців матриці

ColCount = ReadNextInt(f);

// переводимо показчик у потоці на новий рядок

f.ReadLine();

array = new int[RowCount,ColCount];

// зчитуємо елементи матриці у двовимірний масив array

for (int i = 0; i < RowCount; i++)

{

for (int j = 0; j < ColCount; j++)

array[i, j] = ReadNextInt(f);

f.ReadLine();

}

// закриваємо символьний потік

f.Close();

}

catch (Exception e)

{

Console.WriteLine("Помилка: {0}", e.Message);

}

}

public void SaveToFile(string fileName)

{

// пробуємо створити символьний потік для запису

try

{

StreamWriter f = new StreamWriter(fileName);

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

f.WriteLine("{0} {1}",RowCount,ColCount);

// записуємо елементи матриці у текстовий файл

for (int i = 0; i < RowCount; i++)

{

for (int j = 0; j < ColCount; j++)

// записуємо у файл через пробіл елементи i-го рядка матриці

f.Write(" {0}", array[i, j]);

// переходимо на новий рядок у файлі

f.WriteLine();

}

// закриваємо символьний потік

f.Close();

}

catch (Exception e)

{

Console.WriteLine("Помилка: {0}", e.Message);

}

}

public void Display()

{

for (int i = 0; i < RowCount; i++)

{

for (int j = 0; j < ColCount; j++)

Console.Write(" {0}", array[i, j]);

Console.WriteLine();

}

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]