сложностях попыток перевода содержимого текстового поля, представленного выше, в двоичный поток. Мы рассмотрим запись в файлы позже, когда разработаем пример, который может считывать и записывать текстовые файлы.

Итак, запишем код. Вначале добавим дополнительные инструкции using, так как помимо System.IO этот пример будет использовать класс StringBuilder из пространства имен System.Text для создания строк текстового поля:

using System.IO;

using System.Text;

Затем добавляются поля в класс основной формы, одно для представления файлового диалога, и строка, которая задает путь доступа к файлу, просматриваемому в текущий момент:

public class Form1 : System.Windows.Forms.Form {

 OpenFileDialog ChooseOpenFileDialog = new OpenFileDialog();

 string ChosenFile;

Нам нужно также добавить стандартный код формы Windows для работы методов обработки меню и файлового диалога:

 public Form1() {

  InitializeComponent();

  menuFileOpen.Click += new EventHandler(OnFileOpen);

  ChooseOpenFileDialog.FileOk += new CancelEventHandler(OnOpenFileDialogOK);

 }

 void OnFileOpen(object Sender, EventArgs e) {

  ChooseOpenFileDialog.ShowDialog();

 }

 void OnOpenFileDialogOK(object Sender, CancelEventArgs e) {

  ChosenFile = ChooseOpenFileDialog.FileName;

  this.Text = ChosenFile;

  DisplayFile();

 }

Из этого кода мы видим, что, когда пользователь нажимает OK, чтобы выбрать файл в файловом диалоге, вызывается метод DisplayFile(), который реально выполняет работу считывания файла:

 void DisplayFile() {

  int nCols = 16;

  FileStream InStream = new FileStream(ChosenFile, FileMode.Open, FileAccess.Read);

  long nBytesToRead = InStream.Length; if (nBytesToRead > 65536/4)

  nBytesToRead = 65536/4;

  int nLines = (int)(nBytesToRead/nCols) + 1;

  String [] Lines = new string[nLines];

  int nBytesRead = 0;

  for (int i=0; i<nLines; i++) {

   StringBuilder NextLine = new StringBuilder();

   NextLine.Capacity = 4*nCols;

   for (int j = 0; j<nCols; j++) {

    int NextByte = InStream.ReadByte();

    nBytesRead++;

    if (NextByte <0 || nBytesRead > 65536) break;

    char NextChar = (char)NextByte;

    if (NextChar < 16)

NextLine.Append(' x0' + string.Format('{0,1:X}', (int(NextChar));

    else if (char.IsLetterOrDigit(NextChar) || char.IsPunctuation(NextChar))

    (NextLine.Append(' ' + NextChar + ' ');

    else NextLine.Append(' x' + string.Format('{0,2:X}', (int)NextChar));

   }

   Lines[i] = NextLine.ToString();

  }

  InStream.Close();

  this.textBoxContents.Lines = Lines;

 }

Разберем данный метод подробнее. Мы создаем экземпляр FileStream для выбранного файла и хотим открыть существующий файл для чтения. Затем мы определяем, сколько существует байтов для чтения и сколько строк должно выводиться. Число байтов обычно равно числу байтов в файле. Однако текстовые поля могут выводить максимум только 65536 символов, и для выбранного формата выводится 4 символа для каждого байта в файле, поэтому необходимо сделать ограничение числа показываемых байтов, если файл длиннее 65536/4 = 16384.

В случае выведения более длинных файлов в таком рабочем окружении можно рассмотреть класс RichTextBox в пространстве имен System.Windows.Forms. RichTextBox аналогичен текстовому полю, но имеет значительно более развитые средства форматирования и не имеет ограничения на объем выводимого текста. Мы используем здесь TextBox, чтобы сохранить тривиальность примера и сосредоточиться на процессе чтения файла.

Основная часть метода представлена в двух вложенных циклах for, которые создают каждую строку текста для вывода. Мы используем класс StringBuilder для создания каждой строки по соображениям производительности. Мы будем добавлять подходящий текст для каждого байта к строке, которая представляет каждую линию 16 раз. Если каждый раз мы будем выделять новую строку и делать копию полусозданной линии, мы не только затратим много времени на выделение строк, но истратим много памяти из кучи динамической памяти. Отметим, что наше определение 'печатных' символов соответствует буквам, цифрам и символам пунктуации, как указано соответствующими статическими методами System.Char. Мы исключили, однако, все символы со значением меньше 16 из списка печатных символов, а значит, будем перехватывать возврат каретки (13) и перевод строки (10) как двоичные символы (многострочное текстовое поле не может правильно вывести эти символы, если они встречаются отдельно внутри строки).

В конце мы закрываем поток и задаем содержимое текстового поля как массив строк, который был создан.

Чтение и запись текстовых файлов

Теоретически вполне возможно использование класса FileStream для чтения и вывода текстовых файлов. В конце концов, мы уже продемонстрировали, как это делается. Формат, в котором выводился выше файл CivNegotiations.txt, был не очень удобен для пользователя, но это было связано не с какой-либо внутренней проблемой класса FileStream, а со способом,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату