Файлы с последовательным и прямым доступом
Файлы с последовательным доступом:
рис.3
Адр(запись i) = ???
Файлы с прямым доступом:
Запись 1 |
Запись 2 |
• • • |
Запись N |
рис.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.
© ООО «Знанио»
С вами с 2009 года.