KnigaRead.com/
KnigaRead.com » Разная литература » Прочее » Герберт Шилдт - C# 4.0 полное руководство - 2011

Герберт Шилдт - C# 4.0 полное руководство - 2011

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Герберт Шилдт - C# 4.0 полное руководство - 2011". Жанр: Прочее издательство неизвестно, год неизвестен.
Перейти на страницу:

Console.WriteLine("Чтение " + str);

}

catch(IOException exc) {

Console.WriteLine("Ошибка ввода-вывода:n" + exc.Message);

} finally {

dataln.Close ();

}

}

}

Вот к какому результату приводит выполнение этой программы.

Запись 10 Запись 1023.56 Запись True Запись 90.28 Запись Это тест

Чтение 10 Чтение 1023.56 Чтение True Чтение 90.28 Чтение Это тест

Если просмотреть содержимое файла testdata, который получается при выполнении этой программы, то можно обнаружить, что он содержит данные в двоичной, а не в удобочитаемой текстовой форме.

Далее следует более практический пример, демонстрирующий, насколько эффективным может быть двоичный ввод-вывод. Для учета каждого предмета хранения на складе в приведенной ниже программе сначала запоминается наименование предмета, имеющееся в наличии, количество и стоимость, а затем пользователю предлагается ввести наименование предмета, чтобы найти его в базе данных. Если предмет найден, отображаются сведения о его запасах на складе.

/* Использовать классы BinaryReader и BinaryWriter для

реализации простой программы учета товарных запасов. */

using System; using System.10;

class Inventory {

static void Main() {

BinaryWriter dataOut;

BinaryReader dataln;

string item; // наименование предмета

int onhand; // имеющееся в наличии количество

double cost; // цена

try {

dataOut = new

BinaryWriter(new FileStream("inventory.dat", FileMode.Create));

}

catch(IOException exc) {

Console.WriteLine("He удается открыть файл " +

"товарных запасов для вывода");

Console.WriteLine("Причина: " + exc.Message); return;

}

// Записать данные о товарных запасах в файл, try {

dataOut.Write("Молотки"); dataOut.Write(10); dataOut.Write(3.95);

dataOut.Write("Отвертки"); dataOut.Write(18); dataOut.Write(1.50);

dataOut.Write("Плоскогубцы"); dataOut.Write(5);

dataOut.Write (4.95);

dataOut.Write("Пилы"); dataOut.Write (8); dataOut.Write(8.95);

}

catch(IOException exc) {

Console.WriteLine("Ошибка записи в файл товарных запасов");

Console.WriteLine("Причина: " + exc.Message);

} finally {

dataOut.Close();

}

Console.WriteLine() ;

// А теперь открыть файл товарных запасов для чтения, try {

dataln = new

BinaryReader(new FileStream("inventory.dat", FileMode.Open));

}

catch(IOException exc) {

Console.WriteLine("He удается открыть файл " +

"товарных запасов для ввода");

Console.WriteLine("Причина: " + exc.Message); return;

}

// Найти предмет, введенный пользователем.

Console.Write("Введите наименование для поиска: "); string what = Console.ReadLine() ;

Console.WriteLine();

try {

for (;;)    {

// Читать данные о предмете хранения, item = dataln.ReadString() ; onhand = dataln.Readlnt32() ; cost = dataln.ReadDouble();

// Проверить, совпадает ли он с запрашиваемым предметом.

// Если совпадает, то отобразить сведения о нем.

if(item.Equals(what, StringComparison.OrdinallgnoreCase)) {

Console.WriteLine(item + ": " + onhand + " штук в наличии. " +

"Цена: {0:С} за штуку", cost);

Console.WriteLine("Общая стоимость по наименованию <{0}>: {1:С}.", item, cost * onhand);

break;

}

}

}

catch(EndOfStreamException) {

Console.WriteLine("Предмет не найден.");

catch(IOException exc) {

Console.WriteLine("Ошибка чтения из файла товарных запасов");

Console.WriteLine("Причина: " + exc.Message);

} finally {

dataln.Close();

} '

}

}

Выполнение этой программы может привести, например, к следующему результату.

Введите наименование для поиска: Отвертки

Отвертки: 18 штук в наличии. Цена: $1.50 за штуку.

Общая стоимость по наименованию <Отвертки>: $27.00.

Обратите внимание на то, что сведения о товарных запасах сохраняются в этой программе в двоичном формате, а не в удобной для чтения текстовой форме. Благодаря этому обработка числовых данных может выполняться без предварительного их преобразования из текстовой формы.

Обратите также внимание на то, как в этой программе обнаруживается конец файла. Методы двоичного ввода генерируют исключение EndOf StreamException по достижении конца потока, и поэтому файл читается до тех пор, пока не будет найден искомый предмет или сгенерировано данное исключение. Таким образом, для обнаружения конца файла никакого специального механизма не требуется.

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

В предыдущих примерах использовались последовательные файлы, т.е. файлы со строго линейным доступом, байт за байтом. Но доступ к содержимому файла может быть и произвольным. Для этого служит, в частности, метод Seek (), определенный в классе FileStream. Этот метод позволяет установить указатель положения в файле, или так называемый указатель файла, на любое место в файле. Ниже приведена общая форма метода Seek ():

long Seek(long offset, SeekOrigin origin)

где offset обозначает новое положение указателя файла в байтах относительно заданного начала отсчета (origin). В качестве origin может быть указано одно из приведенных ниже значений, определяемых в перечислении SeekOrigin.

Значение

Описание

SeekOrigin.Begin

Поиск от начала файла

SeekOrigin.Current

Поиск от текущего положения

SeekOrigin.End

Поиск от конца файла

Следующая операция чтения или записи после вызова метода Seek () будет выполняться, начиная с нового положения в файле, возвращаемого этим методом. Если во время поиска в файле возникает ошибка, то генерируется исключение IOException. Если же запрос положения в файле не поддерживается базовым потоком, то генерируется исключение NotSupportedException. Кроме того, могут быть сгенерированы и другие исключения.

В приведенном ниже примере программы демонстрируется ввод-вывод в файл с произвольным доступом. Сначала в файл записываются прописные буквы английского алфавита, а затем его содержимое считывается обратно в произвольном порядке.

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

using System; using System.10;

class RandomAccessDemo { static void Main() {

FileStream f = null; char ch;

try {

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

// Записать английский алфавит в файл, for (int i=0; i < 26; i++) f.WriteByte((byte)('A'+i));

//А теперь считать отдельные буквы английского алфавита. f.Seek(0, SeekOrigin.Begin); // найти первый байт ch = (char) f. ReadByte () ;

Console.WriteLine("Первая буква: " + ch) ;

f.Seek(l, 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);

'} finally {

if(f != null) f.Close();

}

Console.WriteLine() ;

}

}

При выполнении этой программы получается следующий результат.

Перзая буква: А Вторая буква: В Пятая буква: Е

Буквы алфавита, через одну:

АСЕ G‘I KMOQSUWY

Несмотря на то что метод Seek () имеет немало преимуществ при использовании с файлами, существует и другой способ установки текущего положения в файле с помощью свойства Position. Как следует из табл. 14.2, свойство Position доступно как для чтения, так и для записи. Поэтому с его помощью можно получить или же установить текущее положение в файле. В качестве примера ниже приведен фрагмент кода из предыдущей программы записи и чтения из файла с произвольным доступом random.dat, измененный с целью продемонстрировать применение свойства Position.

Console.WriteLine("Буквы алфавита через одну: "); for(int i=0; i < 26; i += 2)    {

f.Position = i; // найти i-й символ посредством свойства Position ch = (char) f.ReadByte();

Console.Write(ch + " ");

}

Применение класса MemoryStream

Иногда оказывается полезно читать вводимые данные из массива или записывать выводимые данные в массив, а не вводить их непосредственно из устройства или выводить прямо на него. Для этой цели служит класс MemoryStream. Он представляет собой реализацию класса Stream, в которой массив байтов используется для ввода и вывода. В классе MemoryStream определено несколько конструкторов. Ниже представлен один из них:

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*