Кодировка | Описание |
ASCII | Кодировка ASCII без символов кириллицы, в которой для представления текстовых символов используются младшие 7 бит байта |
Unicode | Кодировка UNICODE. Для представления символов используется 16 бит (т. е. 2 байта). Сигнатура = FF FE в нач.файла для StreamWriter |
UTF7 | Кодировка UCS Transformation Format. Применяется для представления символов UNICODE. В ней используются младшие 7 бит данных |
UTF8 | To же, но для представления символов UNICODE в ней используется 8 бит данных |
Default | Системная кодировка ANSI (не путайте ее с кодировкой ASCII). В этой кодировке для представления каждого символа используется 8 бит данных |
Свойства класса кодировки System.Text.Encoding:
ASCII – 1 байт (старший бит = 0);
Default – по умолчанию (UTF8);
Unicode – 2 байта;
UTF32 – 4 байта;
UTF7 – 1 байт, старший бит не используется;
UTF8 – 1 байт (по умолчанию в .NET).
ФАЙЛЫ В ОП, ДВОИЧНЫЕ ПОТОКИ,
НЕПОТОКОВЫЙ ВВОД-ВЫВОД, ПРЯМОЙ ДОСТУП К ФАЙЛУ.
Файлы в оперативной памяти
Присоединение массива байтов к классам StreamReader или StreamWriter.
Класс MemoryStream
Иногда удобно создать модель файла в ОП. В этом случае нужно заменить открытие файла на создание потока в памяти.
Класс MemoryStream определяет поток байтов в оперативной памяти (см. рис.1). Класс MemoryStream — это реализация класса Stream.
рис.1
Для работы с этим потоком могут использоваться классы StreamReader и StreamWriter. С помощью их методов можно считывать входные данные из массива байтов или записывать их в массив.
Один из конструкторов класса MemoryStream:
MemoryStream (byte[ ] buf)
buf — это массив байтов, который предполагается использовать в операциях ввода-вывода в качестве источника и/или приемника информации.
• Поток доступен как на чтение, так и на запись.
• В поток, создаваемый этим конструктором, можно записывать данные или считывать их из него.
• Перед использованием этого конструктора необходимо позаботиться о достаточном размере массива buf, чтобы он позволил сохранить все направляемые в него данные.
• Этот поток поддерживает метод Seek(), который позволяет перед выполнением чтения/записи сместиться к любому байту массива.
Пример:
// Демонстрация использования класса MemoryStream.
using System;
using System.IO;
class MemStrDemo
{
public static void Main()
{
byte[ ] storage = new byte[255]; // Модель файла
// Создаем поток с ориентацией на память.
MemoryStream mem = new MemoryStream (storage);
// Помещаем объект mem в оболочку StreamWriter.
StreamWriter memWtr = new StreamWriter (mem);
// Записываем данные в память с помощью объекта memWtr.
for (int i = 0; i < 10; i++)
memWtr.WriteLine ("byte [{0}]: {0}", i);
memWtr.Write ('.'); // Ставим в конце точку.
memWtr.Flush (); // Форсируем вывод
Console.WriteLine ("Считываем данные прямо из массива storage: ");
// Отображаем напрямую содержимое памяти.
foreach (char ch in storage)
{
if (ch == '.') break; // После точки будет EOF, который является концом строки.
Console.Write (ch);
}
Console.WriteLine("\nСчитываем данные посредством объекта memRdr: ");
// Помещаем объект mem в оболочку StreamReader.
StreamReader memRdr = new StreamReader (mem);
// Считываем данные из объекта mem, используя средство чтения потоков.
mem.Seek (0, SeekOrigin.Begin); // Установка указателя позиции
// в начало потока.
string str = memRdr.ReadLine();
while (str != null)
{
str = memRdr.ReadLine();
if (str.CompareTo(".") == 0) break; // После точки следует EOF,
// поэтому точка считывается как строка.
Console.WriteLine(str);
}
}
}
Вот как выглядят результаты выполнения этой программы:
Считываем данные прямо из массива storage:
byte [0] : 0
byte [1] : 1
byte [2] : 2
byte [3] : 3
byte [4] : 4
byte [5] : 5
byte [6] : 6
byte [7] : 7
byte [8] : 8
byte [9] : 9
Считываем данные посредством объекта memRdr:
byte [0] : 0
byte [1] : 1
byte [2] : 2
byte [3] : 3
byte [4] : 4
byte [5] : 5
byte [6] : 6
byte [7] : 7
byte [8] : 8
byte [9] : 9
Вместо
mem.Seek (0, SeekOrigin.Begin);
можно применить
memWtr.Close();
mem = new MemoryStream (storage);
Классы StringReader и StringWriter
Если удобнее работать не с массивом байтов в ОП (класс MemoryStream), а с массивом строк, то целесообразно использовать классы StringReader и StringWriter (наследники классов TextReader и TextWriter).
Конструкторы:
StringReader (string str);
StringWriter();
Строка особого формата автоматически создается конструктором StringWriter().
using System;
using System.IO;
class StrRdrDemo
{
public static void Main()
{
// Создаем объект класса StringWriter.
StringWriter strWtr = new StringWriter();
// Записываем данные в StringWriter-объект.
for ( int i = 0; i < 10; i++ )
strWtr.WriteLine ("Значение i равно: " + i);
// Создаем объект класса StringReader.
StringReader strRdr = new StringReader (strWtr.ToString());
string str;
do
{
str = strRdr.ReadLine(); // Считываем данные из StringReader-объекта.
Console.WriteLine(str);
} while (str != null);
}
}
Двоичные потоки
Для выполнения операций ввода/вывода данных различных типов без их преобразований предназначены классы BinaryReader и ВinaryWriter. Важно понимать, что эти данные считываются и записываются с использованием внутреннего двоичного формата, а не в текстовой форме, понятной человеку.
Классы BinaryReader и ВinaryWriter представляют собой оболочку для байтового потока, которая управляет чтением\записью двоичных данных.
рис.2
Наиболее употребительный конструктор класса BinaryWriter имеет вид:
BinaryWriter ( Stream stream [, Encoding] )
Наиболее употребительный конструктор класса BinaryReader имеет вид:
BinaryReader (Stream stream [, Encoding])
stream - поток, в который будут записываться/ считываться данные.
Чтобы записать двоичные данные в файл или прочитать из файла, можно использовать для этого параметра объект, созданный классом FileStream.
Методы вывода данных класса BinaryWriter
Метод | Описание |
void Write (sbyte val) | Записывает byte-значение (со знаком) |
void Write (byte val) | Записывает byte-значение (без знака) |
void Write (byte [ ] buf) | Записывает массив byte-значений |
void Write (short val) | Записывает целочисленное значение типа short короткое целое) |
void Write (ushort val) | Записывает целочисленное ushort -значение (короткое целое без знака) |
void Write (int val) | Записывает целочисленное значение типа int |
void Write (uint val) | Записывает целочисленное uint-значение (целое без знака) |
void Write (long val) | Записывает целочисленное значение типа long (длинное целое) |
void Write (ulong val) | Записывает целочисленное ulong-значение (длинное целое без знака) |
void Write (float val) | Записывает float-значение |
void Write (double val) | Записывает double-значение |
void Write (char val) | Записывает символ |
void Write (char [ ] buf) | Записывает массив символов |
void Write (string val) | Записывает string-значение с использованием его внутреннего представления, которое включает спецификатор длины |
Методы ввода данных, определенные в классе BinaryReader
Метод | Описание |
bool ReadBoolean() | Считывает bool-значение |
byte ReadByte() | Считывает byte-значение |
sbyte ReadSByte() | Считывает sbyte-значение |
byte[ ] ReadBytes(int num) | Считывает num байтов и возвращает их в виде массива |
char ReadChar() | Считывает char-значение |
char[ ] ReadChars(int num) | Считывает num символов и возвращает их в виде массива |
double ReadDouble() | Считывает double-значение |
float ReadSingle() | Считывает float-значение |
short Readlnt16() | Считывает short-значение |
int Readlnt32() | Считывает int-значение |
long Readlnt64() | Считывает long-значение |
ushort ReadUInt16() | Считывает ushort -значение |
uint ReadUInt32() | Считывает uint-значение |
ulong ReadUInt64() | Считывает ulong-значение |
string ReadString() | Считывает string-значение, представленное во внутреннем двоичном формате, который включает спецификатор длины. Этот метод следует использовать для считывания строки, которая была записана с помощью объекта класса BinaryWriter |
int Read () | Возвращает целочисленное представление следующего доступного символа из вызывающего входного потока. При обнаружении конца файла возвращает значение -1 |
int Read (byte [ ] buf, int offset, int num) | Делает попытку прочитать num байтов в массив buf, начиная с элемента buf[offset], и возвращает количество успешно считанных байтов |
int Read (char [ ] buf, int offset, int num) | Делает попытку прочитать num символов в массив buf, начиная с элемента buf[offset], и возвращает количество успешно считанных символов |
Исключения, генерируемые классами BinaryReader и ВinaryWriter:
ArgumentException | поток stream не открыт для ввода/вывода |
ArgumentNullException | поток stream имеет null-значение |
IOException | ошибка ввода/вывода |
EndOfStreamException | Обнаружен конец потока (для Read...) |
Пример. (Без обработки исключений.)
// Запись в файл двоичных данных с последующим их считыванием.
using System;
using System.IO;
class RWData
{
public static void Main()
{
BinaryWriter dataOut;
BinaryReader dataIn;
FileStream fs;
int i = 10;
double d = 1023.56;
bool b = true;
fs = new FileStream ("testdata", FileMode.Create);
dataOut = new BinaryWriter (fs);
dataOut.Write (i);
dataOut.Write (d);
dataOut.Write (b);
dataOut.Write (12.2 * 7.4);
dataOut.Close();
// Теперь попробуем прочитать эти данные.
fs = new FileStream ("testdata", FileMode.Open);
dataIn = new BinaryReader(fs);
i = dataIn.ReadInt32();
d = dataIn.ReadDouble();
b = dataIn.ReadBoolean();
d = dataIn.ReadDouble();
dataIn.Close();
Console.WriteLine ("Прочитали " + i);
Console.WriteLine ("Прочитали " + d);
Console.WriteLine ("Прочитали " + b);
Console.WriteLine ("Прочитали " + d);
}
}
Пример. С обработкой исключений.
// Запись в файл двоичных данных с последующим их считыванием.
using System;
using System.IO;
class RWData
{
public static void Main()
{
BinaryWriter dataOut;
BinaryReader dataIn;
FileStream fs;
int i = 10;
double d = 1023.56;
bool b = true;
try
{
fs = new FileStream("testdata", FileMode.Create);
dataOut = new BinaryWriter(fs);
}
catch (IOException exc)
{
Console.WriteLine(exc.Message + "\nHe удается открыть файл.");
return;
}
try
{
dataOut.Write(i);
dataOut.Write(d);
dataOut.Write(b);
dataOut.Write(12.2 * 7.4);
}
catch (IOException exc)
{
Console.WriteLine(exc.Message +
"\nОшибка при записи.");
}
dataOut.Close();
// Теперь попробуем прочитать эти данные.
try
{
fs = new FileStream("testdata", FileMode.Open);
dataIn = new BinaryReader(fs);
}
catch (FileNotFoundException exc)
{
Console.WriteLine(exc.Message + "\nHe удается открыть файл.");
return;
}
try
{
i = dataIn.ReadInt32();
d = dataIn.ReadDouble();
b = dataIn.ReadBoolean();
d = dataIn.ReadDouble();
}
catch (IOException exc)
{
Console.WriteLine(exc.Message + "Ошибка при считывании.");
}
dataIn.Close();
Console.WriteLine("Прочитали " + i);
Console.WriteLine("Прочитали " + d);
Console.WriteLine("Прочитали " + b);
Console.WriteLine("Прочитали " + d);
}
}
Дата: 2019-02-02, просмотров: 305.