Файлы с последовательным и прямым доступом
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Файлы с последовательным доступом:

 


рис.3

Адр(запись i) = ???

 

Файлы с прямым доступом:

Способ 1.

 

 

рис.4

 

Length(Запись 1) = Length(Запись 2) = Length(Запись N)=const

 

Адр(Запись i) = Length(Запись) * (i-1) байт

 

Способ 2. Файл адресов записей: Адр(запись i) = Адр[i-1]

 

 

 


рис.5

 

Для доступа к требуемой записи необхо­димо использовать метод Seek(), определенный в классе FileStream. Этот метод по­зволяет установить указатель позиции (файловый указатель) в любое место файла.

Формат:

 

long Seek (long newPos, SeekOrigin origin)

  

newPos - новая позиция файлового указателя, выраженная в байтах, относительно позиции, заданной элементом origin. Перемещаться можно как вперед (+), так и назад (-).

Элемент origin мо­жет принимать одно из значений, определенных перечислением SeekOrigin:

 

Значение Описание
SeekOrigin.Begin Поиск от начала файла
SeekOrigin.Current Поиск от текущей позиции
SeekOrigin.End Поиск от конца файла

 

 

После обращению к методу Seek() следующая операция чтения или записи дан­ных будет выполняться на новой позиции в файле.

 

Исключение Описание
IOException Ошибка ввода-вывода
NotSuppotedException Базо­вый поток не поддерживает эту функцию

 

f = new FileStream ("random.dat", FileMode.Create);

 

f.Seek(0, SeekOrigin.Begin); // Переход в начало файла.

f.Seek(4, SeekOrigin.Begin); // Поиск пятого байта (№ б. = 4).

 

f.Seek(-10, SeekOrigin.End); // Поиск одиннадцатого байта от конца.

// Демонстрация произвольного доступа к файлу.

// Записать в файл алфавит прописными буквами,

// а затем выборочно считать его.

using System;

using System.IO;

class RandomAccessDemo

{

public static void Main()

{

   FileStream f;

   char ch;

   try

   {

       f = new FileStream ("random.dat", FileMode.Create);

   }

   catch (IOException exc)

   {

       Console.WriteLine (exc.Message);

       return;

   }

   // Записываем в файл алфавит.

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

   {

       try

       {

           f.WriteByte ((byte)('A' + i));

       }

       catch (IOException exc)

       {

           Console.WriteLine (exc.Message);

           return;

       }

   }

   try

   {

       // Теперь считываем отдельные значения.

       f.Seek (0, SeekOrigin.Begin); // Поиск первого байта.

       ch = (char)f.ReadByte();

       Console.WriteLine("Первое значение равно " + ch);

 

       f.Seek (1, SeekOrigin.Begin); // Поиск второго байта.

       ch = (char)f.ReadByte();

       Console.WriteLine("Второе значение равно " + ch);

       f.Seek (4, SeekOrigin.Begin); // Поиск пятого байта.

       ch = (char)f.ReadByte();

       Console.WriteLine ("Пятое значение равно " + ch);

       Console.WriteLine ();

 

       // Теперь считываем значения через одно.

       Console.WriteLine ("Выборка значений через одно: ");

       for (int i = 0; i < 26; i += 2)

       {

           f.Seek (i, SeekOrigin.Begin);          // Переход к i-му байту.

           ch = (char)f.ReadByte();

           Console.Write (ch + " ");

       }

   }

   catch (IOException exc)

   {

       Console.WriteLine (exc.Message);

   }

   Console.WriteLine();

   f.Close();

}

}

 

При выполнении этой программы получены такие результаты:

Первое значение равно А

Второе значение равно В

Пятое значение равно Е

Выборка значений через одно: ACEGIKMOQSUWY

 

Проблемы.

Строки имеют переменную длину (по фактическому содержимому). Решением проблемы м.б.: 1) добаление к строкам пробелов до одинаковой длины методом PadRicht(); 2) преобразование строки в массив символов методом ToCharArray().

 

В кодировке, используемой по умолчанию (UTF8), русские буквы кодируются двумя байтами, а английские – одним. Решение проблемы: указывать кодировку явно, например, System.Text.Encoding.Unicode.

 



Кодировка текстовых потоков

 

В C# используются следующие статические свойства класса System.Text.Encoding для кодировки текстовых потоков

 

Кодировка Описание
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).

 

Примеры произвольного доступа к записям.

Задача 1.

/*          

Разработать класс «Студент». Каждый студент определяется полями:

Фамилия, имя (тип string);

Год рождения (тип int);

Средний балл за предыдущий год обучения или за вступ. экзамен (тип float).

 

Создать программу учета студентов группы (в виде массива). Информацию о студентах ввести с клавиатуры. Признаком конца списка является ввод пробела в качестве фамилии студента.

 

Вывести на экран информацию обо всех студентах.

 

Информацию обо всех студентах сохранить в файле С:\Temp\GroupDirect.bin с произвольным доступом. Обеспечить постоянную длину всех записей. */

 

using System;

using System.IO;

using System.Collections;

 

class Student

{

public string fio;

public uint   yar;

public float ball;

 

public Student(string f, uint y, float b)

{

   fio = f;

   yar = y;

   ball = b;

}

public void Show()

{

   Console.WriteLine("Студент {0}, год рождения {1}, ср.балл = {2}",

                     fio, yar, ball);

}

}

 

class Example1

{

public static void Main()

{

   string      fio = " ";

   uint       god = 0, n = 1;

   float         ball = 0;

   Student   std;

   BinaryWriter dataOut;

   FileStream  fs;

 

 

   ArrayList tableStd = new ArrayList();

 

   while (true)

   {

      Console.WriteLine(

       "\n____________________Студент {0}____________________________",

                                                                            n);

       Console.Write(

         "Введите фамилию (не > 15 символов, пробел - конец списка): ");

       fio = Console.ReadLine();

       if (fio == " " || fio.Length == 0)

           break;

       try

       {

           Console.Write("Введите год рождения: ");

           god = uint.Parse(Console.ReadLine());

 

           Console.Write("Введите средний балл: ");

           ball = float.Parse(Console.ReadLine());

       }

       catch

       {

      Console.WriteLine("==ОШИБКА== Неверный формат ввода. Повторите!");

          continue;

       }

 

       std = new Student(fio, god, ball);

       tableStd.Add(std);

       n++;

   }

 

   // Таблица создана. выведем ее на экран и сохраним в файле

   Console.WriteLine("\n");

 

   try

   {

       fs = new FileStream(@"c:\Temp\GroupDirect.bin", FileMode.Create,

                                                                                                                                    FileAccess.Write);

       dataOut = new BinaryWriter(fs, System.Text.Encoding.Unicode);

 

 

       for (int i = 0; i < tableStd.Count; i++)

       {

           std = (Student)tableStd[i];

           std.Show();

 

           dataOut.Write("Студент");

           fio = std.fio.PadRight(15);

           dataOut.Write(fio);

           dataOut.Write(std.yar);

           dataOut.Write(std.ball);

       }

   }

 

   catch (Exception e)

   {

       Console.WriteLine("Error: " + e.Message);

       return;

   }

   fs.Close();

}

}

 

Задача 2.

/*   

Вывести на экран информацию из файла С:\Temp\GroupDirect.bin

о студентах, заданных порядковым номером.

Номера студентов ввести с клавиатуры.

Первый студент имеет номер 1.

Признаком конца списка является ввод 0 в качестве номера студента.

*/

 

using System;

using System.IO;

using System.Collections;

using System.Text;

 

class Example

{

public static void Main()

{

   string fio;

   uint god;

   float ball;

 

   uint N; // порядковый номер студента в файле

 

   string str;

   string path = @"c:\Temp\GroupDirect.bin";

   uint kRec;                         // количество записей

   const uint lRec = (7*2+1)+(15*2+1)+4+4; // длина записи

                                                                                                             // (Студент,fio,god,ball) 

 

if (!File.Exists(path))

{

     Console.WriteLine("Файл отсутствует.");

     return;

}

 

FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);

BinaryReader dataIn = new BinaryReader(fs, Encoding.Unicode);

 

kRec = (uint)fs.Length / lRec; //кол.записей = длина файла /

                                                                                                                                                длина записи

Console.WriteLine("В файле студентов: {0}", kRec);

 

while (true)

{

              

      Console.WriteLine("\n__________________________________________");

      Console.Write("Введите номер студента (0 - конец поиска): ");

     try

     {

           N = uint.Parse(Console.ReadLine());

     }

     catch

     {

           Console.WriteLine("==ОШИБКА== Повторите ввод целого числа.");

           continue;

     }

     if (N == 0) break;

 

     if (N > kRec)

     {

        Console.WriteLine("\n==ОШИБКА== Студента с таким номером нет.");

        Console.WriteLine("   Всего в файле студентов: {0}", kRec);

        continue;

     }

 

    // Позиционируем указатель записи

   fs.Seek((N - 1) * lRec, SeekOrigin.Begin);

   try

   {

     str = dataIn.ReadString();

     fio = dataIn.ReadString();

     god = dataIn.ReadUInt32();

     ball = dataIn.ReadSingle();

 

     Console.WriteLine("Студент {0}, год рождения {1}, ср.балл = {2}\n",

                                fio,         god,     ball);

   }

  catch (Exception e)

  {

      Console.WriteLine("Error: " + e.Message);

      return;

  }

}

fs.Close();

}

}

 

 



Дата: 2019-02-02, просмотров: 244.