Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 86
Текст из файла (страница 86)
Таким образом, для обнаружения конца файла никакого специального механизма не требуется. файлы с произвольным доступом В предыдущих примерах использовались лосяедовательньм фша)ы, т.е. файлы со строго линейным доступом, байт за байтом. Но доступ к содержимому файла может быть и произвольным. Для этого служит, в частности, метод Я ее)с ( ), определенный в классе Е11еЯ С ге аш. Этот метод позволяет установить указатель положения в файле, или так иазываемйй указатель файла иа любое место в файле. Ниже приведена общая форма метода Яее)с() . 1опд Яеек(1опч пеыроз, Яееког101п огхдхл) где не ыроз обозначает новое положение указателя файла в байтах относительно заданно- го начала отсчета (огйд1 и).
В качестве о г101п может быть указано одно из приведенных ниже значений, определяемых в перечислении Яее)сог101п. Значение Описание Яееког101п.ведгп Яееког1дгп.Сцггепс Яеехоггв1п.Епс) Поиск от начала файла Поиск от текущего положения Поиск от конца файла Следующая операция чтения или записи после вызова метода Яеех () будет выполняться, начиная с нового положения в файле, возвращаемого этим методом. Если во время поиска в файле возникаег ошибка, то генерируется исключение 1ОЕхсерг1оп. Если же запрос положения в файле ие поддерживается базовым потоком, то генерируется исключение МОСЯцрроггес(Ехсерс1оп. Кроме того, могут быть сгеиерированы и другие исключения. Глава (4, Применение средств ввода.
вывода 447 В приведенном ниже примере программы демонстрируется ввод-вывод в файл с произвольным доступом. Сначала в файл записываются прописные буквы английского алфавита, а затем его содержимое считывается обратно в произвольном порядке. // Продемонстрировать произвольный доступ к файлу. пя1пч Яуягево пятно Яуясеш.101 с1аяя аапбошАссеяяоешо ( ягагтс чотб Матп() ( Г11езсгеаш Гт сЬаг сЬт сгу ( Г = пен Г11езггеаш("гапбош.баг", г11еиобе.Сгеаге) 1 ) сассЬ(10Ехсерсаоп ехс) Сопяоге.иг1ге11пе("Не удается открыть файл")т Сопяо1е.иг1ге11пе(ехс.меяяаче)т геснгпт ) // Записать английский алфавит в файл.
лог(епс 1=01 1 < 251 1++) ( сгу ( г.иг1сеВусе((ьуге)('А'+1))т ) сагсп(1ОЕхсергдоп ехс) ( Сопяо1е.игасеьапе (" Ошибка записи в файл"); сопяо1е.игггег Ьпе (ехс.Меяяаде); Г.С1ояе() т гегпгпт ) ггу ( // А теперь считать отдельные буквы алфавита. Г.ЯееК(0, ЯееКОгпфап.Вер1п)т // найти первый байт сЬ = (спаг) Г.реабВуге()) Сопяо1е.иг1ге11пе("Первая буква: " + сп)) 1.5ееК(1, ЯееКОггдтп.Ведтп)) // найти второй байт сЬ = (спаг) Г.аеабвусе()т Сопяо1е.игтсес1пе("Вторая буква: " + сп)) Г.зеек(4, 5еекоггптп.Ведтп)) // найти пятый байт сЬ = (сЬаг) Г.аеабВусе()т Сопяо1е.игтсе11пе("Пятая буква: " е сп)т Сопяо1е.игтге11пе()т // А теперь прочитать буквы алфавита через одну. сопяо1е.игасеь1пе("Буквы алфавита через одну: ") 448 Часть).
язык Сз еог(1пг 1=0) 1 < 2бт 1 += 2) ( Е.зеек(1, Бееаог1О1п.Вечгп); // найти 1-й символ сп = (сваг) Е.иеабВУГе()т Сопяо1е.иг1се(сь + " ")т ) ) сассп(1ОЕхсерсгоп ехс) Сопяо1е.иг1ке11пе( "Ошибка чтения или поиска в файле"): сопяо1е.иггге11пе(ехс.меяяаде)т ) Сопяо1е.иггсеьтпе() т Е.С1ояе() т ) ) При выполнении этой программы получается следующий результат: первая буква: А Вторая буква: В Пятая буква: Е Буквы алфавита через одну: А С Е 6 1 К М О О 5 О И т Несмотря на то что метод Бее)< () доставляет немало удобств для обращения с файлами, существует и другой способ установки текущего положения в файле с помощью свойства Роя111оп.
Как следует из табл. 14.2, свойство РО51Г1оп доступно как для чтения, так и для записи. Поэтому с его помощью можно получить или же установить текущее положение в файле. В качестве примера ниже приведен фрагмент кода из предыдущей программы записи и чтения из файла с произвольным доступом гапбош. Пас, переделанный с целью продемонстрировать применение свойства Роя1ГЕоп. // Использовать свойство Роягггоп вместо метода Беек() // для установки текущего положения в файле. ггу ( Е.рояЕГ1оп = От сп = (спас) Е.веабВусе()т Сопяо1е.Иггсеьгпе("Первая буква: " + сь); Е.Роя1г1оп = 1т сп = (сваг) Е.веабВУГе()т Сопяо1е.нг1геьгпе("Вторая буква: " + сл)т Е.роя1ГЕоп = 4) сп = (сваг) Е.веабВусе()г Сопяо1е.нггсевапе("Пятая буква: " + сЬ)т СопяоЪе.иггсеьгпе()т // А теперь прочитать буквы алфавита через одну. Сопяо1е.ИГ1севвпе("Буквы алфавита через одну: ")) Еог(гпк 1=0) 1 < 2б) 1 += 2) ( Глава! 4, Применение средств ввода-вывода 449 т.роя1С1оп = 1; // найти 1-й символ сь = (пьат) Г.аезбнуСе(); Сопяо1е.иг1ге(сЬ и " "); ) сзгсЬ(1ОЕхсерС1оп ехс) ( Сопяо1е.иггге51пе("Ошибка чтения мпи поиска з файле") Сопяо1е.иггге51пе(ехс.Меяяаое); Применение класса метотуЗ~хеалп Иногда оказывается полезно читать вводимые данные из массива или записывать выводимые данные в массив, а не вводить их непосредственно из устройства или выводить прямо на него.
Для атой цели слУжит класс МевотуЯСгеав. Он представляет собой реализацию класса Ясгеав, в которой массив байтов используется для ввода и вывода. В классе мевотуясгеав определено несколько конструкторов. Ниже представлен один из ннх. Мевогу5гтеав (Ьуге [ ] Ьит) // Продемонстрировать применение класса Мевпгузггеав. цягпо Яуягепп ця1пч Буягев.10) с1азя МевзггОево ( згаггс чотб Ма1п() ( Ьуге[] ягогзсе = пен Ьуге[255]) // созвать запоминающий поток. Мевпгузгтезв вевяггв = пем Мевогузггеав(зготасе) // Заключить объект вевзгтв з оболочки // чтения и записи данных з потоки. 5ггеавиг1гег вевнгг = пем Яггезвнгггет Ягтеавкеап(ег тевгот = пем Бгтеаваеабет классов (вевяггв)п (вевяспп)) // Записать данные з память, используя тпг(1пг г=о; г < 10; 1++) шевмгг.нгтге11пе("буге [" т 1 + "]: объект вевнгг.
О Поставить з конце точку. вевмгг.нгггесвпе(".")и вевмСт.в'1цяп() где Ь ит обозначает массив байтов, используемый в качестве источника или адресата в за- ПРОСаХ ВВОда-ВЫВОда. ИспольЗУя этот КОНСтруКтОр, СлЕДУет иметь в видУ, что МасСИВ Ьцт должен быть достаточно большим для хранения направляемых в него данных. В качестве примера ниже приведена программа, демонстрирующая применение класса Мевогуясгеав в операциях ввода-вывода.
450 Часть (. [(знк С() Сопво1е.иггсеьгпе (" Чтение прямо из массива зсогаде: ") ~ // Отобразить содержимое массива всогаде // непосредственно. гогеась(сваг сь хп вгогаде) ( пб (сп == '.') Ьгеак7 Сопзо1е.нг1се(сп) 7 ) Сопво1е.кггсеьгпе("1пчтение из потока с помощью объекта щещгбг: "); // Читать из объекта щещвсгщ средствами // ввода данных из потока, щещвсгщ.Беев(0, зеекбггд1п.зед1п]7 // установить //указатель файла в исходное положение всгапд всг = щещгбг.аеас(11пе () 7 нк11е(зсг (= пп11) ( зсг = щещгбг.аеабьгпе()7 15(асг.сощрагето(".") == 0) Ьгеаа; сопво1е.нгьсеъгпе (зсг) 7 ) ) ) Вот к какому результату приводит выполнение этой программы: Чтение прямо из массива всогаде: Ьусе [0]: 0 Ьусе [1]: 1 Ьусе [2]: 2 Ьусе [3]: 3 Ьусе [4]: 4 Ьусе [5]: 5 Ьусе [6]: б Ьусе [7]: 7 Ьусе [8]: 8 Ьусе [9]: 9 В этой программе сначала создается массив байтов, называемый з согаде.
Затем этот массив используется в качестве основной памяти для объекта щещз сгщ класса мещогузггеап. Из объекта щещзггщ, в свою очередь, создаются объекты щещгбг класса зггеащнеабег и щещысг класса зггеащнгасег. С помощью объекта щещисг выводимые данные записываются в запоминающий поток. Обратите внимание на то, что после записи выводимых данных для объекта щещнгг вызывается метод р1 пап () .
Это необходимо для того, чтобы Чтение из Ьусе [1]: Ьусе [2]: Ьусе [3]: Ьусе [4]: Ьусе [5): Ьусе [б]: Ьусе [7]: Ьусе [8]: Ьусе [9]: потока с помощью объекта щещгбг: 1 2 3 4 5 б 7 8 9 Глава !4. Применение средств ввода-вывода 451 содержимое буфера этого объекта записывалось непосредственно в базовый массив. Далее содержимое базового массива байтов отображается вручную в цикле Тогеас) ь После этого указатель файл устанавливается с помощью метода Яее)с () на начало запоминающего потока, из которого затем вводятся данные с помощью объекта потока мейгс(т. Запоминающие потоки очень полезны для программирования.
С их помощью можно, например, организовать сложный вывод с предварительным накоплением данных в массиве до тех пор, пока они не понадобятся. Этот прием особенно полезен для программирования в такой среде с графическим пользовательским интерфейсом, как %(/(пг)отея. Кроме того, стандартный поток может быть переадресован из массива. Это может пригодиться, например, для подачи тестовой информации в программу.
Применение классов я~гхпдйеайег и 81тхпдИгх1ех Для выполнения операций ввода-вывода с запоминанием в некоторых приложениях в качестве базовой памяти иногда оказывается более пригодным массив типа з тт1по, чем массив типа )ауте. Именно для таких случаев и предусмотрены классы ятг1допеас(ег и Бтг1пойт1тег. В частности, класс Бгг1понеас(ег наследует от класса Техтпеас)ет, а класс Ятг1пойт1тет — от класса Техтйт1тет. Следовательно, они представляют собой потоки, имеющие доступ к методам, определенным в этих двух базовых классах, что позволяет, например, вызывать метод ПеаЖ1пе () для объекта. класса Бтт1допеабет, а метод итттеыпе () — для объекта класса я гт1пои та те т.
Ниже приведен конструктор класса ятт1попеас(ет. Ятгтпчаеабег(всттпп зтг) где этг обозначает строку, из которой производится чтение. В классе Ятг1пойг1гег определено несколько конструкторов. Ниже представлен один из наиболее употребительных среди них.
яттгоойт1гег() Этот конструктор создает записывающий объект, который помещает выводимые данные в строку. Для получения содержимого этой строки достаточно вызвать метод ТоБтг1по () . Ниже приведен пример, демонстрирующий применение классов Бтг1понеас(ег и Ятт1дойт1тет. // Продемонстрировать применение классов // ятгадпаеабег и ЯттаоЧИгттег. оз1оп Яузтеп1; оз1дя Яузтеи.го; о1азв Ятгвбгпеио ( зтаг1о то16 Ма1п() ( // Создать объект клааса Ятт1дпйг1тет. Ятг1дчйтгтет зтгнтг = ден Яттаосйтттет(); // Вывести данные в записывающий объект // класса Яттгосйт1тег.