前言
簡單介紹一下io流。
以前寫過兩篇,裡面是java 語言寫的,簡單介紹了一下io流,這裡是對io流的整理。
https://www.cnblogs.com/aoximin/p/12007925.html
https://www.cnblogs.com/aoximin/p/12044270.html
這裡說一下一個經驗,僅獻給入門的人。
剛寫程式碼進行io流讀取或者寫入的時候,有一個思維去考慮這個io流是怎麼從磁碟讀取的或者怎麼從記憶體讀取的,
這個想法是沒錯的,但是不是應用層面考慮的東西,是作業系統和硬體的結合(作業系統篇會介紹全面),這會使人腦複雜,下面請以應用層面考慮問題。
正文
在io流中有幾個概念必須知道:
-
字元流
-
位元組流
-
節點流
-
處理流
如果不清楚這些概念,那麼你就需要看完這一篇回憶一下以前的基礎。
在java中,比如一個檔案的讀取,分為FileInputStream 和 FileOutputStream。
但是在c# 是這樣設計的,檔案流就是檔案流, 沒有把輸入和輸出分開。
但是一般情況下,我們要麼讀,要麼寫,這樣複雜度就更低了。
比如我們建立一個檔案流:
FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
這裡面有幾個引數,分別是: 地址,FileMode,FileAccess,FileShare
那麼看下FileMode 裡面有什麼吧。
public enum FileMode
{
CreateNew = 1,
Create = 2,
Open = 3,
OpenOrCreate = 4,
Truncate = 5,
Append = 6,
}
可以直接參考這個文件:
https://learn.microsoft.com/zh-cn/dotnet/api/system.io.filemode?view=net-7.0
文件中描述的比較清楚,就不贅述了。
FileAccess 第二個引數是FileAccess
[Flags]
public enum FileAccess
{
Read = 1,
Write = 2,
ReadWrite = Write | Read, // 0x00000003
}
許可權,是讀,寫,或者讀和寫。
第4個引數是FileShare:
https://learn.microsoft.com/zh-cn/dotnet/api/system.io.fileshare?view=net-7.0
就是一些共享狀態,比如我這個檔案在讀了,另外的檔案是否可以讀。
這個可以根據自己的應用需求去處理。
然後我們一般情況下是會使用一個叫做File.create 方式去建立檔案流的。
那麼它的預設狀態是:
public static FileStream Create(string path, int bufferSize)
=> new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize);
所以這裡要知道的是,如果我們使用File.create得到的FileStream。
如果檔案存在呢,那麼檔案就會從頭開始寫,這點是新手值得注意的地方。
知道了前面這些基礎概念後,那麼就可以往下走了。
檔案
我們在應用層物件導向變成,那麼我們要做的是什麼?
要做的就是如果將這個檔案,如果抽象成一個物件。
那麼我們程式設計使用什麼方式可以抽象成一個物件呢?
static void Main(string[] args)
{
FileInfo a = new FileInfo("a.txt");
Console.ReadKey();
}
有一個FileInfo 供我們使用,這樣就可以將檔案對映成一個物件了。
一個FileInfo 我們可以拿到上面這些資訊。
還可以對檔案進行操作:
比如:
這些是操作檔案的,那麼有個問題啊,那就是如何操作目錄呢?
DirectoryInfo a = new DirectoryInfo("c://a");
目錄有目錄的資訊。
這裡值得注意的地方是,有些變成程式語言的思想是把目錄看出檔案,然後再檔案物件中就可以建立出目錄。
我們寫程式碼的時候瞭解一下程式語言的思維就好了。
io 流的分類
從運算元據單位不同分為:
-
位元組流
-
字元流
位元組流-它包括流,FileStream,MemoryStream 和 BufferedStream。
字元流-它包括TextReader-TextWriter,StreamReader,StreamWriter和其他流。
透過流的流向不同分為:
-
輸入流
-
輸出流
透過流的角色的不同分為:
-
節點流
-
處理流/包裝流
這個下面都會介紹到。
字元流
簡單介紹一下字元流,這裡面有一個問題。
我們都知道,在檔案儲存的最小單位是位元組。
總沒有聽說,一個檔案存一個bit吧。位元組是儲存的最小單位。
那麼就有一個問題啊,比如我們io,那麼最小有效單位應該也是位元組吧。
傳輸的也是位元組對吧,建立在這個理論基礎上,那麼我們的位元組流是合情合理的。
這個是傳輸層面的意義了。
那麼為什麼有字元流呢?因為我們發現字元格式有utf-8,ASCII等。
比如說utf-8,漢字是3個位元組。比如一個我,那麼應該讀取3個位元組,而不是一個位元組才是有意義的對吧。
那麼就有字元流了。位元組流是每次都是讀取一個位元組,字元流每次讀取的那麼就可能是一個位元組或者兩個或者3個,看編碼形式。
static void Main(string[] args)
{
TextReader textReader = new StreamReader("a.txt", Encoding.ASCII);
Console.ReadKey();
}
StreamReader 是檔案字元流。TextReader 是其基類。
所有的字元流的讀取基類是TextReader。
StreamReader 是對檔案的字元流的讀寫,那麼StringReader 是對記憶體的讀寫了。
其他的就不演示了,自我熟悉就好,c# 官方文件更加專業。
看文件就好:
https://learn.microsoft.com/zh-cn/dotnet/api/system.io.stringreader?view=net-7.0
節點流和處理流
什麼是節點流呢:
節點流是從一個特定的資料來源讀寫資料,如:StreamReader、FileStream。
就是直接從一個資料來源進行讀寫。
那麼什麼是處理流呢?
處理流也叫做包裝流,是連線在存在的流之上,為程式提供更為強大的讀寫功能,如BufferedStream。
static void Main(string[] args)
{
var a= File.Create("a.txt");
BufferedStream stream = new BufferedStream(a);
Console.ReadKey();
}
二進位制處理流
二進位制處理流是這樣的,其實很像字元流。
比如說,我們除了存字元,我們還可以存數字對吧。
還可以存bool型別。
那麼其實就是如果是讀取int,那麼就是讀取4個位元組,讀取bool 就是讀取兩個位元組。
static void Main(string[] args)
{
MemoryStream aStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(aStream);
writer.Write(10);
writer.Write(20);
Console.Read();
}
讀取的時候也是一樣的。
結
也沒什麼好記的,主要是整理一些概念,一些實現原理,會查文件就好。