// FileRead - читает текстовый файл и |
выводит на |
консоль его |
// содержимое |
|
|
|
using System; |
|
|
|
using System. 10; |
|
|
|
namespace |
FileRead |
|
|
|
{ |
|
|
|
|
public |
class Program |
|
|
|
public static void Main(string [] |
args) |
|
{ |
|
|
|
|
// Нам нужен объект для чтения файла |
|
StreamReader sr; |
|
|
|
string sFileName = " "; |
|
|
// |
Пытаемся получить |
корректное |
имя файла до тех пор, |
// |
пока наконец его |
не получим |
(для выхода |
из |
//программы надо использовать комбинацию клавиш
//<Ctrl+C>)
while(true)
{
try
{
// Ввод имени файла
Console.Write("Введите имя текстового файла:"); sFileName = Console.ReadLine();
//Если пользователь ничего не ввел, генерируем
//исключение для указания, что такой ввод
//неприемлем
if (sFileName.Length == 0)
{
throw new
IOException("Введено пустое имя файла");
}
//Открываем файловый поток для чтения; если файл
//не существует - не создаем его
FileStream fs = File.Open(sFileName,
F i1eMode.Open,
FileAccess.Read);
//Преобразуем в StreamReader - этот класс
//использует первые три байта файла для
//определения использованной кодировки (но не для
//языка)
sr = new StreamReader(fs, true); break;
}
// Сообщение об ошибке с указанием имени файла catch(IOException fe)
{
Console.WriteLine("{0}\n\n", fe.Message);
}
}
// Чтение содержимого файла Console.WriteLine("\пСодержимое файла:") ; try
Глава 19. Работа с файлами и библиотеками |
441 |
{
// Чтение по одной строке while(true)
{
// |
Считывание строки |
string slnput = sr.ReadLine() ; |
// |
Выход, |
когда больше считать строку не удается |
if |
(slnput |
== null) |
{
break;
}
// Вывод считанного на консоль
Console.WriteLine(slnput);
}
catch(IOException fe)
// перехватывает все ошибки и сообщает о них Console.Write(fe.Message);
// Закрываем файл (игнорируя возможные ошибки) try
sr.Close();
catch {} sr = null;
// Ожидаем подтверждения пользователя Console.WriteLine("Нажмите <Enter> для " +
"завершения программы.. . ") ;
Console.Read();
}
Вспомним, что текущим каталогом, использовавшимся демонстрационной програм мой FileRead, был подкаталог \bin\Debug в каталоге проекта FileRead (но не ка талог \bin\Debug в каталоге проекта FileWrite). Перед тем как вы запустите про грамму FileRead, поместите текстовый файл в подкаталог \bin\Debug каталогам проекта и запомните имя этого файла, чтобы впоследствии вы могли открыть его. Дли этого вполне подойдет копия файла TestFilel.txt, созданного демонстрационно! программой FileWrite.
Демонстрационная программа FileRead применяет другой подход к именам фай лов. В ней пользователь считывает один и только один файл. Пользователь должен вве сти корректное имя файла, который будет считан программой. После того как программа прочтет файл, она завершает свою работу. Если пользователь хочет прочесть второй файл, он должен заново запустить программу.
Одно из ограничений подхода, использованного в демонстрационной программе Fil eRead, заключается в том, что попытки получить имя файла от пользователя продолжают ся до бесконечности. Если пользователь ошибается, он должен продолжать свои попытки. Единственный выход из программы без ввода корректного имени — воспользоваться ком бинацией клавиш <Ctrl+C> либо щелкнуть на кнопке закрытия консольного окна.
442 |
Часть VII. Дополнительные глава |
Программа начинается с цикла while, как и демонстрационная программа FileWrite. В цикле программа получает имя файла для чтения от пользователя. Если имя файла пустое, программа генерирует свое собственное сообщение об ошибке: Введено пустое имя файла. Если имя файла не пустое, оно используется для открытия объек та FileStream в режиме для чтения. Вызов File.Open() работает так же, как и в демонстрационной программе FileWrite.
Первый аргумент — это имя файла.
Второй аргумент— режим открытия файла. Режим FileMode. Open гласит: "Открыть файл, если он существует, и сгенерировать исключение, если его нет". Другой вариант— OpenNew, который создает файл нулевой длины в случае от сутствия последнего. Лично я никогда не использовал этот режим (кому надо чи тать из пустого файла?), но мало ли — может, имеются люди, умеющие напиться из пустого стакана?
Последний аргумент указывает на желание читать из объекта FileStream. Дру гие возможные варианты — Write и ReadWrite. (Кажется странным открывать файл в программе FileRead с использованием режима Write, не правда ли?)
Полученный в результате объект f s класса FileStream оборачивается в объект sr класса StreamReader — для предоставления удобного доступа к текстовому файлу.
Весь раздел открытия файла размещен в try-блоке в цикле while. Этот try-блок предназначен исключительно для открытия файла. Если в процессе открытия файла про исходит ошибка, генерируется и перехватывается исключение, выводится сообщение об ошибке, и программа возвращается к запросу имени файла. Однако если процесс завер шается благополучно, то команда break передает управление за пределы цикла в раздел чтения файла.
Демонстрационные программы FileRead и FileWrite представляют два разных способа обработки исключений. Вы можете поместить всю программу в один try-блок, как в демонстрационной программе FileWrite, либо по местить раздел открытия файла в собственный t ry-блок. Обычно использовать отдельные try-блоки проще, а кроме того, это позволяет генерировать более точные сообщения об ошибках.
Когда процесс открытия файла завершен, программа FileRead считывает строку текста из файла с помощью вызова ReadLine ( ) . Программа выводит эту строку на консоль посредством хорошо знакомого вызова Console .WriteLine О , после чего возвращается к считыванию очередной строки текста. Когда программа достигает конца файла, вызов ReadLine () возвращает значение null. Когда это происходит, програм ма прекращает цикл чтения, закрывает объект и завершает работу.
Обратите внимание, как вызов Close () обернут в свой собственный небольшой try- блок. Блок catch без аргументов перехватывает все классы исключений (что эквивалентно
catch (Exception)). |
Любая ошибка, сгенерированная |
в Close О, перехватывается |
и игнорируется. Этот |
блок catch предназначен для того, |
чтобы предотвратить распро |
странение исключения и завершение программы. Ошибка игнорируется, поскольку про грамма ничего не может поделать со сбоем в вызове Close ( ) , тем более что через пару строк программа все равно завершается. Вы могли бы поместить вызов Close () в блок
Глава 19. Работа с файлами и библиотеками |
443 |
finally после блока catch для того, чтобы гарантировать его выполнение в любом слу чае, но в данной ситуации это излишне.
Пустой catch включен исключительно в демонстрационных целях. Пред» ставление вызову собственного try-блока с перехватом всего, что можно,пре дотвращает завершение программы из-за несущественных ошибок. Оли этот метод можно использовать только если ошибка действительно некритгга и не вредит работе программы.
Вот как выглядит пример вывода программы:
Введите имя текстового файла:TestFilex.txt
Could not find file "C:\C#Programs\FileRead\TestFilex.txt".
Введите имя текстового файла:TestFilel.txt
Содержимое файла: Это какой-то текст
Иеще
Иеще раз...
Нажмите <Enter> для завершения программы...
Как видите, это тот же текст, который был записан в файл TestFilel. txt, созданный в демонстрационной программе FileWrite (ведь вы не забыли скопировать его! каталог \FileRead\bin\debug?).
444 |
Часть VII. Дополнительные главы |
Глава 20
Работа с коллекциями
В этой главе...
УКаталог как коллекция
>Реализация коллекции LinkedLi st
>Итеративный обход коллекции LinkedList
>Реализация индексирования для упрощения доступа к объектам коллекций
>Упрощение циклического обхода коллекции с помощью нового блока итератора С#
айл представляет собой один из типов коллекций данных, но существуют и дру гие коллекции. Например, каталог можно рассматривать как коллекцию файлов.
Кроме того, С# предоставляет множество типов контейнеров в оперативной памяти.
Эта глава построена на основе главы 15, "Обобщенное программирование", и мате риале, посвященном файлам, из главы 19, "Работа с файлами и библиотеками". Основ ной вопрос, рассматриваемый в данной главе — проход (итерирование) по коллекциям разного вида, от каталогов до массивов и списков всех видов. Вы также узнаете, как на писать собственный класс коллекции (более фундаментальный, чем рассматривавшийся в главе 15, "Обобщенное программирование", пример очереди с приоритетами)— свя занный список.
Чтение и запись — вот основное, что необходимо знать для работы с файлами. Иименно этим и занимались демонстрационные программы FileRead и FileWrite из главы 19, "Работа с файлами и библиотеками". Однако в ряде случаев вам просто нужно просканировать каталог файлов в поисках чего-то.
Приведенная далее демонстрационная программа LoopThroughFiles просматривает все файлы в данном каталоге, считывая каждый файл и вы водя его содержимое на консоль в шестнадцатеричном формате. (Это де монстрирует вам, что файл можно выводить не только в виде строк. Что -та кое шестнадцатеричный формат — вы узнаете немного позже.)
Если запустить эту программу в каталоге с большим количеством файлов, то вывод шестнадцатеричного дампа может занять длительное время. Много времени требует и вывод дампа большого файла. Либо испытайте програм му на каталоге покороче, либо, когда вам надоест, просто нажмите клавиши <Ctrl+C>. Эта команда должна прервать выполнение программы в любом консольном окне.