![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Файлы с последовательным и прямым доступом ⇐ ПредыдущаяСтр 8 из 8
Файлы с последовательным доступом:
рис.3 Адр(запись i) =???
Файлы с прямым доступом:
рис.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() следующая операция чтения или записи данных будет выполняться на новой позиции в файле.
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 для кодировки текстовых потоков
Свойства класса кодировки 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(); } }
|