Работа с потоками ввода-вывода
Summary
There are network, memory, and tape streams. Class
Stream
unifies methods for working with various kinds of IO. This section describes main principles and techniques lying behind working with IO in .NET Framework.
A file is an ordered and named collection of a particular sequence of bytes having persistent storage. Therefore, with files, one thinks in terms of directory paths, disk storage, and file and directory names. In contrast, streams provide a way to write and read bytes to and from a backing store that can be one of several storage mediums. Just as there are several backing stores other than disks, there are several kinds of streams other than file streams.
Обзор классов, нужных для работы с потоками
The abstract base class
Stream
supports reading and writing bytes.
Stream
integrates asynchronous support. Its default implementations define synchronous reads and writes in terms of their corresponding asynchronous methods, and vice versa.
All classes that represent streams inherit from the
Stream
class. The
Stream
class and its derived classes provide a generic view of data sources and repositories, isolating the programmer from the specific details of the operating system and underlying devices.
Streams involve these fundamental operations:
- Streams can be read from. Reading is the transfer of data from a stream into a data structure, such as an array of bytes.
- Streams can be written to. Writing is the transfer of data from a data source into a stream.
- Streams can support seeking. Seeking is the querying and modifying of the current position within a stream.
Depending on the underlying data source or repository, streams might support only some of these capabilities. For example,
NetworkStreams
do not support seeking. The
CanRead
,
CanWrite
, and
CanSeek
properties of
Stream
and its derived classes determine the operations that various streams support.
Классы, используемые для ввода-вывода
FileObject
provides a representation of a text file. Use the
FileObject
class to perform most typical text file operations such as reading, writing, appending, copying, deleting, moving, or renaming. You can also use
FileObject
to examine and, in some cases, set file attributes, encoding, and path information.
Directory
provides static methods for creating, moving, and enumerating through directories and subdirectories. The
DirectoryInfo
class provides instance methods.
DirectoryInfo
provides instance methods for creating, moving, and enumerating through directories and subdirectories. The
Directory
class provides static methods.
File
provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of a
FileStream
. The
FileInfo
class provides instance methods.
FileInfo
provides instance methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of a
FileStream
. The
File
class provides static methods.
FileStream
supports random access to files through its
Seek
method.
FileStream
opens files synchronously by default, but supports asynchronous operation as well.
File
contains static methods, and
FileInfo
contains instance methods.
FileSystemInfo
is the abstract base class for
FileInfo
and
DirectoryInfo
.
Path
provides methods and properties for processing directory strings in a cross-platform manner.
File
,
FileInfo
,
Path
,
Directory
, and
DirectoryInfo
are sealed classes. You can create new instances of these classes, but they cannot have derived classes.
Классы, используемые для чтения/записи в потоки
BinaryReader
(
BinaryWriter
) reads (writes) encoded strings and primitive data types from (to) Streams.
StreamReader
(
StreamWriter
) reads (writes) characters from Streams, using
Encoding
to convert characters to (from) bytes.
StreamReader
(
StreamWriter
) has a constructor that attempts to ascertain what the correct
Encoding
for a given
Stream
is, based on the presence of an Encoding-specific preamble, such as a byte order mark.
StringReader
(
StringWriter
) reads (writes) characters from/to
Strings
. These classes allows you to treat
Strings
with the same API, so your output (input) can be either a
Stream
in any encoding or a
String
.
TextReader
(
TextWriter
) is the abstract base classes for
StreamReader
and
StringReader
(
StreamWriter
and
StringWriter
). While the implementations of the abstract
Stream
class are designed for byte input and output, the implementations of
TextReader=(=TextWriter
) are designed for Unicode character output.
Общие классы потоков ввода-вывода
A
BufferedStream
is a
Stream
that adds buffering to another
Stream
such as a
NetworkStream
. (
FileStream
already has buffering internally, and a
MemoryStream
does not need buffering.) A
BufferedStream
can be composed around some types of streams in order to improve read and write performance. A buffer is a block of bytes in memory used to cache data, thereby reducing the number of calls to the operating system.
A
CryptoStream
links data streams to cryptographic transformations. Although
CryptoStream
derives from
Stream
, it is not part of the
System.IO namespace
, but is in the
System.Security.Cryptography
namespace.
A
MemoryStream
is a nonbuffered stream whose encapsulated data is directly accessible in memory. This stream has no backing store and might be useful as a temporary buffer.
A
NetworkStream
represents a
Stream
over a network connection. Although
NetworkStream
derives from
Stream
, it is not part of the
System.IO
namespace, but is in the
System.Net.Sockets
namespace.
Примеры работы с файлами/директориями
Запись/чтение текстового файла
using System;
using System.IO;
class MyStream
{
private const string FILE_NAME = "Test.data";
public static void Main(String[] args)
{
// Create the new, empty data file.
if (File.Exists(FILE_NAME))
{
Console.WriteLine("{0} already exists!", FILE_NAME);
return;
}
FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);
// Create the writer for data.
BinaryWriter w = new BinaryWriter(fs);
// Write data to Test.data.
for (int i = 0; i < 11; i++)
{
w.Write( (int) i);
}
w.Close();
fs.Close();
// Create the reader for data.
fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// Read data from Test.data.
for (int i = 0; i < 11; i++)
{
Console.WriteLine(r.ReadInt32());
}
w.Close();
}
}
Добавление сообщений в лог-файл
using System;
using System.IO;
class DirAppend
{
public static void Main(String[] args)
{
StreamWriter w = File.AppendText("log.txt");
Log ("Test1", w);
Log ("Test2", w);
// Close the writer and underlying file.
w.Close();
// Open and read the file.
StreamReader r = File.OpenText("log.txt");
DumpLog (r);
}
public static void Log (String logMessage, TextWriter w)
{
w.Write("\r\nLog Entry : ");
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine ("-------------------------------");
// Update the underlying file.
w.Flush();
}
public static void DumpLog (StreamReader r)
{
// While not at the end of the file, read and write lines.
String line;
while ((line=r.ReadLine())!=null)
{
Console.WriteLine(line);
}
r.Close();
}
}
Листинг директории
using System;
using System.IO;
class DirectoryLister
{
public static void Main(String[] args)
{
DirectoryInfo dir = new DirectoryInfo(".");
foreach (FileInfo f in dir.GetFiles("*.cs"))
{
String name = f.FullName;
long size = f.Length;
DateTime creationTime = f.CreationTime;
Console.WriteLine("{0,-12:N0} {1,-20:g} {2}", size,
creationTime, name);
}
}
}
Чтение символов из строки
using System;
using System.IO;
public class CharsFromStr
{
public static void Main(String[] args)
{
// Create a string to read characters from.
String str = "Some number of characters";
// Size the array to hold all the characters of the string
// so that they are all accessible.
char[] b = new char[24];
// Create an instance of StringReader and attach it to the string.
StringReader sr = new StringReader(str);
// Read 13 characters from the array that holds the string, starting
// from the first array member.
sr.Read(b, 0, 13);
// Display the output.
Console.WriteLine(b);
// Close the StringReader.
sr.Close();
}
}
Копирование/перемещение файла
Для копирования файла можно использовать статический метод
File.Copy
. Для перемещения используется метод
File.Move
. Оба метода не работают при необходимости пересекать границу раздела тома.
Асинхронные операции ввода-вывода
Synchronous I/O means that the method is blocked until the I/O operation is complete, and then the method returns its data. With asynchronous I/O, a user can call
BeginRead
or
BeginWrite
. The main thread can continue doing other work, and later the user will be able to process the data. Also, multiple I/O requests can be pending simultaneously.
To be informed when this data is available, you can call
EndRead
or
EndWrite
, passing in the
IAsyncResult
corresponding to the I/O request you issued. You can also provide a callback method that should call
EndRead
or
EndWrite
to figure out how many bytes were read or written. Asynchronous I/O can offer better performance when many I/O requests are pending simultaneously, but generally requires some significant restructuring of your application to work correctly.
See also:
Links
--
AndreyUstyuzhanin - 07 Apr 2004