All input and output work performed in the .NET Framework must use streams. A stream is an abstract representation of a serial device. Serialization devices can store data in a linear fashion and can be accessed in the same way: one byte at a time.
There are two types of streams:
- Output stream: When writing data to some external target, it is necessary to use the output stream. This can be a physical disk file, a network location, a printer, or another program.
- Input stream: used to read data into memory or variables accessible by the program. So far, the most common form of input stream we have used is the keyboard.
The related interfaces and classes of the stream are mainly located in theSystem.IO
namespace. Among them, theStream
class is an abstract class. It has three important subclasses for different access objects:FileStream
class represents file operations,MemoryStream
represents memory operations, andBufferedStream
class represents buffer processing.
1.Stream class
The abstract Stream
class contains many attributes and methods required in the stream, as shown in the following table:
These attributes and methods involve all aspects of the read and write of the stream. The 4 methods of read and write operations are as follows:
int ReadByte();
int Read(byte[] array, int offset, int count);
void WriteByte(byte value);
void Write(byte[] array, int offset, int count);
Among them ReadByte()
, the bytes read in are converted into integers and returned. If no bytes are read, then return -1
. Read()
The method returns the number of bytes read.
By BeginRead()
, EndRead()
, BeginWrite()
and EndWrie()
the like, Stream class can support asynchronous I / O operations.
Seek()
Method means to locate the search pointer in the stream to determine the position of the next read or write operation. In such a stream, its CanSeek
attribute value is true
, and its Seek()
method can be used to set the position of the pointer. Seek()
The method requires two parameters: one is used to indicate the value of the search pointer movement, and the other is used to determine the reference position of the pointer movement. The reference position is SeekOrigin
the enumeration member, which can be one of the following three situations:
- ①
SeekOrigin.Begin
(the beginning of the file); - ②
SeekOrigin.Current
(The current position of the pointer in the file); - ③
SeekOrigin.End
(End of file).
The following code shows how to search in a file:
aStream.Seek(200, SeekOrigin.Begin); // 从开头移到200位置
aStream.Seek(0, SeekOrigin.End); // 移到文件尾
aStream.Seek(-20, SeekOrigin.Current); // 从当前位置反向移动20
2.FileStream class
FileStream
It is Stream
directly derived from it. FileStream
Objects can read content from files, or write content to files, and can handle bytes, characters, strings, and other data types. This object can also be used to perform standard input/output and standard error output.
It should be noted that the FileStream
object is usually not used alone, because its application is closer to the bottom layer. This object can only read and write bytes, so when using it, you must convert strings, numbers, and objects into bytes before they can be passed to FileStream
it. In view of this, it FileStream
is usually packaged into some other classes for use, such as BinaryWriter
or TextReader
, these classes can handle high-level data structures. The FileStream class has many forms of construction methods, so different construction methods can be used according to different combinations of the following parameters FileStream
:
- ① File name;
- ② File handle-an integer used to represent the file handle;
- ③ Access mode-one of FileMode enumeration values;
- ④ Read/write permissions-one of FileAccess enumeration values;
- ⑤ Sharing mode-one of the FileShare enumeration values;
- ⑥ Buffer size.
Table 6-3, Table 6-4, and Table 6-5 respectively describe file access modes, access permissions, and sharing modes.
For example, to create a file and make the file support shared read operations:
FileStream fs = new FileStream(@"c:\temp\foo.txt", FileMode.Create, FileAccess.Reead);
FIleStream
It can be synchronous or asynchronous way to create, at the same time, apart from the Stream
addition of the inherited property, but also increase IsAsync
property. In addition, the method listed in the following table is added to this class: The
GetHandle()
method can return an ReadFile()
identifier that can be used in the native operating system function (such as in Win32 ), but this method must be used with caution. If you use the file handle to make some changes to the underlying file, and then try to use the file FileStream
, it may damage the data in the file.
FileStream
During the operation of the class, the following exceptions may be generated:
- ① ArgumentException——The path is a null character
- ② ArgumentNullException-the path is a null reference
- ③ SecurityException——No operation authority on the file
- ④ FileNotFoundException-file not found
- ⑤ IOException——Some other I/O errors have occurred, such as specifying a wrong driver
- ⑥ DirectoryNotFoundException——The directory does not exist
For example, through FileStream
to read and write the contents of the file:
using System;
using System.IO;
class Test
{
static void Main(){
try {
FileStream fsw = new FileStream("test.dat", FileMode.Create, FileAccess.Write);
// Wirte some data to the stream
fsw.WriteByte(33);
fsw.Write(new byte[] {
34, 35, 36 }, 0, 3);
fsw.Close();
FileStream fsr = new FileStream("test.dat", FileMode.Open, FileAccess.Read);
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
Console.WriteLine(fsr.ReadByte());
} catch (Exception e) {
Console.WriteLine("Exception:" + e.ToString());
}
}
}
operation result:
3.MemoryStream class
MemoryStream
From the class also Stream
inherited, it uses memory instead of the file to store the stream directly, but dealing with FileStream
very similar. MemoryStream
The data is stored in the memory in the form of a byte array, and can be used to replace the role of temporary files in the application.
As with the FileStream
same, MemoryStream
there are many construction methods. The following two are more commonly used:
MemoryStream();
MemoryStream(byte []);
Use the first construction method here to establish MemoryStream
that when data is written to the end of the stream, it MemoryStream
can be expanded accordingly. The second construction method creates a MemoryStream
new instance of the class based on the specified byte array , so that the created stream cannot be resized.
In addition to the Stream
inherited properties, an additional property MemoryStream
has been added Capacity
. Capacity
The attribute can be used to indicate the number of bytes currently allocated to the stream. This attribute is very useful when using byte array-based streams, because this attribute can tell the size of the array, and the Length
attribute can indicate the number of bytes currently being used.
MemoryStream
It is not possible to perform asynchronous read/write methods because this feature is not required for memory I/O. But the object can perform the following three additional methods.
- ①
GetBuffer()
——Returns a reference to the byte array in the stream - ② ——Write
ToArray()
all contents into the byte array - ③ ——Write
WriteTo()
the content of the stream to another Stream
For example, use MemoryStream to operate on memory:
using System;
using System.IO;
class Test
{
static void Main(){
try {
byte[] ary = {
33, 34, 35, 36, 37 };
int b;
MemoryStream msr = new MemoryStream(ary);
MemoryStream msw = new MemoryStream();
while ((b = msr.ReadByte()) != -1) {
msw.WriteByte((byte)(b + 3));
}
byte[] result = msw.ToArray();
foreach (byte bt in result)
Console.WriteLine(bt);
} catch (Exception e) {
Console.WriteLine("Exception:" + e.ToString());
}
}
}
operation result:
4.BufferedStrea类
BufferedStream
Can improve the execution efficiency of read and write operations, because this class can cache data in memory, thereby reducing the number of calls to the operating system. BufferedStream
It cannot be used alone, but should be packaged into some other types of streams, especially the types BinaryWriter
and BinaryReader
types described below . In addition, it is also common to cache and wrap the network stream (NetworkStream). For the BinaryStream
call Flush()
operation, the cached content can be written to the stream.