ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3193

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

//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


//

номером строки

Console.Write("{0:D3} - ", nLine);

DumpBuffer(buffer, numBytes),-

//

После каждых 2 0 строк останавливаемся, так как

// прокрутка консольного окна отсутствует

if

((nLine % 20) == 0)

{

 

Console.WriteLine("Нажмите <Enter> для вывода " + "очередных 20 строк");

Console.ReadLine();

}

}

//DumpBuffer - вывод буфера символов в виде единой

//строки в шестнадцатеричном формате

public static void DumpBuffer(byte[] buffer, int numBytes)

for(int index = 0; index < numBytes; index++)

byte b = buffer[index] ,• Console.Write("{0:X2}, ", b) ,-

Console.WriteLine();

}

}

}

В командной строке пользователь указывает каталог, применяемый в качестве apryl мента программы. Приведенная далее команда выведет шестнадцатеричный дамп каждо- [ го файла из временного каталога (как текстовых, так и бинарных файлов):

l o o p t h r o u g h f i l e s c : \ r a n d y \ t e m p

Если не ввести имя файла, программа по умолчанию использует текущий каталог.! (Шестнадцатеричный дамп выводит все числа в шестнадцатеричной системе счисле-j ния — см. врезку "Шестнадцатеричные числа".)

Шестнадцатеричные числа

Как и бинарные числа (0 и 1), шестнадцатеричные числа также очень важны в компью­ терном программировании. В шестнадцатеричной системе счисления цифрами явля­ ются обычные десятичные цифры 0-9 и буквы А, В, С, D, Е, F — где А = 10, В = 11, F = 15. Для иллюстрации (префикс Ох указывает на шестнадцатеричность выводи­ мого числа): OxD = 13. 0x10 = 16: 1*16 + 0*1. 0х2А = 42: 2*16 + А*1 (здесь А*1 = 10*1). Буквы могут быть как строчными, так и прописными: F означает то же, что ит. Эти числа выглядят причудливо, но они очень полезны, в особенности при отладке

или работе с аппаратной частью или содержимым памяти.

Демонстрационные программы FileRead и FileWrite считывали имена файлов с консоли, в то время как в этой программе имя файла передается в ко­ мандной строке. Поверьте, вас никто не пытается запутать, а всего лишь пред­ лагаются различные варианты решения одной и той же задачи.

448

Часть VII. Дополнительные главы


Первая строка демонстрационной программы LoopThroughFiles определяет на­ личие аргумента в командной строке. Если список аргументов пуст (args. Length ра­ вен 0), программа вызывает Directory. GetCurrentDirectory ( ) . Если программа запущена из Visual Studio, а не из командной строки, то по умолчанию будет использо­ ваться подкаталог bin\Debug в каталоге проекта LoopThroughFiles.

Класс Directory предоставляет пользователю

набор методов

для работы

с каталогами, а класс Filelnf о— методы для

перемещения,

копирования

и удаления файлов.

 

 

Затем программа получает список всех файлов в указанном каталоге посредством вы­ зова GetFileList ( ) . Эта функция возвращает массив объектов Filelnf о. Каждый объект Filelnf о содержит информацию о ф а й л е — например, имя файла (как полное имя с путем, FullName, так и без пути — Name), дату его создания и время последнего изменения. Функция Main () проходит по всему списку файлов с помощью цикла foreach. Она выводит имя каждого файла и передает его функции DumpHex () для вы­ вода содержимого на консоль.

Пауза в конце каждого цикла позволяет программисту просмотреть выведенную DumpHex () информацию.

Функция GetFileList () начинает работу с создания пустого списка Filelnf о, который будет возвращен в случае ошибки.

Этот прием стоит запомнить и использовать при работе с функциями Get...List (): если происходит ошибка, вывести сообщение о ней и вернуть пустой список.

Будьте внимательны при возврате ссылок. Например, не возвращайте ссылки ни на одну из внутренних очередей в классе PriorityQueue в главе 15, "Обобщенное программирование", если не хотите намеренно пригласить поль­ зователей мешать нормальной работе класса (работой не посредством методов класса, а напрямую с очередями). Но GetFileList (} не дает вам доступа к внутренностям одного из ваших классов, так что в данном случае все в порядке.

Затем функция GetFileList () создает объект Directorylnf о. Как и гласит его имя, объект Directorylnf о содержит тот же вид информации о каталоге, что и объект Filelnf о о файле. Однако у объекта Directorylnf о есть доступ к одной вещи, к ко­ торой нет доступа у объекта Filelnf о, а именно к списку файлов каталога в виде мас­ сива Filelnfо.

Как обычно, функция GetFileList () помещает код, работающий с файлами и ка­ талогами, в большой try-блок. Конструкция catch в конце функции перехватывает все генерируемые ошибки и выводит имя каталога (которое, вероятно, введено неверно, т.е.

такого каталога не существует).

 

Функция DumpHex ()

несколько сложнее из-за трудностей в форматировании вывода.

Функция DumpHex ()

начинает работу с открытия файла. Объект

Filelnf о содер­

жит информацию о файле, но не открывает его. Функция DumpHex ()

получает полное

имя файла, включая путь. Затем она открывает FileStream в режиме только для чте­ ния с использованием этого имени. Блок catch перехватывает исключение, если FileStream не в состоянии прочесть файл по той или иной причине.

Затем DumpHex () считывает файл по 10 байт за раз и выводит их в одну строку в шестнадцатеричном формате. После вывода каждых 20 строк программа приостанавли­ вает работу в ожидании нажатия пользователем клавиши <Enter>.

Глава 20. Работа с коллекциями

449


По вертикали консольное окно по умолчанию имеет 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. Дополнительные главы