
10.2.2. Класс StreamReader. Чтение из текстового файла
Чтение из текстового файла должно состоять из следующих шагов:
создать поток FileStream;
создать объект StreamReader, связав его с потоком;
методом Read() или ReadLine() прочитать данные;
методом Close(), освободив промежуточный буфер, закрыть файл;
методом Close(), закрыть файловый поток.
Пример 10.2. Прочитать все строки из текстового файла
Листинг 10.2. Чтение строк из текстового файла
static void Main(string[] args)
{
try
{
FileStream aFile =
new FileStream("Test.txt",
FileMode.Open);
StreamReader f =
new StreamReader(aFile);
string s = f.ReadLine();
//Прочитать все строки
while (s != null)
{
Console.WriteLine(s);
s = f.ReadLine();
}
f.Close();
aFile.Close();
}
catch (IOException e)
{
Console.WriteLine("Ошибка IO ");
Console.WriteLine(e.ToString());
return;
}
Console.ReadKey();
}
10.2.3. Пример: частотный словарь
В качестве второго примера рассмотрим проект, в котором читается текстовый файл и составляется словарь неповторяющихся слов. В качестве разделителей используются символы: ' ', ',', '.', ':', ';', '}', '{', '=', '(', ')' (пробел, запятая, точка, точка с запятой, двоеточие, знак равенства и т.д.).
Создадим новый проект, запишем его и на форму выставим следующие компоненты: listBox1, listBox2, dataGridView1, button1, button2 (рис. 10.2).
В окне Свойства изменим свойства: button1.Name = buttonOpen, button2.Name = buttonRun.
Рис. 10.2. Проект «Частотный словарь»
Для создания словаря введем структуру tDict (листинг 10.3), в которой есть поле word для сохранения слова и поле сount для сохранения числа повторений этого слова в тексте. Все слова будут собираться в динамическом массиве aDict.
Листинг 10.3. Описание структуры
public struct tDict
{
public string Word;
public int Count;
}
public tDict[] aDict = new tDict[]{};
Двойным щелчком на компоненте buttonOpen создадим обработчик события buttonOpenClick и напишем в нем код, который вызовет диалог openFileDialog, а затем заполнит элемент listBox1.
Листинг 10.4. Вызов процедуры SetWords
private void buttonOpen_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() ==
DialogResult.OK)
{
fileName = openFileDialog1.FileName;
FileStream fs =
openFileDialog1.OpenFile() as FileStream;
StreamReader f = new StreamReader(fs);
listBox1.Items.Clear();
while (f.Peek() > 0)
listBox1.Items.Add(f.ReadLine());
f.Close();
fs.Close();
openFileDialog1.Dispose();
}
}
Двойным щелчком на компоненте buttonRun откроем файловый поток FileStream, будем читать файл как текстовый в строки s и для каждой строки вызывать процедуру Parser(s):
Листинг 10.5. Вызов процедуры Parser
private void buttonRun_Click(object sender,
EventArgs e)
{
if (fileName != "")
{
listBox2.Items.Clear();
FileStream aFile =
new FileStream(fileName, FileMode.Open);
StreamReader f = new StreamReader(aFile);
string s = f.ReadLine();
Parser(s);
while (s != null)
{
s = f.ReadLine();
Parser(s);
}
f.Close();
aFile.Close();
for (int i = 0; i < aDict.Length; i++)
{
s = aDict[i].Word + " " +
Convert.ToString(aDict[i].Count);
listBox2.Items.Add(s);
}
for (int i = 0; i < aDict.Length; i++)
dataGridView1.Rows.Add(aDict[i].Word,
Convert.ToString(aDict[i].Count));
}
}
После завершения чтения файла массив aDict[] выводится в элементы listBox2 и dataGridView1.
Процедура Parser(s) из строки s методом Split() создает массив слов sArr[]. Затем каждое слово массива sArr[] анализируется: если его нет в массиве aDict[], то длина массива aDict[] увеличивается и слово запоминается:
Листинг 10.6. Метод Parser()
public void Parser(string s)
{
if ((s != null) && (s != ""))
{
char[] separators =
{' ',',','.',':',';','}','{','=','(',')'};
string[] sArr = s.Split(separators,
StringSplitOptions.RemoveEmptyEntries);
// не включать пустые строки
// попытаться найти слово
for (int i = 0; i < sArr.Length; i++)
{
int n = FindWord(sArr[i]);
if (n == -1)
{
int L = aDict.Length;
Array.Resize<tDict>(ref aDict, ++L);
aDict[L - 1].word = sArr[i];
aDict[L - 1].count = 1;
}
else
aDict[n].count++;
}
}
}
Приведем код функции FindWord(), которая пытается найти номер слова s в массиве aDict[]. Если слово найдено, то функция вернет номер этого слова, иначе она вернет -1:
Листинг 10.7. Функция поиска FindWord()
public int FindWord(string s)
{
int L = aDict.Length;
int i = -1;
bool ok = false;
while ((i < L - 1) && !ok)
ok = aDict[++i].word == s;
if (ok) return i; else return -1;
}
На рис. 10.2 представлены результаты работы этой программы для текста самой этой программы.