русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Передача параметров в метод Main из командной строки


Дата добавления: 2013-12-23; просмотров: 2835; Нарушение авторских прав


Запуск программы из командной строки

Замечание. Далее мы будем работать с командным окном SDK Command Prompt

Вариант 2

Вариант 1

Компиляция программы из командной строки

  1. Создайте новый проект или откройте старый, который выводит на экран сообщение:
2. "Привет!"
  1. Сохраните исходный текст программы на диск D в папку Temp c именем Program.cs
  1. Выполните последовательность действий: Пуск - Все программы - Microsoft Visual Studio 2005 - Visual Studio 2005 Tools - Visual Studio 2005 Command Prompt
  2. Откроется консольное окно:

  1. Выполните последовательность действий: Пуск - Все программы - Microsoft .Net Framwork SDK v2.0 - SDK Command Prompt
  2. Откроется консольное окно:

  1. В командной строке окна запишите следующую команду:
4. csc /out:d:\temp\hello.exe d:\temp\Program.cs

где csc - команда компиляции исполняемого файла

/out - определяет местоположение и название скомпилированного файла, в нашем случае исполняемый файл называется hello.exe и будет располагаться в папке temp диска d.

d:\temp\Program.cs - определяет местоположение и название исходного файла.

  1. Для выполнения команды нажмите клавишу Enter:

Замечание. В данном случае компиляция прошла успешно. В противном случае на экране будет выведено сообщение о том, по какой причине компиляция не возможна. Наиболее часто пользователь неверно указывает путь к файлам или допускает ошибку в имени исходного файла.

В командной строке SDK Commond Prompt указать полный путь к файлу, например, d:\temp\hello.exe и нажать клавишу Enter.

В нашем случае консольное окно примет вид:

  1. Создадим новый проект, в котором содержится следующий код:
2. static void Main(string[] args) //метод принимает параметры в виде массива строк3. {4. Console.WriteLine("Командная строка содержит" + args.Length + "аргументов.\n Вот они");5. for (int i = 0; i < args.Length; i++) //просматриваем содержимое массива args6. Console.WriteLine(args[i]);7. }
  1. Сохраним данный проект в папку temp на диске d.
  2. Запустим SDK Commond Prompt, сгенерируем exe файл и запустим его:



В данном случае никакие параметры при вызове Program.exe не передавались, поэтому список аргументов пуст.

  1. Теперь при обращении к исполняемому файлу после указания его местоположения запишем строку один два три четыре пять и нажмем клавишу Enter.

В нашем случае строка "один два три четыре пять" была передана в метод Main. При передаче строка автоматически разбивается пробелами на подстроки, которые записываются массив args.

  1. Параметры в метод Main могут передаваться только в виде массива строк, но элементы этого массива внутри метода Main могут быть преобразованы к нужном типу.
  2. Внесем изменения в код метода Main:
13. static void Main(string[] args)14. {15. if (args.Length ==2)16. {17. try18. {19. int a = int.Parse(args[0]);20. int b = int.Parse(args[1]);21. Console.WriteLine("{0} + {1} = {2}", a, b, a + b);22. }23. catch (FormatException)24. {25. Console.WriteLine("передаваемые параметры должны быть целыми числами");26. }27. }28. else Console.WriteLine("В метод Main следует передавать два целочисленных параметра");29. }
  1. Сохраните данный файл в папку temp на диске d, и не забудьте сгенерировать исполняемый файл.
  2. Несколько раз вызовите исполняемый файл из консольного окна, используя разное количество параметров и разные типы параметров:


Лекция 10. Регулярные выражения

Стандартный класс string позволяет выполнять над строками различные операции, в том числе поиск, замену, вставку и удаление подстрок. Тем не менее, есть классы задач по обработке символьной информации, где стандартных возможностей явно не хватает. Чтобы облегчить решение подобных задач, в Net Framework встроен более мощный аппарат работы со строками, основанный на регулярных выражениях.

Регулярные выражения предназначены для обработки текстовой информации и обеспечивают:

  1. Эффективный поиск в тексте по заданному шаблону;
  2. Редактирование текста;
  3. Формирование итоговых отчетов по результатам работы с текстом.

Подробно рассмотрим первые два аспекта применения регулярных выражений.

10.1 Метасимволы в регулярных выражениях

Регулярное выражение - это шаблон, по которому выполняется поиск соответствующего фрагмента текста. Язык описания регулярных выражений состоит из символов двух видов: обычных символов и метасимволов. Обычный символ представляет в выражении сам себя, а метасимвол - некоторый класс символов.

Рассмотрим наиболее употребительные метасимволы:

Класс символов Описание Пример
. Любой символ, кроме \n. Выражение c.t соответствует фрагментам: cat, cut, c#t, c{t и т.д.
[] Любой одиночный символ из последовательности, записанной внутри скобок. Допускается использование диапазонов символов. Выражение c[aui]t соответствует фрагментам: cat, cut, cit. Выражение c[a-c]t соответствует фрагментам: cat, cbt, cct.
[^] Любой одиночный символ, не входящий в последовательность, записанную внутри скобок. Допускается использование диапазонов символов. Выражение c[^aui]t соответствует фрагментам: cbt, cct, c2t и т.д. Выражение c[^a-c]t соответствует фрагментам: cdt, cet, c%t и т.д.
\w Любой алфавитно-цифровой символ. Выражение c\wt соответствует фрагментам: cbt, cct, c2t и т.д., но не соответствует фрагментам c%t, c{t и т.д.
\W Любой не алфавитно-цифровой символ. Выражение c\Wt соответствует фрагментам: c%t, c{t, c.t и т.д., но не соответствует фрагментам cbt, cct, c2t и т.д.
\s Любой пробельный символ. Выражение \s\w\w\w\s соответствует любому слову из трех букв, окруженному пробельными символами.
\S Любой не пробельный символ. Выражение \s\S\S\S\s соответствует любым трем непробельным символам, окруженным пробельными.
\d Любая десятичная цифра Выражение c\dt соответствует фрагментам: c1t, c2t, c3t и т.д.
\D Любой символ, не являющийся десятичной цифрой Выражение c\Dt не соответствует фрагментам: c1t, c2t, c3t и т.д.

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

Уточняющие символы Описание
^ Фрагмент, совпадающий с регулярными выражениями, следует искать только в начале строки
$ Фрагмент, совпадающий с регулярными выражениями, следует искать только в конце строки
Фрагмент, совпадающий с регулярными выражениями, следует искать только в начале многострочной строки
\Z Фрагмент, совпадающий с регулярными выражениями, следует искать только в конце многострочной строки
\b Фрагмент, совпадающий с регулярными выражениями, начинается или заканчивается на границе слова, т.е. между символами, соответствующими метасимволам \w и \W
\B Фрагмент, совпадающий с регулярными выражениями, не должен встречаться на границе слов

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

Повторители Описание Пример
* Ноль или более повторений предыдущего элемента Выражение ca*t соответствует фрагментам: ct, cat, caat, caaat и т.д.
+ Одно или более повторений предыдущего элемента Выражение ca+t соответствует фрагментам: cat, caat, caaat и т.д.
? Не более одного повторения предыдущего элемента Выражение ca?t соответствует фрагментам: ct, cat.
{n} Ровно n повторений предыдущего элемента Выражение ca{3}t соответствует фрагменту: cаааt. Выражение (cat){2} соответствует фрагменту: cаtcat.
{n,} По крайней мере n повторений предыдущего элемента Выражение ca{3,}t соответствует фрагментам: cаааt, caaaat, caaaaaaat и т.д. Выражение (cat){2,} соответствует фрагментам: catcat, catcatcat и т.д.
{n, m} От n до m повторений предыдущего элемента Выражение ca{2, 4}t соответствует фрагментам: cааt, caaat, caaaat.

Регулярное выражение записывается в виде строкового литерала, причем перед строкой необходимо ставить символ @, который говорит о том, что строку нужно будет рассматривать и в том случае, если она будет занимать несколько строчек на экране. Однако символ @ можно не ставить, если в качестве шаблона используется шаблон без метасимволов.

Замечание. Если нужно найти какой-то символ, который является метасимволом, например, точку, можно это сделать защитив ее обратным слэшем. Т.е. просто точка означает любой одиночный символ, а \. означает просто точку.

Примеры регулярных выражений:

  1. слово rus -
2. @"rus" или "rus"
  1. номер телефона в формате xxx-xx-xx - @"\d\d\d-\d\d-\d\d" или @"\d{3}(-\d\d){2}"
  2. номер автомобиля - @"[A-Z]\d{3}[A-Z]{2}\d{2,3}RUS"

Задания. Запишите регулярное выражение, соответствующее:

  1. 1. дате в формате дд.мм.гг или дд.мм.гггг
  2. 2. времени в формате чч.мм или чч:мм
  3. 3. целому числу (со знаком и без)
  4. 4. вещественному числу (со знаком и без, с дробной частью и без, с целой частью и без)

10.2 Поиск в тексте по шаблону

Пространство имен библиотеки базовых классов System.Text.RegularExpressions содержит все объекты платформы .NET Framework, имеющие отношение к регулярным выражениям. Важнейшим классом, поддерживающим регулярные выражения, является класс Regex, который представляет неизменяемые откомпилированные регулярные выражения. Для описания регулярного выражения в классе определено несколько перегруженных конструкторов:

  1. Regex() - создает пустое выражение;
  2. Regex(String) - создает заданное выражение;
  3. Regex(String, RegexOptions) - создает заданное выражение и задает параметры для его обработки с помощью элементов перечисления RegexOptions (например, различать или нет прописные и строчные буквы).

Поиск фрагментов строки, соответствующих заданному выражению, выполняется с помощью методов IsMach, Mach, Matches класса Regex.

Метод IsMach возвращает true, если фрагмент, соответствующий выражению, в заданной строке найден, и false в противном случае. Например, попытаемся определить, встречается ли в заданном тексте слово собака:

static void Main(){ Regex r = new Regex("собака",RegexOptions.IgnoreCase); string text1 = "Кот в доме, собака в конуре."; string text2 = "Котик в доме, собачка в конуре."; Console.WriteLine(r.IsMatch(text1)); Console.WriteLine(r.IsMatch(text2)); }

Замечание. RegexOptions.IgnoreCase - означает, что регулярное выражение применяется без учеба регистра символов

Можно использовать конструкцию выбора из нескольких элементов. Варианты выбора перечисляются через вертикальную черту. Например, попытаемся определить, встречается ли в заданном тексте слов собака или кот:

static void Main(string[] args){ Regex r = new Regex("собака|кот",RegexOptions.IgnoreCase); string text1 = "Кот в доме, собака в конуре."; string text2 = "Котик в доме, собачка в конуре."; Console.WriteLine(r.IsMatch(text1)); Console.WriteLine(r.IsMatch(text2)); }

Попытаемся определить, есть ли в заданных строках номера телефона в формате xx-xx-xx или xxx-xx-xx:

static void Main(){ Regex r = new Regex(@"\d{2,3}(-\d\d){2}"); string text1 = "tel:123-45-67"; string text2 = "tel:no"; string text3 = "tel:12-34-56"; Console.WriteLine(r.IsMatch(text1)); Console.WriteLine(r.IsMatch(text2)); Console.WriteLine(r.IsMatch(text3));}

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

Метод Match класса Regex не просто определяет, содержится ли текст, соответствующий шаблону, а возвращает объект класса Match - последовательность фрагментов текста, совпавших с шаблоном. Следующий пример позволяет найти все номера телефонов в указанном фрагменте текста:

static void Main(){ Regex r = new Regex(@"\d{2,3}(-\d\d){2}"); string text = @"Контакты в Москве tel:123-45-67, 123-34-56; fax:123-56-45 Контакты в Саратове tel:12-34-56; fax:12-56-45"; Match tel = r.Match(text); while (tel.Success) { Console.WriteLine(tel); tel = tel.NextMatch(); }}

Следующий пример позволяет подсчитать сумму целых чисел, встречающихся в тексте:

static void Main(){ Regex r = new Regex(@"[-+]?\d+"); string text = @"5*10=50 -80/40=-2"; Match teg = r.Match(text); int sum = 0; while (teg.Success) { Console.WriteLine(teg); sum += int.Parse(teg.ToString()); teg = teg.NextMatch(); } Console.WriteLine("sum=" + sum);}

Задание. Измените программу так, чтобы на экран дополнительно выводилось количество найденных чисел.

Метод Matches класса Regex возвращает объект класса MatchCollection - коллекцию всех фрагментов заданной строки, совпавших с шаблоном. При этом метод Matches многократно запускает метод Match, каждый раз начиная поиск с того места, на котором закончился предыдущий поиск.

static void Main(string[] args) { string text = @"5*10=50 -80/40=-2"; Regex theReg = new Regex(@"[-+]?\d+"); MatchCollection theMatches = theReg.Matches(text); foreach (Match theMatch in theMatches) { Console.Write("{0} ", theMatch.ToString()); } Console.WriteLine(); }}

10.3 Редактирование текста

Регулярные выражения могут эффективно использоваться для редактирования текста. Например, метод Replace класса Regex позволяет выполнять замену одного фрагмента текста другим или удаление фрагментов текста:

Пример 1. Изменение номеров телефонов:

static void Main(string[] args) { string text = @"Контакты в Москве tel:123-45-67, 123-34-56; fax:123-56-45. Контакты в Саратове tel:12-34-56; fax:11-56-45"; Console.WriteLine("Старые данные\n"+text); string newText=Regex.Replace(text, "123-", "890-"); Console.WriteLine("Новые данные\n" + newText); }

Задание. Измените программу так, чтобы шестизначные номера заменялись на семизначные добавлением 0 после первых двух цифр. Например, номер 12-34-56 заменился бы на 120-34-56.

Пример 2. Удаление всех номеров телефонов из текста:

static void Main() { string text = @"Контакты в Москве tel:123-45-67, 123-34-56; fax:123-56-45. Контакты в Саратове tel:12-34-56; fax:12-56-45"; Console.WriteLine("Старые данные\n"+text); string newText=Regex.Replace(text, @"\d{2,3}(-\d\d){2}", ""); Console.WriteLine("Новые данные\n" + newText); }}

Задание. Измените программу так, чтобы из текста удалялись слова tel и fax (если после данных слов стоят двоеточия, то их тоже следует удалить).

Пример 3. Разбиение исходного текста на фрагменты:

static void Main(){ string text = @"Контакты в Москве tel:123-45-67, 123-34-56; fax:123-56-45. Контакты в Саратове tel:12-34-56; fax:12-56-45"; string []newText=Regex.Split(text,"[ ,.:;]+"); foreach( string a in newText) Console.WriteLine(a);}

Задание. Разместите текст на одной строке и посмотрите, как изменится вывод данных. Объясните результаты.

Самостоятельная работа

Класс Group позволяет группировать соответствия на основе синтаксиса регулярных выражений и представлять результаты действия одного группирующего выражения. Группирующее выражение именует группу и задает регулярное выражение. Любой фрагмент строки, удовлетворяющий этому регулярному выражению, будет добавлен в группу. Например, группу ip можно задать следующим выражением:

@"(?<ip>(\d|\.)+)\s"

В данной записи (? ) говорит о том, что начинает формироваться группа, <ip> определяет имя данной группы, а (\d|\.)+)\s определяет шаблон регулярного выражения, который будет связан с этой группой. Если при поиске фрагмент текста будет соответствовать данному шаблону, то этот фрагмент будет заноситься в группу ip.

Класс Match является производным от класса Group и имеет коллекцию Groups, которая содержит все группы, обнаруженные объектом Match. Создание и использование коллекции Groups и классов Group иллюстрируется следующим примером:

static void Main(string[] args){ string text = @"04:55:34 223.34.12.156 www.aaa.ru 04:59:55 213.134.112.56 www.bbb.cc.com 05:05:01 223.34.12.156 www.aaa.ru"; Regex theReg = new Regex(@"(?<time>(\d|\:)+)\s"+ @"(?<ip>(\d|\.)+)\s"+ @"(?<site>\S+)"); MatchCollection theMatches = theReg.Matches(text); foreach (Match theMatch in theMatches) { if (theMatch.Length != 0) { Console.WriteLine("\ntheMatch: {0}", theMatch.ToString()); //1 Console.WriteLine("time: {0}", theMatch.Groups["time"]); //2 Console.WriteLine("ip: {0}", theMatch.Groups["ip"]); //3 Console.WriteLine("site: {0}", theMatch.Groups["site"]); //4 } }}

В этом примере строка 1 целиком выводит фрагмент текста совпавший с регулярным выражением, а строки 2-4, то только тот текст, который был помещен в конкретную группу

Практическое задание

  1. Шаблоны регулярных выражений для групп time, ip и site записаны в упрощенном виде. Преобразуйте их к такому виду, чтобы они соответствовали ограничениям, накладываемым на формат времени, ip-адреса и адреса web-сайта.
  2. Используя дополнительную литературу и Интернет, более подробно изучите работу с классом Group и коллекцией Groups класса Match

Лекция 11. Организация С#-системы ввода-вывода

С#-программы выполняют операции ввода-вывода посредством потоков, которые построены на иерархии классов. Поток (stream) - это абстракция, которая генерирует и принимает данные. С помощью потока можно читать данные из различных источников (клавиатура, файл) и записывать в различные источники (принтер, экран, файл). Несмотря на то, что потоки связываются с различными физическими устройствами, характер поведения всех потоков одинаков. Поэтому классы и методы ввода-вывода можно применить ко многим типам устройств.

На самом низком уровне иерархии потоков ввода-вывода находятся потоки, оперирующие байтами. Это объясняется тем, что многие устройства при выполнении операций ввода-вывода ориентированы на байты. Однако для человека привычнее оперировать символами, поэтому разработаны символьные потоки, которые фактически представляют собой оболочки, выполняющие преобразование байтовых потоков в символьные и наоборот. Кроме этого, реализованы потоки для работы с int-, double-, short- значениями, которые также представляют оболочку для байтовых потоков, но работают не с самими значениями, а с их внутренним представлением в виде двоичных кодов.

Центральную часть потоковой С#-системы занимает класс Stream пространства имен System.IO. Класс Stream представляет байтовый поток и является базовым для всех остальных потоковых классов. Из класса Stream выведены такие байтовые классы потоков как:

  1. FileStream - байтовый поток, разработанный для файлового ввода-вывода
  2. BufferedStream - заключает в оболочку байтовый поток и добавляет буферизацию, которая во многих случаях увеличивает производительность программы;
  3. MemoryStream - байтовый поток, который использует память для хранения данных.

Программист может вывести собственные потоковые классы. Однако для подавляющего большинства приложений достаточно встроенных потоков.

Подробно мы рассмотрим класс FileStream, классы StreamWriter и StreamReader, представляющие собой оболочки для класса FileStream и позволяющие преобразовывать байтовые потоки в символьные, а также классы BinaryWriter и BinaryReader, представляющие собой оболочки для класса FileStream и позволяющие преобразовывать байтовые потоки в двоичные для работы с int-, double-, short- и т.д. значениями.

11.1 Байтовый поток

Чтобы создать байтовый поток, связанный с файлом, создается объект класса FileStream. При этом в классе определено несколько конструкторов. Чаще всего используется конструктор, который открывает поток для чтения и/или записи:

FileStream(string filename, FileMode mode)

где:

  1. параметр filename определяет имя файла, с которым будет связан поток ввода-вывода данных; при этом filename определяет либо полный путь к файлу, либо имя файла, который находится в папке bin/debug вашего проекта.
  2. параметр mode определяет режим открытия файла, который может принимать одно из возможных значений, определенных перечислением FileMode:
    • FileMode.Append - предназначен для добавления данных в конец файла;
    • FileMode.Create - предназначен для создания нового файла, при этом если существует файл с таким же именем, то он будет предварительно удален;
    • FileMode.CreateNew - предназначен для создания нового файла, при этом файл с таким же именем не должен существовать;
    • FileMоde.Open - предназначен для открытия существующего файла;
    • FileMode.ОpenOrCreate - если файл существует, то открывает его, в противном случае создает новый
    • FileMode.Truncate - открывает существующий файл, но усекает его длину до нуля

Если попытка открыть файл оказалась неуспешной, то генерируется одно из исключений: FileNotFoundException - файл невозможно открыть по причине его отсутствия, IOException - файл невозможно открыть из-за ошибки ввода-вывода, ArgumentNullException - имя файла представляет собой null-значение, ArgumentException - некорректен параметр mode, SecurityException - пользователь не обладает правами доступа, DirectoryNotFoundException - некорректно задан каталог.

Другая версия конструктора позволяет ограничить доступ только чтением или только записью:

FileStream(string filename, FileMode mode, FileAccess how)

где:

  1. параметры filename и mode имеют то же назначение, что и в предыдущей версии конструктора;
  2. параметр how, определяет способ доступа к файлу и может принимать одно из значений, определенных перечислением FileAccess:
  1. FileAccess.Read - только чтение;
  2. FileAccess.Write - только запись;
  3. FileAccess.ReadWrite - и чтение, и запись.

После установления связи байтового потока с физическим файлом внутренний указатель потока устанавливается на начальный байт файла.

Для чтения очередного байта из потока, связанного с физическим файлом, используется метод ReadByte(). После прочтения очередного байта внутренний указатель перемещается на следующий байт файла. Если достинут конец файла, то метод ReadByte() возвращает значение -1.

Для побайтовой записи данных в поток используется метод WriteByte().

По завершении работы с файлом его необходимо закрыть. Для этого достаточно вызвать метод Close (). При закрытии файла освобождаются системные ресурсы, ранее выделенные для этого файла, что дает возможность использовать их для работы с другими файлами.

Рассмотрим пример использования класса FileStream, для копирования одного файла в другой. Но вначале создадим текстовый файл text.txt в папке bin/debug текущего проекта. И внесем в него произвольную информацию, например:

12 456Hello! 23,67 4: Message using System;using System.Text;using System.IO; //для работы с потоками namespace MyProgram{ class Program { static void Main() { try { FileStream fileIn = new FileStream("text.txt", FileMode.Open, FileAccess.Read); FileStream fileOut = new FileStream("newText.txt", FileMode.Create, FileAccess.Write); int i; while ((i = fileIn.ReadByte())!=-1) { //запись очередного файла в поток, связанный с файлом fIleOut fileOut.WriteByte((byte)i); } fileIn.Close(); fileOut.Close(); } catch (Exception EX) { Console.WriteLine(EX.Message); } } }}

Задание. Подумайте, почему для переменной i указан тип int. Можно было бы указать тип byte?

11.2 Символьный поток

Чтобы создать символьный поток нужно поместить объект класса Stream (например, FileStream) "внутрь" объекта класса StreamWriter или объекта класса StreamReader. В этом случае байтовый поток будет автоматически преобразовываться в символьный.

Классе StreamWriter предназначен для организации выходного символьного потока. В нем определено несколько конструкторов. Один из них записывается следующим образом:

StreamWriter(Stream stream);

где параметр stream определяет имя уже открытого байтового потока.

Например, создать экземпляр класса StreamWriter можно следующим образом:

StreamWriter fileOut=new StreamWriter(new FileStream("text.txt", FileMode.Create, FileAccess.Write));

Этот конструктор генерирует исключение типа ArgumentException, если поток stream не открыт для вывода, и исключение типа ArgumentNullException, если он (поток) имеет null-значение.

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

StreamWriter(string name);

где параметр name определяет имя открываемого файла.

Например, обратиться к данному конструктору можно следующим образом:

StreamWriter fileOut=new StreamWriter("c:\temp\t.txt");

И еще один вариант конструктора StreamWriter:

StreamWriter(string name, bool appendFlag);

где параметр name определяет имя открываемого файла;

параметр appendFlag может принимать значение true - если нужно добавлять данные в конец файла, или false - если файл необходимо перезаписать.

Например:

StreamWriter fileOut=new StreamWriter("t.txt", true);

Теперь для записи данных в поток fileOut можно обратиться к методу WriteLine. Это можно сделать следующим образом:

fileOut.WriteLine("test");

В данном случае в конец файла t.txt будет дописано слово test.

Класс StreamReader предназначен для организации входного символьного потока. Один из его конструкторов выглядит следующим образом:

StreamReader(Stream stream);

где параметр stream определяет имя уже открытого байтового потока.

Этот конструктор генерирует исключение типа ArgumentException, если поток stream не открыт для ввода.

Например, создать экземпляр класса StreamWriter можно следующим образом:

StreamReader fileIn = new StreamReader(new FileStream("text.txt", FileMode.Open, FileAccess.Read));

Как и в случае с классом StreamWriter у класса StreamReader есть и другой вид конструктора, который позволяет открыть файл напрямую:

StreamReader (string name);

где параметр name определяет имя открываемого файла.

Обратиться к данному конструктору можно следующим образом:

StreamReader fileIn=new StreamReader ("c:\temp\t.txt");

В C# символы реализуются кодировкой Unicode. Для того, чтобы можно было обрабатывать текстовые файлы, содержащие русский символы, созданные, например, в Блокноте, рекомендуется вызывать следующий вид конструктора StreamReader:

StreamReader fileIn=new StreamReader ("c:\temp\t.txt", Encoding.GetEncoding(1251));

Параметр Encoding.GetEncoding(1251) говорит о том, что будет выполняться преобразование из кода Windows-1251 (одна из модификаций кода ASCII, содержащая русские символы) в Unicode. Encoding.GetEncoding(1251) реализован в пространстве имен System.Text.

Теперь для чтения данных из потока fileIn можно воспользоваться методом ReadLine. При этом если будет достигнут конец файла, то метод ReadLine вернет значение null.

Рассмотрим пример, в котором данные из одного файла копируются в другой, но уже с использованием классов StreamWriter и StreamReader.

static void Main(){ StreamReader fileIn = new StreamReader("text.txt", Encoding.GetEncoding(1251)); StreamWriter fileOut=new StreamWriter("newText.txt", false); string line; while ((line=fileIn.ReadLine())!=null) //пока поток не пуст { fileOut.WriteLine(line); } fileIn.Close(); fileOut.Close();}

Задание. Выясните, для чего предназначен метод ReadToEnd() и когда имеется смысл его применять.

Таким образом, данный способ копирования одного файла в другой, даст нам тот же результат, что и при использовании байтовых потоков. Однако, его работа будет менее эффективной, т.к. будет тратиться дополнительное время на преобразование байтов в символы. Но у символьных потоков есть свои преимущества. Например, мы можем использовать регулярные выражения для поиска заданных фрагментов текста в файле.

static void Main(){ StreamReader fileIn = new StreamReader("text.txt"); StreamWriter fileOut=new StreamWriter("newText.txt", false); string text=fileIn.ReadToEnd(); Regex r= new Regex(@"[-+]?\d+"); Match integer = r.Match(text); while (integer.Success) { fileOut.WriteLine(integer); integer = integer.NextMatch(); } fileIn.Close(); fileOut.Close();}

11.3 Двоичные потоки

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

Выходной поток BinaryWriter поддерживает произвольный доступ, т.е. имеется возможность выполнять запись в произвольную позицию двоичного файла. Наиболее важные методы потока BinaryWriter:

Член класса Описание
BaseStream Определяет базовый поток, с которым работает объект BinaryWriter
Close Закрывает поток
Flush Очищает буфер
Seek Устанавливает позицию в текущем потоке
Write Записывает значение в текущий поток

Наиболее важные методы выходного потока BinaryReader:

Член класса Описание
BaseStream Определяет базовый поток, с которым работает объект BinaryReader
Close Закрывает поток
PeekChar Возвращает следующий символ потока без перемещения внутреннего указателя в потоке
Read Считывает очередной поток байтов или символов и сохраняет в массиве, передаваемом во входном параметре
ReadBoolean, ReadByte, ReadInt32 и т.д Считывает из потока данные определенного типа

Двоичный поток открывается на основе базового протока (например, FileStream), при этом двоичный поток будет преобразовывать байтовый поток в значения int-, double-, short- и т.д.

Рассмотрим пример формирования двоичного файла:

static void Main() { //открываем двоичный поток BinaryWriter fOut=new BinaryWriter(new FileStream("t.dat",FileMode.Create)); //записываем данные в двоичный поток for (int i=0; i<=100; i+=2) { fOut.Write(i); } fOut.Close(); //закрываем двоичный поток }

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

static void Main() { FileStream f=new FileStream("t.dat",FileMode.Open); BinaryReader fIn=new BinaryReader(f); long n=f.Length/4; //определяем количество чисел в двоичном потоке int a; for (int i=0; i<n; i++) { a=fIn.ReadInt32(); Console.Write(a+" "); } fIn.Close(); f.Close(); }

Двоичные файлы являются файлами с произвольным доступом, при этом нумерация элементов в двоичном файле ведется с нуля. Произвольный доступ обеспечивает метод Seek. Рассмотрим его синтаксис:

Seek(long newPos, SeekOrigin pos)

где параметр newPos определяет новую позицию внутреннего указателя файла в байтах относительно исходной позиции указателя, которая определяется параметром pos. В свою очередь параметр pos должен быть задан одним из значений перечисления SeekOrigin:

Значение Описание
SeekOrigin.Begin Поиск от начала файла
SeekOrigin.Current Поиск от текущей позиции указателя
SeekOrigin.End Поиск от конца файла

После вызова метода Seek следующие операции чтения или записи будут выполняться с новой позиции внутреннего указателя файла.

Рассмотрим пример организации произвольного доступа к двоичному файлу (на примере файла t.dat):

static void Main() { //изменение данных в двоичном потоке FileStream f=new FileStream("t.dat",FileMode.Open); BinaryWriter fOut=new BinaryWriter(f); long n=f.Length; //определяем количество байт в байтовом потоке int a; for (int i=0; i<n; i+=8) //сдвиг на две позиции, т.к. тип int занимает 4 байта { fOut.Seek(i,SeekOrigin.Begin); fOut.Write(0); } fOut.Close(); //чтение данных из двоичного потока f=new FileStream("t.dat",FileMode.Open); BinaryReader fIn=new BinaryReader(f); n=f.Length/4; //определяем количество чисел в двоичном потоке for (int i=0; i<n; i++) { a=fIn.ReadInt32(); Console.Write(a+" "); } fIn.Close(); f.Close(); }

Поток BinaryReader не имеет метода Seek, однако используя возможности потока FileStream можно организовать произвольный доступ при чтении двоичных файлов. Рассмотрим следующий пример:

static void Main(){ //Записываем в файл t.dat целые числа от 0 до 100 FileStream f=new FileStream("t.dat",FileMode.Open); BinaryWriter fOut=new BinaryWriter(f); for (int i=0; i<100; ++i) { fOut.Write(i);; } fOut.Close(); //Объекты f и fIn связаны с одним и тем же файлом f=new FileStream("t.dat",FileMode.Open); BinaryReader fIn=new BinaryReader(f); long n=f.Length; //определяем количество байт потоке //Читаем данные из файла t.dat, перемещая внутренний указатель на 8 байт, т.е. на два целых числа for (int i=0; i<n; i+=8) { f.Seek(i,SeekOrigin.Begin); int a=fIn.ReadInt32(); Console.Write(a+" "); } fIn.Close(); f.Close();}

11.4 Перенаправление стандартных потоков

Тремя стандартными потоками, доступ к которым осуществляется через свойства Console.Out, Console.In и Console.Error, могут пользоваться все программы, работающие в пространстве имен System. Свойство Console.Out относится к стандартному выходному потоку. По умолчанию это консоль. Например, при вызове метода Console.WriteLine() информация автоматически передается в поток Console.Out. Свойство Console.In относится к стандартному входному потоку, источником которого по умолчанию является клавиатура. Например, при вводе данных с клавиатуры информация автоматически передается потоку Console.In, к которому можно обратиться с помощью метода Console.ReadLine(). Свойство Console.Error относится к ошибкам в стандартном потоке, источником которого также по умолчанию является консоль. Однако эти потоки могут быть перенаправлены на любое совместимое устройство ввода-вывода, например, на работу с физическими файлами.

Перенаправить стандартный поток можно с помощью методов SetIn(), SetOut() и SetError(), которые являются членами класса Console:

static void Setln(TextReader input)static void SetOut(TextWriter output)static void SetError(TextWriter output)

Пример перенаправления потоков проиллюстрирован следующей программой, в которой двумерный массив вводится из файла input.txt, а выводится в файл output.txt

static void Main(){ try { int[,] MyArray; StreamReader file=new StreamReader("input.txt"); Console.SetIn(file); // перенаправляем стандартный входной поток на file string line=Console.ReadLine(); string []mas=line.Split(' '); int n=int.Parse(mas[0]);int m=int.Parse(mas[1]); MyArray = new int[n,m]; for (int i = 0; i < n; i++) { line = Console.ReadLine(); mas = line.Split(' '); for (int j = 0; j < m; j++) { MyArray[i,j] = int.Parse(mas[j]); } } PrintArray("исходный массив:", MyArray, n, m); file.Close();} static void PrintArray(string a, int[,] mas, int n, int m){ StreamWriter file=new StreamWriter("output.txt"); // перенаправляем стандартный входной поток на file Console.SetOut(file); Console.WriteLine(a); for (int i = 0; i < n; i++) { for (int j=0; j<m; j++) Console.Write("{0} ", mas[i,j]); Console.WriteLine(); } file.Close();} ___input.txt_________3 41 4 2 84 9 0 15 7 4 2

При необходимости восстановить исходное состояние потока Console.In можно следующим образом:

TextWriter str = Console.In; // первоначально сохраняем исходное состояние входного потока…Console.SetIn(str); // при необходимости восстанавливаем исходное состояние входного потока

Аналогичным образом можно восстановить исходное состояние потока Console.Out:

TextWriter str = Console.Out; // первоначально сохраняем исходное состояние выходного потока…// при необходимости восстанавливаем исходное состояние выходного потокаConsole.SetOut(str);

Задание. Подумайте для чего нужно два потока Console.Out и Console.Error, если они оба при стандартной работе выводят информацию на экран.



<== предыдущая лекция | следующая лекция ==>
Практикум | Практикум


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.017 сек.