C # Learn from the story: Stream (-)
Directory:
What is Stream?
What is a byte sequence?
Stream Constructor
Important attributes and methods of Stream
Stream example
Stream asynchronous read/write
Class Diagram of Stream and its subclass
Summary
What is Stream?
The explanation in MSDN is too concise: provides a general view of the byte sequence
(I don't want to understand it that way. This will make me crazy. The stream I understand is as clear and beautiful as the rivers in nature, and the stream in c # is the same, many technologies or core technologies require streaming help)
What is a byte sequence?
In fact, in simple terms, the byte sequence refers:
Byte objects are stored as consecutive byte sequences, which are sorted in certain order to form a byte sequence.
The stream interpretation can be abstracted into the following situations:
For example, if a river contains a fish swim, the fish is a byte. The Byte includes the eyes, mouth, and so on of the fish to form eight binary values, obviously, this river is our core object: Stream
Right now, let's explain how c # Stream is used.
Let's learn the structure, attributes, and related methods of the Stream class.
First, constructor
The Stream class has a protected Type constructor, but it is an abstract class and cannot be directly used as follows:
Stream stream = new Stream ();
So we can customize a Stream to inherit from the Stream to see which attributes must be overwritten or customized:
View Code
Public class MyStreamExample: Stream
{
Public override bool CanRead
{
Get {throw new NotImplementedException ();}
}
Public override bool CanSeek
{
Get {throw new NotImplementedException ();}
}
Public override bool CanWrite
{
Get {throw new NotImplementedException ();}
}
Public override void Flush ()
{
Throw new NotImplementedException ();
}
Public override long Length
{
Get {throw new NotImplementedException ();}
}
Public override long Position
{
Get
{
Throw new NotImplementedException ();
}
Set
{
Throw new NotImplementedException ();
}
}
Public override int Read (byte [] buffer, int offset, int count)
{
Throw new NotImplementedException ();
}
Public override long Seek (long offset, SeekOrigin origin)
{
Throw new NotImplementedException ();
}
Public override void SetLength (long value)
{
Throw new NotImplementedException ();
}
Public override void Write (byte [] buffer, int offset, int count)
{
Throw new NotImplementedException ();
}
}
We can see that the system automatically implements the abstract attributes and attribute methods of Stream.
1: CanRead: Read-only attribute to determine whether the stream can be read:
2: CanSeek: Read-only attribute to determine whether the stream supports tracking and searching
3: CanWrite: Read-only attribute to determine whether the current stream can be written
* 4: void Flush (): This must be carefully stated:
When we use a stream to write a file, the data stream first enters the buffer zone, instead of writing the file immediately. After this method is executed, the data stream in the buffer zone is immediately injected into the basic stream.
Description in MSDN: use this method to move all information from the base buffer to its target or clear the buffer, or simultaneously perform these two operations. You may need to repair the object based on its status.
Change the current position in the Stream (for example, when the basic Stream supports searching). When using the StreamWriter or BinaryWriter class, do not refresh the Stream base object.
Instead, use the Flush or Close method of this class. This method ensures that the data is first refreshed to the basic stream and then written to the file.
(The red part is the key. please be sure to understand it. We will introduce it in the relevant sections in the future)
5: Length: indicates the stream Length.
* 6: Position attribute: (very important)
Although it can be seen from the literal that this Position attribute only indicates a Position in the stream, we will find this idea very naive in actual development,
In many asp.net projects, uploading files or images may experience the following pain: The Stream object is cached, causing the Position attribute to be unavailable in the Stream.
Finding the correct Position will make people crazy. In fact, it is very easy to solve this problem. You must think of it smartly. In fact, we must set Stream. Position before every use of Stream.
Set it to 0, but this cannot solve the problem fundamentally. The best way is to wrap the stream object with the Using statement, and close the recycle after it is used up.
* 7: abstract int Read (byte [] buffer, int offset, int count)
This method contains three key parameters: the buffer byte array, the offset and the number of read bytes. Each time a byte is read, the total number of bytes in a buffer zone is returned.
The first parameter: This array is equivalent to an empty box. Each time the Read () method reads a byte from the stream, it is put into this empty box. (You can use the buffer byte array after reading all the data)
The second parameter indicates the offset, which indicates the position (offset) in the stream for reading.
The last parameter is the number of bytes read.
The returned value is the total number of bytes read.
* 8: abstract long Seek (long offset, SeekOrigin origin)
Do you still remember the Position attribute? In fact, the Seek method is to reset a position in the stream. Before you describe the effect of the offset parameter, let's take a look at the SeekOrigin enumeration:
If offset is negative, it is required that the new location is prior to the location specified by the origin, and its interval is different from the number of bytes specified by offset. If offset is zero (0), the new position is required to be located at the position specified by origin.
If the offset value is positive, the new location is required to be located after the position specified by the origin, and the interval between the new locations is different from the number of bytes specified by the offset value.
Stream. Seek (-3, Origin. End); indicates the number of 3rd positions forward at the End of the Stream.
Stream. Seek (0, Origin. Begin); indicates the starting position of the Stream www.2cto.com
Stream. Seek (3, Orig 'in. Current); indicates the third position after the Current position of the Stream.
After searching, a new position in the stream is returned. In fact, we can understand the subtlety of the Seek method.
* 9: abstract void Write (byte [] buffer, int offset, int count)
This method contains three key parameters: the buffer byte array, the offset and the number of read bytes.
Different from the read method, buffer, the first parameter in the write method, already has many bytes.
We only need to set the offset and count to write the data in the buffer into the stream.
* 10: virtual void Close ()
Close the stream and release resources. In actual operations, if you do not need using, do not forget to close the stream after it is used.
This method is especially important. Never forget to close the current stream after it is used!
In order to allow you to quickly understand and digest the above attributes and methods, I will write an example and the key sections will be described in detail.
Static void Main (string [] args)
{
Byte [] buffer = null;
String testString = "Stream! Hello world ";
Char [] readCharArray = null;
Byte [] readBuffer = null;
String readString = string. Empty;
// I will elaborate on MemoryStream in subsequent chapters
Using (MemoryStream stream = new MemoryStream ())
{
Console. WriteLine ("Initial string: {0}", testString );
// If the stream can be written
If (stream. CanWrite)
{
// First, we try to write testString into the stream.
// For more information about Encoding, I will describe it in another article and use it to convert string-> byte [].
Buffer = Encoding. Default. GetBytes (testString );
// We start from the first position of the array and the length is 3. After writing, the stream has data.
// For beginners, it is hard to understand when data is written into the stream. I have met a lot in front of lengthy project code.
// Many new users will have this experience. I hope to use such simple code to give new users or veterans a basic experience.
Stream. Write (buffer, 0, 3 );
Console. WriteLine ("current Stream. Postion is at Position {0}", stream. Position + 1 );
// Move the last three digits from the last position (current position) to the last 7th digits
Long newPositionInStream = stream. CanSeek? Stream. Seek (3, SeekOrigin. Current): 0;
Console. WriteLine ("relocates and Stream. Postion is in position {0}", newPositionInStream + 1 );
If (newPositionInStream <buffer. Length)
{
// Write the new position (7th bits) to the end of the buffer. Note that the stream has written three data "Str"
Stream. Write (buffer, (int) newPositionInStream, buffer. Length-(int) newPositionInStream );
}
// After writing, set the Position attribute of stream to 0 to start reading data in the stream.
Stream. Position = 0;
// Set an empty box to receive data in the stream. The length is determined by the stream length.
ReadBuffer = new byte [stream. Length];
// Set the total number of stream reads,
// Note! At this time, the stream has read the data to readBuffer.
Int count = stream. CanRead? Stream. Read (readBuffer, 0, readBuffer. Length): 0;
// Since the encryption Encoding method was used at the beginning, we must decrypt and convert the readBuffer into a Char array to resplice it into a string.
// First, obtain the number of corresponding Char from the readBuffer data read by the stream.
Int charCount = Encoding. Default. GetCharCount (readBuffer, 0, count );
// Set a new readCharArray array by the number of Char
ReadCharArray = new char [charCount];
// The powerful feature of the Encoding class is that it not only contains encryption methods, but can even be created by the decrypted (GetDecoder ()),
// The decrypted will fill the readCharArray (through the GetChars method, convert the readBuffer one by one to convert byte to char, and fill it in the readCharArray in the same order)
Encoding. Default. GetDecoder (). GetChars (readBuffer, 0, count, readCharArray, 0 );
For (int I = 0; I <readCharArray. Length; I ++)
{
ReadString + = readCharArray [I];
}
Console. WriteLine ("read string: {0}", readString );
}
Stream. Close ();
}
Console. ReadLine ();
}
Display result:
Note that stream. Positon is a magical attribute. In complex programs, stream object operations are often complicated,
Be sure to set stream. Positon to the correct position you need, and use the using statement, which will automatically destroy the stream object,
Of course Stream. Close () everyone knows
Next let's talk about how to implement asynchronous operations in the stream.
There are several key methods in the Stream base class, which can implement asynchronous read/write well,
Asynchronous reading
Public virtual IAsyncResult BeginRead (byte [] buffer, int offset, int count, AsyncCallback callback, Object state)
Asynchronous write
Public virtual IAsyncResult BeginWrite (byte [] buffer, int offset, int count, AsyncCallback callback, Object state)
End asynchronous reading
Public virtual int EndRead (IAsyncResult asyncResult)
End asynchronous write
Public virtual void EndWrite (IAsyncResult asyncResult)
You can easily find that the first two methods implement the IAsyncResult interface, and the last two end methods also conform to the IAsyncResult parameter,
In fact, this is not complicated. (it must be noted that each time you call the in method, you must call the corresponding end method)
What is consistent with the general synchronous read or write method is that they can be used as synchronous methods, but they may not escape blocking and crash in complex cases, but once enabled
After Asynchronization, these blocking problems will no longer exist. It can be seen that Microsoft's support for Asynchronization is increasing.
Finally, the class diagram about the Stream class and its subclass in c #
What about class charts? Everyone will think so ^
Why is this gray in the directory? In fact, I personally think this class chart should not be included in this blog post because we really understand and are skilled in operating all the sub-classes of Stream? (Excluding Daniel)
(This is also one of the motivations for writing subsequent articles. writing blogs can improve the absorption of knowledge points, not only helping others, but also improving their understanding of knowledge points ), so I want to place the class diagram here
Summary of Series
Summary:
This chapter introduces the basic concepts of a Stream and some important attributes and methods contained in the Stream base class in c, the key is the details of some methods and attributes and the things we must pay attention to when operating the stream object,
Many of the knowledge points in this article are learned by yourself, and it is not easy to write text late at night. Please pay more attention. The next chapter will introduce streaming tools: StreamReader and StreamWriter.
Coming soon!
From anti-clockwise alert