- •1 Файлы и потоки
- •2 Потоки данных и классы
- •2.1 Стандартные потоки
- •2.2 Базовые классы для работы с файлами и потоками
- •2.2.1 Основные классы ввода и вывода
- •2.2.2 Классы на базе FileSystemInfo
- •2.2.3 Классы для работы с потоками
- •2.2.4 Классы для работы с потоками текстовых символов
- •2.3 Перечисления
- •3 Работа со стандартными потоками
- •3.1 Стандартный поток ввода
- •3.2 Стандартный поток вывода
- •3.2.1 Стандартный поток вывода сообщений об ошибках
- •3.3 Программа StdStreams
- •4 Создание потоков, связанных с файлами
- •4.1 Открытие потока FileStream
- •4.2 Открытие потоков BinaryWriter и BinaryReader
- •4.3 Закрытие потоков
- •4.4 Запись двоичных данных
- •4.5 Чтение двоичных данных
- •4.6 Программа Binary
- •4.7 Работа с текстовыми файлами
- •5 Выбор кодировки символов
- •5.1 Кодовые страницы
- •5.2 Недостатки модели кодовых страниц
- •5.3 Стандарт UNICODE
- •5.3.1 Unicode в Microsoft Windows NT/2000/XP
- •5.3.2 UNICODE в Microsoft Windows 95
- •5.4 Кодировка текстовых потоков
- •5.5 Кодировка текстовых строк в двоичных потоках
- •6 Буферизация потоков
- •6.1 Буферизация двоичных потоков
- •6.2 Буферизация текстовых потоков
- •6.3 Принудительный сброс буферов
- •7 Потоки в оперативной памяти
- •7.1 Создание потока
- •7.2 Чтение данных
- •7.3 Запись данных
- •7.4 Доступ к буферу потока MemoryStream
- •7.5 Потоки на базе строк string
- •7.6 Потоки класса StringBuilder
- •8 Краткие выводы
- •8.1 Создание и чтение бинарного файла
- •8.2 Создание текстового файла
- •8.3 Добавление в текстовый файл
- •8.4 Чтение и запись в файл строк на русском языке
- •8.5 Посимвольное чтение текстового файла
- •8.6 Построчное чтение текстового файла
- •8.7 Чтение файла полностью
В составе Microsoft Windows 95 поставляется набор шрифтов UNICODE. Вы также можете установить в этой ОС и старые кириллические шрифты, разработанные для Microsoft Windows 3.1.
5.4 Кодировка текстовых потоков
После такого краткого введения в кодировки символов мы рассмотрим способы выбора кодировки для текстовых потоков, создаваемых в программах С#.
Кодировка символов задается в конструкторе, создающем выходной поток данных. Например, при создании потока текстовых строк StreamWriter мы можем указать в третьем параметре конструктора нужную нам кодировку:
StreamWriter sw = new StreamWriter(testFile, false, Systern.Text.Encoding.UNICODE);
Кодировка указывается как статическое свойство класса System. Text .Encoding. Возможные варианты кодировки с именами соответствующих статических свойств перечислены в табл. 5.
Кодировка
ASCII
UNICODE
UTF7
UTF8
Default
Таблица 5: Кодировки текстовых потоков
Описание
Кодировка ASCII без символов кириллицы, в которой для представления текстовых символов используются младшие 7 бит байта
Кодировка UNICODE, Для представления символов используется 16 бит {т. е. 2 байта)
Кодировка UCS Transformation Format, Применяется для представления символов UNICODE. В ней используются младшие 7 бит данных
То же, но для представления символов UNICODE в ней используется 8 бит данных
Системная кодировка ANSI (не путайте ее с кодировкой ASCII), В этой кодировке для представления каждого символа используется 8 бит данных
Заметим, что кодировка символов может быть задана только при создании потока. Если поток уже создан, программа может определить текущую кодировку символов, воспользовавшись для этого свойством Encoding:
Console.WriteLine("Кодировка файла: {0} ", sw.Encoding);
Это свойство доступно только для чтения.
В листинге 4 мы привели пример программы, создающей текстовый файл в кодировке UNICODE.
Листинг 4.
using System; using System.IO;
namespace Encoding
{
class EncodingApp
{
private const string testFile = "mydata.txt";
static void Main (string[) args)
{
if(File.Exists(testFile))
{
Console.WriteLine("Файл {0) уже существует", testFile); Console.ReadLine();
return;
}
StreamWriter sw = new StreamWriter(testFile, false. System.Text.Encoding.UNICODE); Console.WriteLine("Кодировка файла: {0}", sw.Encoding);
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();
}
}
}
От программы, исходный тскст которой был приведен ранее в листинге 3, она отличается только наличием двух строк, приведенных ниже:
StreamWriter sw = new StreamWriter[testFile, false, System.Text.Encoding.UNICODE); Console.WriteLine("Кодировка файла: {0}", sw.Encoding);
Первая из этих строк задает кодировку символов UNICODE, а вторая — отображает кодировку символов на консоли:
Колировка файла: System.Text.UNICODEEncoding Каждый охотник желает знать, где сидит фазан! Число "Пи" равно примерно 3,1415926. Файл успешно создан
На рис. 10 мы показали содержимое созданного файла в виде дампа.
Рисунок 10: Созданный файл в кодировке UNICODE
Обращаем ваше внимание, что в самом начале файла находятся байты OxFF и ОхЕЕ.
Это сигнатура, предназначенная для определения порядка следования байтов в 16разрядных символах UNICODE.
Для чего она нужна?
Стандарт UNICODE предназначен для работы на различных компьютерных платформах. Однако разные процессоры применяют различный порядок следования байтов в слове; наиболее значимый байт может быть расположен как по старшему, так и по младшему адресу.
Для правильной обработки текстового файла UNICODE на любой платформе приложение должно знать порядок следования байтов, использованный в этом файле. Для обозначения такого порядка и применяется 2-байтовая сигнатура. Ее значение может быть равно OxFEFF для прямого порядка следования байтов или OxFFEF для обратного.
5.5 Кодировка текстовых строк в двоичных потоках
Как мы уже говорили, двоичные потоки создаются с помощью классов FileStream, BinaryWriter и BinaryReader. С помощью метода Write программа может записывать в двоичный поток не только числа, но и строки класса string. Соответствующий пример программы был приведен в разделе «Программа Binary» (см. листинг 2).
Напомним, что при записи строк string в двоичный поток они снабжаются префиксом длины, вслед за которым идут байты символов. По умолчанию для представления символов применяется кодировка ANSI, однако при необходимости программа может ее изменить.
При создании выходного потока класса BinaryWriter мы можем указать конструктору необходимую кодировку текстовых символов:
FileStream fs = new FileStreamftestFile, FileMode.CreateNew); BinaryWriter bw = new BinaryWriter(fs, System.Text.Encoding.UNICODE);
В данном случае мы указали кодировку UNICODE. После этого запись строк в поток выполняется как обычно:
bw.Write("Text string");
Для того чтобы правильно прочитать текстовые строки из двоичного потока, при создании входного потока BinaryReader мы тоже должны указать кодировку:
fs = new FileStream(testFile, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs, System.Text.Encoding.UNICODE);
После этого можно будет прочитать строку из входного двоичного потока методом ReadString:
string s = br.Readstring();
Эта техника демонстрируется в программе, исходный текст которой приведен в листинге 5.
Листинг 5.
using System; using System.IO;
namespace BinaryEncoding
{
class BinaryEncodingApp
{
private const string testFile = "mydata.dat"; static void Main(string[1 args)
{
if(File.Exists(testFile))
{
Console.WriteLine("Файл {0} уже существует", testFile); Console.ReadLine();
return;
}
FileStream fs = new FileStream(testFile, FileMode.CreateNew); BinaryWriter bw = new BinaryWriter(fs, System.Text.Encoding.UNICODE);
Как выглядит текстовая строка UNICODE в созданном нами двоичном файле? Взгляните на рис. 11, где мы показали дамп этого файла.
Рисунок 11: Текст в двоичном потоке имеет кодировку UNICODE
bw.Write("Text string"); for(uint i = 0; i < 20; i++)
{
bw.Write((uint) i);
}
bw.Close(); fs.Close();
fs = new FileStreamftestFile, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs, System.Text.Encoding.UNICODE); string s = br.ReadStringО; Console.WriteLine(s);
for (uint i = 0; i < 20; i++)
{
Console.Write("{0} *, br.ReadUInt32());
}
br.Close(); fs.Close();
Console.WriteLine("\пФайл успешно создан"); Console.ReadLine();
}
}
}
Обратите внимание, что первый байт файла содержит длину текстовой строки. Вслед за этим байтом идут 2-байтовые символы UNICODE,