C# для чайников
.pdf
Глава 20
Работа с коллекциями
В этой главе...
УКаталог как коллекция
>Реализация коллекции LinkedLi st
>Итеративный обход коллекции LinkedList
>Реализация индексирования для упрощения доступа к объектам коллекций
>Упрощение циклического обхода коллекции с помощью нового блока итератора С#
айл представляет собой один из типов коллекций данных, но существуют и дру гие коллекции. Например, каталог можно рассматривать как коллекцию файлов.
Кроме того, С# предоставляет множество типов контейнеров в оперативной памяти.
Эта глава построена на основе главы 15, "Обобщенное программирование", и мате риале, посвященном файлам, из главы 19, "Работа с файлами и библиотеками". Основ ной вопрос, рассматриваемый в данной главе — проход (итерирование) по коллекциям разного вида, от каталогов до массивов и списков всех видов. Вы также узнаете, как на писать собственный класс коллекции (более фундаментальный, чем рассматривавшийся в главе 15, "Обобщенное программирование", пример очереди с приоритетами)— свя занный список.
Чтение и запись — вот основное, что необходимо знать для работы с файлами. Иименно этим и занимались демонстрационные программы FileRead и FileWrite из главы 19, "Работа с файлами и библиотеками". Однако в ряде случаев вам просто нужно просканировать каталог файлов в поисках чего-то.
Приведенная далее демонстрационная программа LoopThroughFiles просматривает все файлы в данном каталоге, считывая каждый файл и вы водя его содержимое на консоль в шестнадцатеричном формате. (Это де монстрирует вам, что файл можно выводить не только в виде строк. Что -та кое шестнадцатеричный формат — вы узнаете немного позже.)
Если запустить эту программу в каталоге с большим количеством файлов, то вывод шестнадцатеричного дампа может занять длительное время. Много времени требует и вывод дампа большого файла. Либо испытайте програм му на каталоге покороче, либо, когда вам надоест, просто нажмите клавиши <Ctrl+C>. Эта команда должна прервать выполнение программы в любом консольном окне.
//LoopThroughFiles - проход по всем файлам, содержащимся в
//каталоге. Здесь выполняется вывод шестнадцатеричного
// |
дампа файла на экран, но могут выполняться и любые иные |
// |
действия |
using System; using System. 10,-
namespace LoopThroughFiles
{
public class Program
{
public static void Main(string [] args)
{
// Если каталог не указан...
string sDirectoryName; if (args.Length == 0)
{
// ... получаем имя текущего каталога...
sDirectoryName = Directory.GetCurrentDirectory();
}
else
{
//...в противном случае считаем, что первый
//переданный программе аргумент и есть имя
//используемого каталога
sDirectoryName = args[0];
}
Console.WriteLine(sDirectoryName);
//Получение списка всех файлов каталога FileInfo[] files = GetFileList(sDirectoryName);
//Проход по всем файлам списка с выводом
//шестнадцатеричного дампа каждого файла
foreach(Filelnfо file in files)
{
// Вывод имени файла Console.WriteLine("\п\пДамп файла { о } : " ,
file.FullName);
//Вывод содержимого файла DumpHex(file);
//Ожидание подтверждения пользователя Console.WriteLine("\пНажмите <Enter> для вывода " +
"следующего файла"); Console.ReadLine() ;
}
//Файлы закончились! Console.WriteLine("\пБольше файлов нет");
//Ожидаем подтверждения пользователя Console.WriteLine("Нажмите <Enter> для " +
"завершения программы...");
Console.Read();
}
// |
GetFileList - получение списка всех файлов в |
|
// |
указанном |
каталоге |
public static |
FileInfo[] |
|
446 |
GetFileList(string sDirectoryName) |
|
|
Часть VII. Дополнительные главы |
|
{
// Начинаем с пустого списка Filelnfot] files = new Filelnfо [Obtry
{
//Получаем информацию о каталоге Directorylnfо di =
new Directorylnfо(sDirectoryName);
//В ней имеется список файлов
files = di.GetFiles();
}
catch(Exception e)
|
{ |
|
|
|
|
Console .WriteLine ( "Каталог \"" |
+ sDirectoryName + |
||
|
|
|
" \" неверен") ,- |
|
|
Console.WriteLine(e.Message); |
|
||
|
} |
|
|
|
|
return files; |
|
||
} |
|
|
|
|
// |
DumpHex - |
для заданного файла выводит его содержимое |
||
// |
на |
консоль |
|
|
public |
static |
void DumpHex(Filelnfо |
file) |
|
{ |
|
|
|
|
|
// Открываем файл |
|
||
|
FileStream |
fs; |
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
string sFileName = file.FullName; |
|||
|
fs |
= new |
FileStream(sFileName, |
FileMode.Open, |
|
|
|
FileAccess.Read); |
|
//В действительности Filelnfо предоставляет метод
//file.OpenRead(), который открывает FileStream за
//вас, если вы слишком ленивы
}
catch(Exception е)
{
Console.WriteLine("\пНе могу читать \"" + file.FullName + " \ " " ) ;
Console.WriteLine(е.Message);
return;
}
// Построчный проход по содержимому файла for(int nLine = 1; true; nLine++)
{
// Считываем очередные 10 байтов (это все, что можно
//разместить в одной строке); выходим, когда все
//байты считаны
byte[] buffer = new byte [10] ;
int numBytes = fs.Read(buffer, 0, buffer.Length); if (numBytes == 0)
{
return;
}
Глава 20. //РаботаВыводис коллекциямисчитанные только что данные, предваряя их 447
По вертикали консольное окно по умолчанию имеет 25 строк (правда, пользо ватель может изменить эту настройку, добавив или убрав строки). Это означа ет, что вы должны делать паузу после вывода каждых 20 строк или около того, В противном случае данные будут быстро выведены на экран и пользователь не сможет их прочесть.
Операция деления по модулю (%) возвращает остаток после деления. То есть выраже ние (nLine%20) = = 0 истинно при значениях nLine, равных 20, 40, 60, 80.... Словом, идея понятна. Это важный метод, применимый для всех видов циклов, когда нужно вы полнять некоторую операцию только с определенной частотой.
Функция DumpBuf fer () выводит каждый член массива байтов с использованием управляющего элемента форматирования Х2. Х2 хотя и звучит как название какого-то секретного военного эксперимента, означает всего лишь "вывести число в виде двух шестнадцатеричных цифр" (см. главу 9, "Работа со строками в С#").
Диапазон значений byte — от 0 до 255, или OxFF — т.е. двух шестнадцатеричных цифр для вывода одного байта достаточно.
Вот как выглядят первые 20 строк при выводе содержимого файла output.txt. Даже его собственная мать не узнала бы его в таком виде...
Дамп |
|
файла С:\C#ProgramsVi\holdtank\Test2\bin\output.txt: |
|||||||
001 |
- |
53, 74, 72, 65, 61, 6D, |
20, |
28, |
70, |
72, |
|||
002 |
- |
6F, 74, 65, 63, 74, 65, |
64, |
29, |
0D, |
OA, |
|||
003 |
- |
20, 20, 46, 69, 6C, 65, |
53, |
74, |
72, |
65, |
|||
004 |
- |
61, 6D, 28, 73, 74, 72, |
69, |
6E, |
67, |
2C, |
|||
005 |
- |
20, 46, 69, 6C, 65, 4D, |
6F, |
64, |
65, |
2C, |
|||
006 |
- |
20, 46, 69, 6C, 65, 41, |
63, |
63, |
65, |
73, |
|||
007 |
- |
73, 29, OD, OA, 20, 20, |
4D, |
65, |
6D, |
6F, |
|||
008 |
- |
72, 79, 53, 74, 72, 65, |
61, |
6D, |
28, |
29, |
|||
009 |
- |
3B, OD, |
OA, |
20, |
20, 4E, |
65, |
74, |
77, |
6F, |
010 |
- |
72, 6B, |
53, |
74, |
72, 65, |
61, |
6D, |
OD, |
OA, |
011 |
- |
20, 20, 42, 75, 66, 66, |
65, |
72, |
53, |
74, |
|||
012 |
- |
72, 65, |
61, |
6D, |
20, 2D, |
20, |
62, |
75, |
66, |
013 |
- |
66, 65, |
72, |
73, |
20, 61, |
6E, |
20, |
65, |
78, |
014 |
- |
69, 73, |
74, |
69, |
6E, 67, |
20, |
73, |
74, |
72, |
015 |
- |
65, 61, |
6D, |
20, |
6F, 62, |
6A, |
65, |
63, |
74, |
016 |
- |
OD, OA, OD, OA, 42, 69, |
6E, |
61, |
72, |
79, |
|||
017 |
- |
52, 65, |
61, |
64, |
65, 72, |
20, |
2D, |
20, |
72, |
018 |
- |
65, 61, |
64, |
20, |
69, 6E, |
20, |
76, |
61, |
72, |
019 |
- |
69, 6F, |
75, |
73, |
20, 74, |
79, |
70, |
65, |
73, |
020 |
- |
20, 28, |
43, |
68, |
61, 72, |
2C, |
20, |
49, |
6E, |
Нажмите <Enter> для вывода очередных 2 0 строк
Можно восстановить файл в виде строк из вывода в шестнадцатеричном фор мате. 0x61 — числовой эквивалент символа а. Буквы, расположены в алфавит ном порядке, так что 0x65 должно быть символом е. 0x20 — пробел. Приве денная здесь первая строка выглядит при обычной записи в виде строк как " S t r e a m ( р г " . Интригующе, не правда ли? Полностью коды букв вы можете найти в разделе "ASCII, table of codes" справочной системы.
Эти коды корректны и при использовании набора символов Unicode, который приме няется С# по умолчанию (побольше о Unicode вы можете узнать, прогулявшись в Интер нете в поисках "Unicode characters").
450 |
Часть VII. Дополнительные главы |
