Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Файлы с произвольным доступом
В предыдущих примерах использовались последовательные файлы, т.е. файлы со строго линейным доступом, байт за байтом. Но доступ к содержимому файла может быть и произвольным. Для этого служит, в частности, метод Seek(), определенный в классе FileStream. Этот метод позволяет установить указатель положения в файле, или так называемый указатель файла,на любое место в файле. Ниже приведена общая форма метода Seek(): long Seek(long offset,SeekOrigin origin) где offset обозначает новое положение указателя файла в байтах относительно заданного начала отсчета (origin). В качестве origin может быть указано одно из приведенных ниже значений, определяемых в перечислении SeekOrigin.
Следующая операция чтения или записи после вызова метода Seek() будет выполняться, начиная с нового положения в файле, возвращаемого этим методом. Если во время поиска в файле возникает ошибка, то генерируется исключение IOException. Если же запрос положения в файле не поддерживается базовым потоком, то генерируется исключение NotSupportedException. В приведенном ниже примере программы демонстрируется ввод-вывод в файл с произвольным доступом. Сначала в файл записываются прописные буквы английского алфавита, а затем его содержимое считывается обратно в произвольном порядке. // Продемонстрировать произвольный доступ к файлу. using System; using System.IO; 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(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("Ошибка ввода-вывода\n" + exc.Message); } finally { if (f!= null) f.Close(); } Console.WriteLine(); } } Первая буква: А Вторая буква: В Пятая буква: Е Буквы алфавита через одну: А C E G I K M O Q S U W Y Несмотря на то что метод 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 определено несколько конструкторов. Ниже представлен один из них: MemoryStream(byte[] buffer) где buffer обозначает массив байтов, используемый в качестве источника или адресата в запросах ввода-вывода. Используя этот конструктор, следует иметь в виду, что массив buffer должен быть достаточно большим для хранения направляемых в него данных. // Продемонстрировать применение класса MemoryStream. using System; using System.IO; class MemStrDemo { static void Main() { byte[] storage = new byte[255]; // Создать запоминающий поток. MemoryStream memstrm = new MemoryStream(storage); // Заключить объект memstrm в оболочки классов чтения и записи данных в потоки. StreamWriter memwtr = new StreamWriter(memstrm); StreamReader memrdr = new StreamReader(memstrm); try { // Записать данные в память, используя объект memwtr. for (int i = 0; i < 10; i++) memwtr.WriteLine("byte [" + i + "]: " + i); // Поставить в конце точку. memwtr.WriteLine("."); memwtr.Flush(); Console.WriteLine("Чтение прямо из массива storage: "); // Отобразить содержимое массива storage непосредственно, foreach (char ch in storage) { if (ch == '.') break; Console.Write(ch); } Console.WriteLine("\nЧтение из потока с помощью объекта memrdr: "); // Читать из объекта memstrm средствами ввода данных из потока. memstrm.Seek(0, SeekOrigin.Begin); // установить указатель файла // в исходное положение string str = memrdr.ReadLine(); while (str!= null) { str = memrdr.ReadLine(); if (str[0] == '.') break; Console.WriteLine(str); } } catch (IOException exc) { Console.WriteLine("Ошибка ввода-вывода\n" + exc.Message); } finally { // Освободить ресурсы считывающего и записывающего потоков. memwtr.Close(); memrdr.Close(); } } } Чтение прямо из массива storage: byte [0]: 0 byte [1]: 1 byte [2]: 2 byte [3]: 3 byte [4]: 4 byte [5]: 5 byte [6]: 6 byte [7]: 7 byte [8]: 8 byte [9]: 9 Чтение из потока с помощью объекта memrdr: byte [1]: 1 byte [2]: 2 byte [3]: 3 byte [4]: 4 byte [5]: 5 byte [6]: 6 byte [7]: 7 byte [8]: 8 byte [9]: 9 В этой программе сначала создается массив байтов, называемый storage. Затем этот массив используется в качестве основной памяти для объекта memstrm класса MemoryStream. Из объекта memstrm, в свою очередь, создаются объекты memrdr класса StreamReader и memwtr класса StreamWriter. С помощью объекта memwtr выводимые данные записываются в запоминающий поток. Обратите внимание на то, что после записи выводимых данных для объекта memwtr вызывается метод Flush(). Это необходимо для того, чтобы содержимое буфера этого объекта записывалось непосредственно в базовый массив. Далее содержимое базового массива байтов отображается вручную в цикле foreach. После этого указатель файла устанавливается с помощью метода Seek() в начало запоминающего потока, из которого затем вводятся данные с помощью объекта потока memrdr. Применение классов StringReader и StringWriter Для выполнения операций ввода-вывода с запоминанием в некоторых приложениях в качестве базовой памяти иногда лучше использовать массив типа string, чем массив типа byte. Именно для таких случаев и предусмотрены классы StringReader и StringWriter. В частности, класс StringReader наследует от класса TextReader, а класс StringWriter — от класса TextWriter. Следовательно, они представляют собой потоки, имеющие доступ к методам, определенным в этих двух базовых классах, что позволяет, например, вызывать метод ReadLine() для объекта класса StringReader, а метод WriteLine() — для объекта класса StringWriter. Ниже приведен конструктор класса StringReader: StringReader(string s) где s обозначает символьную строку, из которой производится чтение. В классе StringWriter определено несколько конструкторов. Ниже представлен один из наиболее часто используемых. StringWriter() Этот конструктор создает записывающий поток, который помещает выводимые данные в строку. Для получения содержимого этой строки достаточно вызвать метод ToString(). using System; using System.IO; class StrRdrDemo { static void Main() { StringWriter strwtr = null; StringReader strrdr = null; try { // Создать объект класса StringWriter. strwtr = new StringWriter(); // Вывести данные в записывающий поток типа StringWriter. for (int i = 0; i < 10; i++) strwtr.WriteLine("Значение i равно: " + i); // Создать объект класса StringReader. strrdr = new StringReader(strwtr.ToString()); //А теперь ввести данные из считывающего потока типа StringReader string str = strrdr.ReadLine(); while (str!= null) { str = strrdr.ReadLine(); Console.WriteLine(str); } } catch (IOException exc) { Console.WriteLine("Ошибка ввода-вывода\n" + exc.Message); } finally { // Освободить ресурсы считывающего и записывающего потоков. if (strrdr!= null) strrdr.Close(); if (strwtr!= null) strwtr.Close(); } } }І В данном примере сначала создается объект strwtr класса StringWriter, в который выводятся данные с помощью метода WriteLine(). Затем создается объект класса StringReader с использованием символьной строки, содержащейся в объекте strwtr. Эта строка получается в результате вызова метода ToString() для объекта strwtr. И наконец, содержимое данной строки считывается с помощью метода ReadLine(). Класс File В среде .NET Framework определен класс File, который может оказаться полезным для работы с файлами, поскольку он содержит несколько статических методов, выполняющих типичные операции над файлами. В частности, в классе File имеются методы для копирования и перемещения, шифрования и расшифровывания, удаления файлов, а также для получения и задания информации о файлах, включая сведения об их существовании, времени создания, последнего доступа и различные атрибуты файлов (только для чтения, скрытых и пр.). Кроме того, в классе File имеется ряд удобных методов для чтения из файлов и записи в них, открытия файла и получения ссылки типа FileStream на него. В классе File содержится слишком много методов для подробного их рассмотрения, поэтому мы уделим внимание только трем из них. Сначала будет представлен метод Сору(), а затем — методы Exists() и GetLastAccessTime(). Копирование файлов с помощью метода Сору() Ранее в этой главе демонстрировался пример программы, в которой файл копировался вручную путем чтения байтов из одного файла и записи в другой. И хотя задача копирования файлов не представляет особых трудностей, ее можно полностью автоматизировать с помощью метода Сору(), определенного в классе File. Ниже представлены две формы его объявления. static void Copy (string имя_исходного_файла,string имя_целевого_файла) static void Copy (string имя_исходного_файла,string имя_целевого_файла, boolean overwrite) В первой форме данный метод копирует файл только в том случае, если файл, на который указывает имя_целево-го_файла, еще не существует. А во второй форме копия заменяет и перезаписывает целевой файл, если он существует и если параметр overwrite принимает логическое значение true. Но в обоих случаях может быть сгенерировано несколько видов исключений, включая IOException и FileNotFoundException. В приведенном ниже примере программы метод Сору() применяется для копирования файла. Имена исходного и целевого файлов указываются в командной строке. using System; using System.IO; class CopyFile { static void Main(string[] args) { if (args.Length!= 2) { Console.WriteLine("Применение: CopyFile Откуда Куда"); return; } // Копировать файлы. try { File.Copy(args[0], args[1]); } catch (IOException exc) { Console.WriteLine("Ошибка копирования файла\n" + exc.Message); } } } Применение методов Exists() и GetLastAccessTime() Метод Exists() определяет, существует ли файл, а метод GetLastAccessTime() возвращает дату и время последнего доступа к файлу. Ниже приведены формы объявления обоих методов. static bool Exists(string путь) static DateTime GetLastAccessTime(string путь) В обоих методах путь обозначает файл, сведения о котором требуется получить. Метод Exists() возвращает логическое значение true, если файл существует и доступен для вызывающего процесса. А метод GetLastAccessTime() возвращает структуру DateTime, содержащую дату и время последнего доступа к файлу. using System; using System.IO; class ExistsDemo { static void Main() { if (File.Exists("test.txt")) Console.WriteLine("Файл существует. В последний раз он был доступен " + File.GetLastAccessTime("test.txt")); else Console.WriteLine("Файл не существует"); } } Кроме того, время создания файла можно выяснить, вызвав метод GetCreationTime(), а время последней записи в файл, вызвав метод GetLastWriteTime(). Имеются также варианты этих методов для представления данных о файле в формате всеобщего скоординированного времени (UTC). Попробуйте поэкспериментировать с ними. using System; using System.IO; class ExistsDemo { static void Main() { if (File.Exists("test.txt")) { Console.WriteLine("Файл существует.\nВ последний раз он был доступен " + File.GetLastAccessTime("test.txt")); Console.WriteLine("Время создания файла " + File.GetCreationTime("test.txt")); Console.WriteLine("Время последней записи в файл " + File.GetLastWriteTime("test.txt")); } else Console.WriteLine("Файл не существует");
} } Date: 2015-09-02; view: 407; Нарушение авторских прав |