Файлы с последовательным и прямым доступом
Файлы с последовательным доступом:
рис.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:
|
После обращению к методу 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.
Дата добавления: 2019-02-08; просмотров: 634;