Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 10 Бинарные файлы.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
165.81 Кб
Скачать

10.3.6. Запись и чтение типизированного файла

Понятия типизированный файл в C# нет, но можно смоделировать это понятие. Рассмотрим процесс записи и чтения полей класса Group, имеющего два поля: ID – целого типа и Name – типа string. Так как мы хотим сохранить механизм прямого доступа, то поле Name должно иметь фиксированную длину. Поэтому введем класс короткой строки ShortString, у объектов которого свойство s всегда имеет длину Len:

Листинг 11.16. Класс короткой строки ShortSting

class ShortSting

{

public int Len;

string fs; // поле fs

public string s { // свойство s

get { return fs; }

set {fs = value; fs = fs.PadRight(Len);}

}

// Конструктор

public ShortSting(int val, string st)

{

Len = val;

s = st;

}

}

Если длина строки короче Len, то метод PadRight() дополняет ее справа пробелами.

Класс Group содержит в себе три поля (name, ID, size), конструктор Group() и три метода Write(), Read() и Output():

Листинг 10.17. Поля и методы класса Group

class Group

{

public ShortSting Name;

public int ID;

int size;

Char[] charData;

byte[] byData;

byte[] byByte;

public Group(int ID, string st)

// конструктор

public void Write(FileStream aFile, int adr)

// метод записи

public void Read(FileStream aFile, int adr)

// метод чтения

public void Output(FileStream aFile)

// метод вывода

}

В конструкторе Group(int ID, string st) заполняется два поля, ID и Name, и вычисляется размер size записываемых полей структуры:

size = sizeof(int) + 2*this.Name.Len;

При вычислении учитывается, что для строки необходимо в два раза байт больше.

Листинг 10.18. Конструктор класса Group

public Group(int ID, string st)

{

this.ID = ID;

this.Name = new ShortSting(20,st);

size = sizeof(int) + 2*this.Name.Len;

byData = new byte[size];

charData = new char[Name.Len];

}

Метод записи готовит для записи массив byData[] и записывает его. Для каждого поля (ID и name) используется вспомогательный массив byByte[], в который методом BitConverter.GetBytes() заносятся данные простых типов и методом GetBytes() для строки. Затем массив byByte[] копируется в основной массив byData[] методом byByte.CopyTo(byData, ofs):

Листинг 10.19. Метод записи

public void Write(FileStream aFile, int adr)

{

int ofs = 0;

charData = Name.s.ToCharArray();

int offset;

if (adr != -1)

offset = adr*size;

else

offset = (int)aFile.Length;

byByte = BitConverter.GetBytes(ID);

byByte.CopyTo(byData, ofs);

ofs += 4;

byByte = new byte[2 * charData.Length];

Encoder e =

Encoding.Unicode.GetEncoder();

e.GetBytes(charData, 0, charData.Length,

byByte, 0, true);

byByte.CopyTo(byData, ofs);

aFile.Seek(offset, SeekOrigin.Begin);

aFile.Write(byData, 0, size);

aFile.Flush();

}

Метод чтения читает данные в массив byData[], методами типа BitConverter.ToInt32() конвертирует часть массива в простые данные, методом GetChars() конвектирует часть массива в массив charData[], который далее используется для заполнения строки name:

Листинг 10.20. Метод чтения

public void Read(FileStream aFile, int adr)

{

aFile.Seek(adr * size, SeekOrigin.Begin);

aFile.Read(byData, 0, size);

int ofs = 0;

ID = BitConverter.ToInt32(byData, ofs);

ofs += 4;

Decoder d = Encoding.Unicode.GetDecoder();

d.GetChars(byData,ofs,2*Name.Len, charData, 0);

string s = "";

for (int i = 0; i < charData.Length; i++)

s += charData[i];

Name.s = s;

}

Метод вывода циклом for выводит все записи из файла на экран:

Листинг 10.21. Метод вывода

public void Output(FileStream aFile)

{

int L = (int)aFile.Length;

for (int i = 0; i < L / size; i++ )

{

this.Read(aFile, i);

Console.WriteLine(Name.s);

}

}

}

В методе Main() создается поток FileStream, делаются три новые записи в конец файла, замещается запись по адресу 2 и выводятся все записи.

Листинг 10.22. Метод Main() программы

class Program

{

static void Main(string[] args)

{

FileStream aFile =

new FileStream("Group.dat",FileMode.Open);

Group group = new Group(1, "1 группа");

group.Write(fw, -1);

group = new Group(2, "2 группа");

group.Write(fw, -1);

group = new Group(3, "3 группа");

group.Write(fw, -1);

group = new Group(4, "4 группа");

group.Write(fw, 2);

group.Output(aFile);

aFile.Close();

Console.ReadKey();

}

}