
- •Язык c# и структура простой программы
- •Что такое .Net Framework
- •Что такое с#
- •Создание первой программы на с#
- •Пространство имен System
- •С# как язык Объектно-Ориентированного Программирования (ооп)
- •Состав и назначение файлов проекта
- •Структура сборки
- •Элементы языка c#
- •Базовый синтаксис с#
- •Переменные
- •Числа без знака
- •Числа со знаком
- •Числа для финансистов
- •Текстовые символы
- •Логический тип данных
- •Литералы с плавающей точкой
- •Символьные литералы
- •Строковые литералы
- •Выражения и операторы с#
- •Инициализация переменных и оператор присваивания
- •Значение в левой части
- •Ввод данных с консоли
- •Математические операторы
- •Вычисление остатка при целочисленном делении
- •Унарные операторы
- •Унарное логическое отрицание
- •Составные операторы
- •Поразрядные операторы
- •Поразрядное логическое и
- •Поразрядное логическое или
- •Поразрядное логическое исключающее или
- •Унарная поразрядная операция дополнения
- •Поразрядный сдвиг
- •Пример использования поразрядных операторов
- •Логические операторы
- •Операторы отношения
- •Приоритеты операторов
- •Исполнители алгоритмов
- •Исполнитель Чертежник
- •Исполнитель Робот
- •Компьютер как формальный исполнитель алгоритмов
- •Блок-схема
- •Псевдокод
- •Необходимые свойства алгоритма
- •Понятие о временной сложности алгоритма
- •Примеры
- •Правила для определения сложности
- •Тернарный условный оператор
- •Применение логических операций
- •Конструкция выбора
- •Примеры применения оператора выбора
- •Объединение меток case
- •Пропущенный break
- •Пример программы: Простые числа
- •Пример обработки одномерного массива чисел
- •Использование генератора случайных данных
- •Использование оператора foreach
- •Типы задач обработки одномерных числовых массивов
- •Поиск элемента в массиве
- •Многомерные массивы
- •Базовые операции со строками
- •Методы типа string
- •Копирование и клонирование строк
- •Конкатенация строк
- •Извлечение подстроки
- •Вставка подстроки
- •Замена символов и строк
- •Удаление символов из строки
- •Удаление незначащих пробелов
- •Преобразование к верхнему и нижнему регистру
- •Выравнивание по левому и правому краю поля
- •Объединение массива строк
- •Разбор строки
- •Сравнение строк
- •Форматирование текстовых строк
- •Функции
- •Описание и использование функций
- •Возвращаемые значения
- •Передача параметров
- •Выходные параметры
- •Область действия переменных
- •Область действия переменных и управляющие конструкции
- •Рекурсия
- •Параметры функции Main()
- •Перегрузка функций
- •Перечислимый тип
- •Определение перечислимых типов
- •Структуры
- •Описание структур
- •Использование структур в качестве параметров функций
- •Использование структур в качестве возвращаемых значений функций
- •Функции структур
- •Файлы и потоки
- •Основные классы ввода и вывода
- •Классы для работы с потоками
- •Классы для работы с потоками текстовых символов
- •Работа с текстовыми файлами
- •Запись двоичных данных
- •Пример программы для работы с двоичным файлом
- •Просмотр содержимого каталога
- •Получение информации о каталоге
Работа с текстовыми файлами
Текстовые файлы содержат символьную информацию, но, как и двоичные, тоже состоят из байтов. Поэтому потоки FileStream, BinaryWriter и BinaryReader можно использовать для записи в файлы и чтения из файлов текстовых строк, но лучше применять специально предназначенные для этого средства. Речь идет о потоках классов StreamWriter и StreamReader. Эти потоки чрезвычайно просты в использовании и удобны для работы с текстовыми файлами.
Основные приемы использования потоков StreamWriter и StreamReader демонстрируются в программе, исходный текст которой приведен ниже:
using System;
using System.IO;
namespace TextFile
{
class Program
{
static string testFile = "mydata.txt";
static void Main(string[] args)
{
if (File.Exists(testFile))
{
Console.WriteLine("Файл {0} уже существует", testFile);
Console.ReadLine();
return;
}
StreamWriter sw = File.CreateText(testFile);
sw.WriteLine("Каждый охотник желает знать, где сидит фазан!");
sw.WriteLine("Число \"Пи\" равно примерно {0}.", 3.1415926);
sw.Close();
StreamReader sr = File.OpenText(testFile);
while (true)
{
string str = sr.ReadLine();
if (str == null)
break;
Console.WriteLine(str);
}
sr.Close();
Console.WriteLine("Файл успешно создан");
Console.ReadLine();
}
}
}
Данная программа сразу после запуска проверяет существование рабочего файла в текущем каталоге:
if (File.Exists(testFile))
{
Console.WriteLine("Файл {0} уже существует", testFile);
Console.ReadLine();
return;
}
Если файл с именем mydata.txt существует в текущем каталоге, программа завершает свою работу с сообщением об ошибке. В противном случае программа создает текстовый файл и открывает поток для работы с ним класса StreamWriter:
StreamWriter sw = File.CreateText(testFile);
Как видите, эта операция выполняется методом CreateText, определенным в классе File. Аналогичного эффекта можно было бы достичь и с помощью следующего конструктора класса StreamWriter:
StreamWriter sw = new StreamWriter(testFile, false);
Первый параметр этого конструктора определяет полный путь к открываемому файлу. Если значение второго параметра равно true, новые данные будут добавлены к файлу, а если false — содержимое файла будет перезаписано.
Для открытия текстового файла на запись вы можете использовать любой из этих конструкторов. Заметим, что в классе StreamWriter имеются и другие конструкторы, позволяющие, например, задать кодировку текстовых символов, записываемых в файл.
После того как поток StreamWriter открыт, программа может записывать в него текстовые строки, пользуясь хорошо известными вам методами Write и WriteLine:
sw.WriteLine("Каждый охотник желаетзнать, где сидит фазан!");
sw.WriteLine ("Число \"Пи\" равно примерно {0}.", 3.1415926);
Когда запись новых данных в поток завершена, необходимо закрыть поток методом Close:
sw.Close();
Теперь о чтении данных из текстового файла. Прежде всего, программа должна открыть поток класса StreamReader, привязав его к файлу. Это можно сделать методом File.OpenText:
StreamReader sr = File.OpenText(testFile);
Вы можете также открыть поток и привязать его к файлу с помощью конструктора класса StreamReader:
StreamReader sr = new StreamReader(testFile);
Далее наша программа считывает текстовые строки из файла, вызывая в цикле метод ReadLine:
while(true)
{
string str = sr.ReadLine();
if(str == null)
break;
Console.WriteLine(str);
}
Этот метод возвращает прочитанную строку или значение null при достижении конца файла. После завершения работы с потоком StreamReader его следует закрыть методом Close:
sr.Close();
Таким образом, приведенная выше программа записывает две строки в файл, а затем читает их оттуда и отображает на консоли:
При повторном запуске, однако, результат будет совершенно другой:
Это совершенно нормально, т.к. программа включает проверку существования файла и в случае его обнаружения завершает работу.
Работа с двоичными файлами
Открытие потока FileStream
Для работы с двоичными файлами программа должна вначале создать поток класса FileStream, воспользовавшись соответствующим конструктором, например:
FileStream fs = new FileStream("myfile.dat", FileMode.CreateNew);
В качестве первого параметра конструктору необходимо передать полный путь к файлу или имя файла, а в качестве второго — режим открытия потока:
Режимы открытия файла FileMode
-
Режим
Описание
Append
Если файл существует, он открывается. Текущая позиция устанавливается на конец файла. Если указанного файла нет, то он создается. Этот режим можно использовать только совместно с режимом доступа FileAccess.Write. При попытке чтения из файла, открытого подобным образом, возникает исключительная ситуация
Create
ОС должна создать новый файл. Если указанный файл уже существует, он будет перезаписан
CreateNew
ОС должна создать новый файл. Если указанный файл уже существует, возникнет исключительная ситуация
Open
Требуется открыть существующий файл. Необходим доступ FileIOPermissionAccess.Read. Если требуемый файл не найден, возникает исключительная ситуация
OpenOrCreate
Если указанный файл существует, он должен быть открыт. В противном случае ОС должна создать и открыть указанный файл
Truncate
Требуется открыть существующий файл. После открытия файл обрезается до нулевой длины, при этом все ранее хранившиеся в нем данные пропадают. При попытке чтения из файла, открытого подобным образом, возникает исключение
В зависимости от того, для какой цели создается файл, вы можете выбрать тот или иной режим открытия потока. Например, если поток, связанный с файлом, открывается только для чтения, выбирайте режим FileMode.Open. В этом случае будет открыт существующий файл. Если же файл открывается для записи, то вы можете либо открыть существующий файл, перезаписав его содержимое или дописав в него новые данные, а также создать новый файл.
В классе FileStream существует несколько конструкторов, позволяющих определить не только путь к файлу, но и режим его открытия, разрешенный доступ к файлу и режим совместного использования файла:
FileStream fs1 = new FileStream(name, FileMode.Open, FileAccess.Read);
FileStream fs2 = new FileStream(name, FileMode.Open, FileAccess.Read,FileShare.Read);
Режим доступа к файлу, передаваемый приведенным выше конструкторам через третий параметр, задается как константа класса FileAccess:
Режимы доступа FileAccess
Режим |
Тип доступа |
Read |
Доступ только на чтение |
ReadWrite |
Доступ на чтение и запись |
Write |
Доступ на запись |
При необходимости при открытии можно задать режим совместного использования файла, когда несколько для одного и того же файла одновременно создается потоков различными программами. Этот режим задается при помощи констант класса FileShare:
Режимы совместного использования файла FileShare
Режим |
Тип доступа |
Inheritable |
Идентификатор файла может наследоваться дочерним процессом |
None |
Запрет совместного использования файла. Любые дополнительные запросы на открытие файла будут запрещены то тех пор, пока файл не будет закрыт |
Read |
Допускаются дополнительные запросы на открытие файла для чтения |
ReadWrite |
Допускаются дополнительные запросы на чтение и запись |
Write |
Допускаются дополнительные запросы на запись |
Открытие и закрытие потоков BinaryWriter и BinaryReader
Первый шаг к работе с файлом - создание потока на базе этого файла с использованием класса FileStream. Далее на базе полученного таким образом потока необходимо создать потоки классов BinaryWriter или BinaryReader, предназначенные соответственно для записи в файл и чтения из файла двоичных данных:
BinaryWriter bw = new BinaryWriter(fs);
BinaryReader br = new BinaryReader(fs);
Работа с открытыми потоками записи или чтения осуществляется в соответствии с алгоритмом решения задачи.
После того как программа завершила работу с потоками, она должна их закрыть. Для закрытия потоков используется метод Close. Потоки необходимо закрывать в порядке, обратном их открытию. Если вначале был открыт поток FileStream, а затем на его базе созданы потоки класса BinaryWriter и BinaryReader, то закрывать потоки нужно в обратном порядке: вначале потоки BinaryWriter и BinaryReader, а затем поток FileStream:
FileStream fs = new FileStream("myfile.dat", FileMode.CreateNew);
BinaryWriter bw = new BinaryWriter(fs);
BinaryReader br = new BinaryReader(fs);
// Работа с потоками
bw.Close();
br.Close();
fs.Close();