Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






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






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

 
 

 


рис.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();

}

}

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.