Делегаты, события и потоки выполнения. Работа с файлами
Использование делегатов в качестве методов обратного вызова. Определение делегатов в качестве статических членов. Определение событий с помощью делегатов. Основные операции над файлами: создание, удаление, запись и чтение файла. Составные делегаты.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | лекция |
Язык | русский |
Дата добавления | 29.07.2012 |
Размер файла | 23,7 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Лекция 38-39. Делегаты, события и потоки выполнения. Работа с файлами
Использование делегатов в качестве методов обратного вызова
Определение делегатов в качестве статических членов
Создавать делегаты только при необходимости
Составные делегаты
Определение событий с помощью делегатов
Работа с файлами
Одно из полезных нововведений в С# -- делегаты (delegates). Их назначение по сути совпадает с указателями функций в C++, но делегаты являются управляемыми объектами и привязаны к типам. Это значит, что исполняющая среда (runtime) гарантирует, что делегат указывает на допустимый объект, а это в свою очередь означает получение всех достоинств указателей функций без связанных с этим опасностей, таких как применение недопустимых адресов или разрушение памяти других объектов. В этой главе мы рассмотрим делегаты в сравнении с интерфейсами, их синтаксис и проблемы их применения. Мы также увидим несколько примеров использования делегатов с функциями обратного вызова и асинхронными обработчиками событий.
Из главы 9 мы узнали как определяются и реализуются интерфейсы. Как вы знаете, с концептуальной точки зрения интерфейсы -- это связки между двумя различными частями кода. Но при этом интерфейсы во многом напоминают классы, так как объявляются в период компиляции и могут включать методы, свойства, индексаторы и события. Что касается делегата, то он ссылается на единственный метод и определяется в период выполнения. В С# две основных области применения делегатов: методы обратного вызова и обработчики событий.
Использование делегатов в качестве методов обратного вызова
Методы обратного вызова повсеместно используются в Windows для передачи указателя функции другой функции, чтобы последняя могла вызвать первую (через переданный ей указатель). Так, функция Win32 API
EnumWindows перечисляет все окна верхнего уровня на экране и для каждого окна вызывает переданную ей функцию. Обратные вызовы применяют по-разному, но наиболее распространены два случая.
Асинхронная обработка Методы обратного вызова используют при асинхронной обработке, когда вызванному коду требуется существенное время для обработки запроса. Обычно сценарий таков. Клиентский код вызывает метод, передавая ему метод обратного вызова. Вызванный метод начинает работу в своем потоке и сразу возвращает управление. Запущенный поток затем выполняет основную работу, при необходимости обращаясь к функции обратного вызова. Очевидное достоинство такого подхода в том, что клиент продолжает работу, не блокируясь на потенциально длительное время, которое требуется для синхронного вызова.
Введение дополнительного кода в код класса Другой распространенный способ применения методов обратного вызова имеет место, когда класс позволяет клиенту указать метод для дополнительной нестандартной обработки. Например, в классе Windows Listbox можно указать нисходящий или восходящий порядок сортировки элементов. Кроме еще некоторых базовых возможностей для сортировки, этот класс на самом деле не дает полной свободы действий и остается общим классом. Но при этом Listbox позволяет указывать для сортировки функцию обратного вызова. Таким образом, Listbox для сортировки вызывает функцию обратного вызова, и ваш код может выполнять нужные нестандартные действия.
Рассмотрим пример определения и применения делегата. В этом примере у нас есть класс менеджера базы данных, который отслеживает все активные соединения с БД и предоставляет метод перечисления этих соединений. Если допустить, что менеджер БД находится на удаленной машине, правильным решением будет сделать метод асинхронным, позволив клиенту предоставлять метод обратного вызова. Заметьте: в реальном приложении вам следовало бы задействовать многопоточность, чтобы добиться подлинной асинхронности. Но для упрощения примера и поскольку мы не рассматривали многопоточность, пока не будем ее применять.
Для начала определим два главных класса: DBManager n DBConnection.
class DBConnection <
}
class DBManager { static DBConnection[] activeConnections;
public delegate void EnumConnectionsCallback(DBConnection
connection); public static void EnumConnections(EnumConnectionsCallback
callback) {
foreach (DBConnection connection in activeConnections)
{
callback(connection);
} } }
Метод EnumConnectionsCallback является делегатом, что определяется ключевым словом delegate в начале сигнатуры метода. Как видите, этот делегат возвращает void и принимает единственный аргумент -- объект DBConnection. Метод EnumConnections в соответствии с его определением принимает единственный аргумент -- метод EnumConnectionsCallback. Чтобы вызвать метод DBManager.EnumConnections нам нужно лишь передать ему экземпляр делегата DBManager.EnumConnectionCallback.
Для создания экземпляра делегата нужно применить new, передав ему имя метода, имеющего ту же сигнатуру, что и у делегата. Вот пример:
DBManager.EnumConnectionsCallback myCallback =
new DBManager.EnumConnectionsCallback(ActiveConnectionsCallback);
DjlManager.EnumConnections(myCallback);
Заметьте, что это можно скомбинировать в единый вызов:
DBManager.EnumConnections(new
DBManager.EnumConnectionsCallback(ActiveConnectionsCallback));
Вот и все, что касается базового синтаксиса делегатов. Теперь посмотрим на законченный пример:
using System;
class DBConnection {
public DBConnection(string name) {
this.name = name; }
protected string Name; public string name {
get {
return this.Маше; }
set {
this.Name = value; > } }
class DBManager {
static DBConnection[] activeConnections;
public void AddConnectionsO
{
activeConnections = new DBConnection[5];
for (int i = 0; i < 5; i++)
{
activeConnections[i] = new DBConnection("DBConnection " + (i + 1)); > }
public delegate void EnumConnectionsCallback(DBConnection
connection); public static void EnumConnections(EnumConnectionsCallback
callback) {
foreach (DBConnection connection in activeConnections)
{
callback(connection);
} } }
class DelegatelApp {
public static void ActiveConnectionsCallback(DBConnection
connection) {
Console.WriteLine("Callback method called for "
+ connection.name); }
public static void Main() {
DBManager dbMgr = new DBManagerO; dbMg r.AddConnections();
DBManager.EnumConnectionsCallback myCallback =
new DBManager.EnumConnectionsCallback (ActiveConnectionsCallback);
DBManager.EnumConnections(myCallback); } }
После компиляции и запуска этого приложения мы получим такие результаты:
Callback method called for DBConnection 1
Callback method called for DBConnection 2
Callback method called for DBConnection 3
Callback method called for DBConnection 4
Callback method called for DBConnection 5
Определение делегатов в качестве статических членов
Довольно неуклюжее решение создавать экземпляр делегата при каждом его применении, но в С# можно определять метод, который используется при создании делегата как статический член класса. Ниже приведен предыдущий пример с применением такого подхода. Заметьте, что теперь делегат определен как статический член класса myCallback и этот член может использоваться в методе Main, так что клиенту нет нужды создавать экземпляр делегата.
using System;
class DBConnection {
public DBConnection(string name)
{
this.name = name;
}
protected string Name; public string name {
get {
return this.Name; }
set {
this.Name = value; } } }
class DBManager {
static DBConnection[] activeConnections;
public void AddConnectionsO
{
activeConnections = new DBConnection[5];
for (int i = 0; i < 5; i++)
{
activeConnections[i] = new DBConnection("DBConnection " + (i + 1))-} }
public delegate void EnumConnectionsCallback(DBConnection connection);
public static void EnumConnections(EnumConnectionsCallback
callback) {
foreach (DBConnection connection in activeConnections)
callback(connection); } } }
class Delegate2App {
public static DBManager.EnumConnectionsCallback
myCallback = new DBManager.EnumConnectionsCallback (ActiveConnectionsCallback);
public static void ActiveConnectionsCallback(DBConnection
connection) {
Console.WriteLine ("Callback method called for " +
connection.name); }
public static void Main() {
DBManager dbMgr = new DBManager();
dbMgr. AddConnectionsO;
DBManager. EnurnConnections(myCallback); } }
ПРИМЕЧАНИЕ
Поскольку общим правилом именования делегатов является добавление слова Callback к имени метода, принимающего делегат в качестве аргумента, можно по ошибке использовать имя этого метода вместо имени делегата. При этом компилятор уведомит, что вы указали метод там, где ожидается класс. Получив такую ошибку, помните: проблема в том, что вы указали метод вместо делегата.
Создавайте делегаты только при необходимости
В двух примерах, которые мы рассмотрели, делегаты создаются независимо от того, будут ли они когда-либо использоваться. В рассмотренных примерах ничего плохого в этом нет, поскольку известно, что они будут вызываться. Но в целом при определении делегатов важно решить, когда их создавать. Скажем, может случиться, что создание делегатов потребует немалого времени и затрат. В таких случаях, когда вы знаете, что клиент обычно не обращается к данному методу обратного вызова, можно отложить создание делегата до момента, когда он действительно потребуется, заключив создание его экземпляра в оболочку свойства. Это иллюстрирует следующий измененный класс DBManager, в котором для создания экземпляра делегата используется неизменяемое свойство (поскольку для него представлен только метод-получатель), using System;
class DBConnection {
public DBConnection(string name)
{
this.name = name;
}
protected string Name; public string name {
get {
return this.Name; }
set {
this.Name = value; } } }
class DBManager {
static DBConnection[] activeConnections;
public void AddConnections()
{
activeConnections = new DBConnection[5];
for (int i = 0; i < 5; i++)
{
activeConnections[i] = new
DBConnection("DBConnection " + (i + 1)); }
}
public delegate void EnumConnectionsCallback(DBConnection
connection); public static void EnumConnections(EnumConnectionsCallback
callback) {
foreach (DBConnection connection in activeConnections)
{
callback(connection); } } }
class DelegateSApp {
public DBManager.EnumConnectionsCallback myCallback
{
get
{
return new DBManager.EnumConnectionsCallback (ActiveConnectionsCallback); } }
public static void ActiveConnectionsCallback(DBConnection
connection) {
Console.WriteLine
("Callback method called for " + connection.name); }
Bublic static void Main() {
DelegateSApp app = new Delegate3App();
DBManager dbMgr = new DBManagerO; dbMgr.AddConnections();
DBManager.EnumConnections(app. myCallback); }
}
делегат событие файл
Составные делегаты
Объединение делегатов -- создание одного делегата из нескольких -- одна из тех возможностей, которая поначалу не кажется такой уж полезной, но если вы столкнетесь с такой потребностью, то будете признательны команде разработчиков С# за то, что они это предусмотрели. Разберем некоторые примеры, когда может быть полезно объединение делегатов. В первом примере мы имеем дистрибьюторскую систему и класс, просматривающий все наименования товара на данном складе, вызывая метод обратного вызова для каждого наименования, запасов которого менее 50 единиц. В реальном дистрибьюторском приложении формула должна учитывать не только наличные запасы, но также заказанные и находящиеся "в пути". Но возьмем простой пример: если наличие на складе менее 50 единиц, возникает исключение.
Фокус в том, что мы хотим разделить методы, которые вызываются, если запасы ниже допустимых: нам нужно запротоколировать сам факт и, кроме того, послать письмо по электронной почте менеджеру по закупкам. Итак, составим делегат из нескольких других:
using System;
using System.Threading;
class Part {
public Part(string sku)
{
this.Sku = sku;
Random r = new Random(DateTime.Now.Millisecond);
double d = r.NextDoubleO * 100;
this.OnHand = (int)d; }
protected string Sku; public string sku {
get
{
return this.Sku;
}
set
{
this.Sku = value;
} }
protected int OnHand; public int onhand
{
get
{
return this.OnHand;
}
set
{
this.OnHand = value;
} } }
class InventoryManager
{
protected const int MIN_ONHAND = 50;
public Part[] parts; public InventoryManagerO
{
parts = new Part[5];
for (int 1=0; i < 5; i++)
{
Part part = new Part("Part " + (i + 1));
} Thread.Sleep(10); // Генератор случайных чисел,
// установленный по времени.
partsti] = part;
Console,WriteLine("Adding part '{0}' on-hand = {1}", part.sku, part.onhand);
} }
public delegate void OutOfStockExceptionMethod(Part part);
public void ProcessInventory(OutOfStockExceptionMethod exception)
{
Console.WriteLine("\nProcessing inventory...");
foreach (Part part in parts)
{
if (part.onhand < MIN_ONHAND) {
Console.WriteLine
("{0} ({1}) is below minimum on-hand {2}", part.sku, part.onhand, MIN_ONHAND);
exception(part); > } } }
class ComposlteDelegatelApp {
public static void LogEvent(Part part)
{
Console.WriteLine("\tlogging event...");
}
public static void EmailPurchasingMgr(Part part) {
Console.WriteLine("\teraailing Purchasing manager..."); }
public static void Main() {
InventoryManager mgr = new InventoryManager();
InventoryManager.OutOfStockExceptionMethod LogEventCallback =
new InventoryManager.OutOfStockExceptionMethod(LogEvent);
Invento ryManage r.OutOfStockExceptionMethod EmailPurchasingNgrCallback =
new InventoryManager.OutOfStockExceptionMethod (EmailPurchasingMgr);
InventoryManager.OutOfStockExceptionMethod OnHandExceptionEventsCallback =
EmailPurchasingMgrCallback + LogEventCallback;
mgr.ProcessInventory(OnHandExceptionEventsCallback); } }
В результате выполнения мы увидим результат вроде этого:
Adding part 'Part V on-hand = 16
Adding part 'Part 2' on-hand = 98
Adding part 'Part 3' on-hand = 65
Adding part 'Part 4' on-hand = 22
Adding part 'Part 5' on-hand = 70
Processing inventory...
Part 1 (16) is below minimum on-hand 50
logging event...
entailing Purchasing manager... Part 4 (22) is below minimum on-hand 50
logging event...
emailing Purchasing manager...
Таким образом, эта возможность языка позволяет динамически определять, какие методы нужно включать в метод обратного вызова, и объединять их в составной делегат. Исполняющая среда распознает, что эти методы нужно вызвать последовательно. Кроме того, вы можете убрать любой делегат из составного оператором "минус".
Тот факт, что эти методы вызываются последовательно, заставляет спросить: почему просто не связать методы в цепочку, чтобы каждый метод вызывал последующий? В нашем примере, где у нас всего два метода и вызываются они всегда оба, это сделать можно. Но усложним при-- мер. Допустим, у нас несколько магазинов, расположенных в разных местах, и каждый сам решает какие методы вызывать. К примеру, на территории одного магазина находится общий товарный склад, и здесь нужно запротоколировать событие и сообщить менеджеру о закупках, а в других магазинах -- запротоколировать событие и сообщить управляющему магазина.
Такое требование легко реализовать, динамически создавая составной делегат на основе информации о конкретном местоположении магазина. Без делегатов нам пришлось бы написать метод, который не только определял бы, какие методы вызывать, но и отслеживал, какие методы уже вызывались, а какие еще нужно вызвать. Смотрите, как делегаты упрощают эту потенциально сложную операцию.
using System;
class Part {
public Part(string sku)
{
this.Sku = sku;
Random г = new Random(DateTime.Now.Millisecond);
double d = r.NextDoubleO * 100;
this.OnHand = (int)d; }
protected string Sku; public string sku {
get
{
return this.Sku;
}
set
{
this.Sku = value;
} }
protected int OnHand; public int onhand {
get {
return this.OnHand; }
set {
this.OnHand = value; } } }
class InventoryManager {
protected const int MIN_ONHAND = 50;
public Part[] parts; public InventoryManagerO {
parts = new Part[5];
for (int i = 0; i < 5; i++)
{
Part part = new Part("Part " + (i + 1)); parts[i] = part; Console.WriteLine
("Adding part '{0}' on-hand = {1}", part.sku, part.onhand); } }
public delegate void OutOfStockExceptionMethod(Part part);
public void ProcessInventory(OutOfStockExceptionMethod exception) {
Console.WriteLine("\nProcessing inventory...");
foreach (Part part in parts)
{
if (part.onhand < MIN_ONHAND) {
Console.WriteLine
("{0} ({1" is below minimum onhand {2}", part.sku, part.onhand, MIN_ONHANO);
exception(part); } } } }
class CompositeDelegate2App {
public static void LogEvent(Part part)
{
Console.WriteLine("\tlogging event...");
}
public static void EmailPurchasingMgr(Part part)
{
Console.WriteLine("\temailing Purchasing manager..,"); }
public static void EmailStoreMgr(Part part) {
Console.WriteLine("\temailing store manager..."); }
public static void Main() {
InventoryManager mgr = new InventoryManagerO;
InventoryManager.OutOfStockExceptionMethod[]
exceptionMethods = new
InventoryManager.OutOfStockExceptionMethod[3]; exceptionMethods[0] = new
InventoryManager.OutOfStockExceptionMethod
(LogEvent); exceptionMethods[1] = new
InventoryManager.OutOfStockExceptionMethod
(EmailPurchasingMgr); exceptionMethods[2] = new
InventoryManager.OutOfStockExceptionMethod (EmailStoreMgr);
int location = 1;
InventoryManager.OutOfStockExceptionMethod compositeDelegate;
if (location == 2) {
compositeDelegate =
exceptionMethods[0] + exceptionMethods[1]; }
else {
compositeDelegate =
exceptionMethods[0] + exceptionMethods[2]; }
mgr.ProcessInventory(compositeDelegate); } }
Теперь при компиляции и выполнении этого приложения результаты будут отличаться в зависимости от значения переменной location.
Определение событий с помощью делегатов
Практически во всех Windows-приложениях требуется асинхронная обработка событий. Некоторые из этих событий связаны с самой ОС, например, когда Windows посылает сообщения в очередь сообщений при- \ ложения при том или ином взаимодействии пользователя с приложени-I ем. Другие больше связаны с предметной областью, например, когда \ нужно распечатать счет при обновлении заказа.
Работа с событиями в С# соответствует модели "издатель -- подписчик", где класс публикует событие, которое он может инициировать, и любые классы могут подписаться на это событие. При инициации события исполняющая среда следит за тем, чтобы уведомить всех подписчиков о возникновении события.
Метод, вызываемый при возникновении события, определяется делегатом. Однако нужно помнить об ограничениях, которые налагаются на делегаты, используемые для этих целей. Во-первых, нужно чтобы такой делегат принимал два аргумента. Во-вторых, эти аргументы всегда должны представлять два объекта: тот, что инициировал событие (издатель), и информационный объект события, который должен быть производным от класса EventArgs .NET Framework.
Скажем, мы хотим отслеживать изменения объемов запасов. Мы создаем класс InventoryManager, который будет всегда использоваться при обновлении запасов. Этот класс должен публиковать события, возника-, ющие при всяком изменении запасов вследствие закупок, продаж и других причин. Тогда любой класс, которому нужно отслеживать изменения, должен подписаться на эти события. Вот как это делается на С# при помощи делегатов и событий:
using System;
class InventoryChangeEventArgs : EventArgs
{
public InventoryChangeЈventArgs(string sku, int change)
{
this.sku = sku;
this.change = change; }
string sku; public string Sku {
get
{
return sku;
} }
int change; public int Change {
get {
return change; } } }
class InventoryManager // Издатель. {
public delegate void InventoryChangeEventHandler (object source, InventoryChangeEventArgs e);
public event InventoryChangeEventHandler OnlnventoryChangeHandler;
public void Updatelnventory(string sku, int change) {
if (0 == change)
return; // Ничего обновлять не нужно.
// Здесь должен быть код для обновления БД.
InventoryChangeEventArgs e = new
InventoryChangeEventArgs(sku, change);
if (OnlnventoryChangeHandler != null) OnInventoryChangeHandler(this, e); } }
class InventoryWatcher // Подписчик.
{
public InventoryWatcher(InventoryManager inventoryManager) {
this.inventoryManager = inventoryManager;
inventoryManager.OnlnventoryChangeHandler += new
InventoryManager.InventoryChangeEventHandler
(Onlnvento ryChange); } void OnInventoryChange(object source, InventoryChangeEventArgs e)
}
\ int change = e.Change;
\ Console.WriteLineC'Part '{0}' was {1} by {2} units", \ e.Sku,
change : 0 ? "increased" ; "decreased",
Math.Abs(e.Change));
}
InventoryManager inventoryManager;
}
class EventslApp {
public static void Main() {
InventoryManager inventoryManager = new InventoryManager();
InventoryWatcher inventoryWatch =
new InventoryWatcher(inventoryManager);
inventoryManager.Updatelnventory("111 006 116", -2);
inventoryManager.Updatelnventory("111 005 383", 5); } }
Рассмотрим первые два члена класса InventoryManager:
public delegate void InventoryChangeEventHandler
(object source, InventoryChangeEventArgs e);
public event InventoryChangeEventHandler OnlnventoryChangeHandler;
Первая строка кода -- это делегат, вы можете узнать его по определению сигнатуры метода. Как я говорил, все делегаты, используемые с событиями, должны быть определены с двумя аргументами: объект-издатель (в данном случае source) и информационный объект события (производный от EventArgs объект). Во второй строке указано ключевое слово event, член, имеющий тип указанного делегата, и метод (или методы), которые будут вызываться при возникновении события.
Update Inventory, -- последний метод класса Inventory Manager -- вызывается при каждом изменении запасов. Как видите, он создает объект типа InventoryChangeEventArgs, который передается всем подписчикам и описывает возникшее событие.
Теперь рассмотрим еще две строки кода:
if (OnlnventoryChangeHandler != null)
OnInventoryChangeHandler(this, e); I
Условный оператор // проверяет, есть ли подписчики, связанные с / методом OnlnventoryChangeHandler. Если это так, т. e. OnlnventoryChangeHandler не равен null, инициируется событие. Вот и все, что касается издателя. Теперь рассмотрим код подписчика.
Подписчик в нашем случае представлен классом Inventory Watcher. Ему нужно выполнять две простые задачи. Во-первых, он должен указать себя как подписчик, создав новый экземпляр делегата типа Inventory-Manager. InventoryChange Event Handler и добавив этот делегат к событию InventoryManager.OnlnventoryChangeHandler. Обратите особое внимание на синтаксис: чтобы добавить себя к списку подписчиков, он использует составной оператор присваивания +=, чтобы не уничтожить предыдущие подписчики.
inventoryManager.OnlnventoryChangeHandler +=
new InventoryManager.InventoryChangeEventHandler (OnlnventoryChange);
Единственный аргумент, указываемый здесь, -- имя метода, вызываемого при возникновении события.
Последняя задача, которую должен выполнить подписчик, -- это реализовать свой обработчик событий. В данном случае обработчик ошибок -- InventoryWatcher.OnlnventoryChange -- выводит сообщение об изменении запасов с указанием номера позиции.
И, наконец, в коде этого приложения при каждом вызове метода InventoryManager. Update Inventory создаются экземпляры классов Inventory-Manager и Inventory Watcher т автоматически инициируется событие, которое приводит к вызову метода InventoryWatcher.OnlnventoryChanged.
События. События играют важную роль в программировании Windows GUI. Идея состоит в том, что часто требуется информировать некоторый код о том, что произошли те или иные события. Например, при наборе текста в Microsoft Word каждый раз, когда нажимается клавиша, Word должен быть информирован об этом, чтобы он смог выполнить соответствующее действие. (Обычно это означает добавление соответствующей буквы в документ и отображение ее на экране.) Каждый раз при нажатии на клавишу Windows вызывает конкретный метод внутри Word, который осуществляет соответствующее действие, т.е. обрабатывает событие. Для того чтобы Windows могла сделать это, Word в некоторый момент должен сообщить Windows о том, какой метод необходимо вызвать в ответ на нажатие клавиши. Поэтому Word должен вызвать функцию API и передать ей подробности об этом методе. В очередной раз мы видим, что сведения о методе должны быть переданы в качестве параметра. Очевидно, что, программируя на С#, мы будем иметь дело со средой исполнения .NET, а не с Windows, но когда мы приступим к программированию GUI с помощью Windows Forms, то используем те же самые принципы: код должен будет сообщать среде исполнения .NET о том, какие методы обрабатывают какие события. Чтобы сделать это, необходимо будет передавать подробную информацию о методах в качестве параметров другим методам.
Подведем итоги
Делегаты -- привязанные к типу управляемые объекты -- играют в С# ту же роль, что и указатели функций в C++. Отличие делегатов от классов и интерфейсов в том, что они ссылаются на один метод и определяются в период выполнения. Делегаты широко применяются для асинхронной обработки и добавления нестандартного кода к коду классов. Делегаты могут использоваться для многих целей, включая методы обратного вызова, определение статических методов и обработку событий.
Работа с файлами
Будут рассмотрены основные операции над файлами.
Примечание. Все необходимые классы находятся в пространстве имен System.IO.
Создание файла
Для этого воспользуемся классом FileInfo из пространства имен System.IO. В конструктор передаем имя будущего файла. Создание файла производится вызовом метода Create().
FileInfo fi = new FileInfo("new.txt");
fi.Create();
Удаление файла
Все аналогично предыдущему примеру. Для удаления файла используем метод Delete().
FileInfo fi = new FileInfo("new.txt");
fi.Delete();
Запись в файл
Для записи (а в последующем и для чтения) в файл мы будем использовать символьные потоки позволяющие оперировать непосредственно с символами Unicode.
StreamWriter sw = new StreamWriter("name.txt");
sw.WriteLine("блаблабла");
sw.Close();
После всех действий над файлом не забываем закрывать его используя метод Close(), в противном случае изменения в файле не только не будут сохранены. Приведеный выше пример записи файла полностью перезаписывает его, если же надо дописать в конец файла:
StreamWriter sw;
FileInfo fi = new FileInfo("name.txt");
sw = fi.AppendText();
sw.WriteLine("blablabla");
sw.Close();
Чтение из файла
Для того чтобы файл был корректно считан (без всяких непонятных символов), он должен быть сохранен в юникоде.
StreamReader streamReader = new StreamReader("name.txt");
string str = "";
while (!streamReader.EndOfStream)
{
str += streamReader.ReadLine();
}
Ещё один вариант, для разнообразия
StreamReader streamReader = new StreamReader("name.txt");
string str = "", str_temp="";
while ((str_temp = streamReader.ReadLine()) != null)
{
str += str_temp;
}
1. Размещено на www.allbest.ru
Подобные документы
Описание типизированных файлов. Принципы работы с файлами, создание и открытие на запись нового файла. Чтение из файла, открытие существующего файла на чтение. Определение имени файла. Запись в текстовый файл. Описание множества и операции над ними.
реферат [86,4 K], добавлен 07.02.2011Рассмотрение основных типов данных: значений и ссылок. Отражение объектно-ориентированной методологии одиночного наследования IL в иерархической структуре общей системы типов. Виды интрефейсов и делегатов. Встроенные типы данных в спецификации CTS.
курсовая работа [99,0 K], добавлен 09.08.2015Проверка существования и статуса файла. Определение его размера. Открытие файла для чтения, записи, добавления. Закрытие файловых дескрипторов. Запись из переменной в файл. Загрузка файла из сети. Создание и удаление каталога. Функции работы с каталогами.
презентация [133,9 K], добавлен 21.06.2014Изучение сущности и основных задач файловой системы. Принципы работы с папками и файлами. Комплекс системных программных средств, реализующих управление файлами: создание, уничтожение, чтение, запись, именование, поиск и другие операции над файлами.
курсовая работа [309,6 K], добавлен 11.11.2013Работа с файлами, папками WINDOWS: понятие файла, папки, сохранение, переименование. Вычисление суммы порядковых номеров фамилии и имени. Алгоритм расчета себестоимости. реализация в других программах алгоритма и отчета по нему. Файлы, папки WINDOWS.
контрольная работа [17,9 K], добавлен 05.06.2008Использование программы "Total Commander": пользовательский интерфейс, клавиатурные сочетания, операции с файлами, контекстные меню, внутренний просмотр файлов. Назначение и применение функциональных клавиш. Особенности работы с каталогами и файлами.
презентация [462,3 K], добавлен 25.09.2014Работа с элементом управления в VB.net. Работа с файлами, организация последовательного доступа с помощью объектов Streareader и Streamwriter. Последовательный доступ с помощью класса File, программирование задач с использованием циклов с параметром.
лабораторная работа [644,8 K], добавлен 27.12.2013Схема речеобразования у человека. Запись и считывание данных из речевого сигнала в MATLAB. Синтаксис вызова функции. Операции над звуковыми файлами. Исследование мужского и женского голосов. Спектрограммы голосов. Обработка речи в Simulink, Wavelet.
контрольная работа [2,2 M], добавлен 18.04.2013Основные функции Norton Commander и их реализация при работе с каталогами и файлами. Управление дисковой и файловой структурами персонального компьютера. Создание каталога, переход между каталогами, удаление каталога, создание текстового файла.
контрольная работа [20,6 K], добавлен 09.03.2011Теоретическое изучение и практическое применение приёмов работы с файлами в операционной системе Windows 95. Файлы и папки: основные понятия и правила формирования имен файлов в Windows. Характеристика и анализ особенностей операций с файлами и папками.
контрольная работа [139,9 K], добавлен 09.03.2011