Книга: C# для профессионалов. Том II

Пример: ReadWriteText

Пример: ReadWriteText

Пример ReadWriteText выводит результат использования классов StreamReader и StreamWriter. Он похож на предыдущий пример ReadBinaryFile, но предполагает, что считываемый файл является текстовым файлом, и выводит его в этом виде. Он может сохранить файл (со всеми изменениями, которые будут сделаны в тексте в текстовом поле). Он будет сохранять любой файл в формате Unicode.

Снимок показывает использование ReadWriteText для вывода того же файла CivNegotiations, который использовался раньше. В этот раз, однако, мы сможем прочитать содержимое гораздо легче.


Не будем вдаваться в детали добавления методов обработки событий для диалога открытия файла, поскольку они по сути такие же, что и в примере BinaryFileReader. Как и для данного примера, открытие нового файла приводит к вызову метода DisplayFile(). Единственное реальное различие между этим примером и предыдущим состоит в реализации DisplayFile, а также в том факте, что теперь имеется возможность сохранить файл. Она представлена другим пунктом меню — save. Обработчик для этого пункта вызывает другой добавленный в код метод — SaveFile(). (Отметим, что этот файл всегда перезаписывает первоначальный файл, этот пример не имеет возможности записи в другой файл.)

Посмотрим сначала на SaveFile, так как это простейшая функция. Мы просто записываем каждую строку текстового поля по очереди в поток StreamWriter, полагаясь на метод StreamReader.WriteLine() для добавления комбинации возврата каретки-перевода строки в конце каждой строки:

void SaveFile() {
 StreamWriter sw = new StreamWriter(ChosenFile, false, Encoding.Unicode);
 foreach (string Line in textBoxContents.Lines) sw.WriteLine(Line);
 sw.Close();
}
ChosenFile
является строковым полем основной формы, которое содержит имя прочитанного файла (как и в предыдущем примере). Отметим, что при открытии потока определяется кодирование Unicode. Если желательно записывать файлы в другом формате, необходимо изменить значение этого параметра. Второй параметр в этом конструкторе будет задан как true, если мы хотим добавлять к файлу, но в данном случае мы этого не делаем. Кодирование должно задаваться во время создания объекта записи потока. В дальнейшем оно доступно только для чтения как свойство Encoding.

Теперь проверим, как считываются файлы. Процесс чтения осложняется тем, что мы не знаем, пока не прочитаем файл, сколько строк он будет содержать (другими словами, сколько последовательностей (char)13 - (char)10 находится в файле). Решим эту проблему, считывая сначала файл в экземпляр класса StringCollection, который находится в пространстве имен System.Collections.Specialized. Этот класс создан для хранения множества строк, которые могут динамически увеличиваться. Он реализует два интересующих нас метода: Add(), добавляющий строку в коллекцию, и CopyTo(), который копирует коллекцию строк в обычный массив (экземпляр System.Array). Каждый элемент объекта StringCollection будет содержать одну строку файла.

Метод DisplayFile() вызывает другой метод ReadFileIntoStringCollection(), который реально считывает файл. После этого мы знаем, сколько имеется строк, поэтому можно скопировать StringCollection в обычный массив фиксированного размера и передать этот массив в текстовое поле. Так как при создании копии копируются только ссылки на строки, а не сами строки, процесс будет достаточно эффективным:

void DisplayFile() {
 StringCollection LinesCollection = ReadFileIntoStringCollection();
 string [] LinesArray = new string[LinesCollection.Count];
 LinesCollection.CopyTo(LinesArray, 0);
 this.textBoxContents.Lines = LinesArray;
}

Второй параметр StringCollection.CopyTo() указывает индекс в массиве назначения, где мы хотим начать размещение коллекции.

Теперь рассмотрим метод ReadFileIntoStringCollection(). Мы используем StreamReader для считывания каждой строки. Основной трудностью является необходимость подсчитывать считанные символы, чтобы не превысить емкость текстового поля:

ArrayList ReadFileIntoStringCollection() {
 const int MaxBytes = 65536;
 StreamReader sr = new StreamReader(ChosenFile);
 StringCollection Result = new StringCollection();
 int nBytesRead = 0;
 string NextLine;
 while ((NextLine = sr.ReadLine()) != null) {
  nBytesRead += NextLine.Length;
  if (nBytesRead > MaxBytes) break;
  Result.Add(NextLine);
 }
 sr.Close();
 return Result;
}

Код завершен.

Если выполнить ReadWriteText — считать файл CivNegotiations и затем сохранить его, то файл будет иметь формат Unicode. Это невозможно для любого из обычных оконных приложений: Notepad, Wordpad и даже наш собственный пример ReadWriteText будут по-прежнему считывать файл и выводить его правильно в Windows NT/2000/XP, хотя, так как Windows 9х не поддерживает Unicode, приложения типа Notepad не смогут понять файл Unicode на этих платформах (Если загрузить пример с web-сайта издательства Wrox Press, то можно попробовать это сделать.) Однако, если попробовать вывести файл снова с помощью предыдущего примера ReadBinaryFile, то разница будет заметна немедленно, как на следующем экране. Два начальных файла указывают, что файл имеет формат Unicode, и поэтому мы видим, что каждый символ представлен двумя байтами. Этот последний факт вполне очевиден, поскольку старший байт каждого символа в данном конкретном файле равен нулю, поэтому каждый второй байт в этом файле выводится теперь как x00:


Оглавление книги


Генерация: 3.670. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз