當打開文件進行讀寫時,它變成一個 流。
從根本上說,流是通過通信路徑傳遞的字節序列。
有兩個主要的流:輸入流 和 輸出流。
-
輸入流用於從文件讀取數據(讀操作)
-
輸出流用於向文件寫入數據(寫操作)
文章目錄
一、C# I/O 類
System.IO 命名空間有各種不同的類,用於執行各種文件操作,如創建和刪除文件、讀取或寫入文件,關閉文件等。
System.IO 命名空間中常用的非抽象類:
I/O 類 | 描述 |
---|---|
BinaryReader | 從二進制流讀取原始數據。 |
BinaryWriter | 以二進制格式寫入原始數據。 |
BufferedStream | 字節流的臨時存儲。 |
Directory | 有助於操作目錄結構。 |
DirectoryInfo | 用於對目錄執行操作。 |
DriveInfo | 提供驅動器的信息。 |
File | 有助於處理文件。 |
FileInfo | 用於對文件執行操作。 |
FileStream | 用於文件中任何位置的讀寫。 |
MemoryStream | 用於隨機訪問存儲在內存中的數據流。 |
Path | 對路徑信息執行操作。 |
StreamReader | 用於從字節流中讀取字符。 |
StreamWriter | 用於向一個流中寫入字符。 |
StringReader | 用於讀取字符串緩衝區。 |
StringWriter | 用於寫入字符串緩衝區。 |
二、FileStream 類
System.IO 命名空間中的 FileStream 類有助於文件的讀寫與關閉。
該類派生自抽象類 Stream。
您需要創建一個 FileStream 對象來創建一個新的文件,或打開一個已有的文件。
創建 FileStream 對象的語法:
FileStream <object_name> = new FileStream( <file_name>,
<FileMode Enumerator>, <FileAccess Enumerator>, <FileShare Enumerator>);
例:創建一個 FileStream 對象 F 來讀取名爲 sample.txt 的文件
FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
參數:
- FileMode 枚舉定義了各種打開文件的方法。FileMode 枚舉的成員有:
- Append:打開一個已有的文件,並將光標放置在文件的末尾。如果文件不存在,則創建文件。
- Create:創建一個新的文件。如果文件已存在,則刪除舊文件,然後創建新文件。
- CreateNew:指定操作系統應創建一個新的文件。如果文件已存在,則拋出異常。
- Open:打開一個已有的文件。如果文件不存在,則拋出異常。
- OpenOrCreate:指定操作系統應打開一個已有的文件。如果文件不存在,則用指定的名稱創建一個新的文件打開。
- Truncate:打開一個已有的文件,文件一旦打開,就將被截斷爲零字節大小。然後我們可以向文件寫入全新的數據,但是保留文件的初始創建日期。如果文件不存在,則拋出異常。
- FileAccess 枚舉的成員有:Read、ReadWrite 和 Write。
- FileShare 枚舉的成員有:
- Inheritable:允許文件句柄可由子進程繼承。Win32 不直接支持此功能。
- None:謝絕共享當前文件。文件關閉前,打開該文件的任何請求(由此進程或另一進程發出的請求)都將失敗。
- Read:允許隨後打開文件讀取。如果未指定此標誌,則文件關閉前,任何打開該文件以進行讀取的請求(由此進程或另一進程發出的請求)都將失敗。但是,即使指定了此標誌,仍可能需要附加權限才能夠訪問該文件。
- ReadWrite:允許隨後打開文件讀取或寫入。如果未指定此標誌,則文件關閉前,任何打開該文件以進行讀取或寫入的請求(由此進程或另一進程發出)都將失敗。但是,即使指定了此標誌,仍可能需要附加權限才能夠訪問該文件。
- Write:允許隨後打開文件寫入。如果未指定此標誌,則文件關閉前,任何打開該文件以進行寫入的請求(由此進程或另一進過程發出的請求)都將失敗。但是,即使指定了此標誌,仍可能需要附加權限才能夠訪問該文件。
- Delete:允許隨後刪除文件。
例:
using System;
using System.IO;
namespace FileIOApplication
{
class Program
{
static void Main(string[] args)
{
FileStream F = new FileStream("test.dat",
FileMode.OpenOrCreate, FileAccess.ReadWrite);
for (int i = 1; i <= 20; i++)
{
F.WriteByte((byte)i);
}
F.Position = 0;
for (int i = 0; i <= 20; i++)
{
Console.Write(F.ReadByte() + " ");
}
F.Close();
Console.ReadKey();
}
}
}
運行結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1
這裏可以看到,由於最後一位我們沒有寫入,所以讀取到的是 -1。
二如果我們再運行一遍這個程序,改爲寫入 10 位,讀取 11 位,那讀到的 11 個數字都有結果,這是因爲前面寫入的信息還在。
三、C# 高級文件操作
3.1 文本文件的讀寫
StreamReader 和 StreamWriter 類有助於完成文本文件的讀寫。
這些類從抽象基類 Stream 繼承,Stream 支持文件流的字節讀寫。
3.1.1 StreamReader 類
StreamReader 類繼承自抽象基類 TextReader,表示閱讀器讀取一系列字符。
StreamReader 類中一些常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public override void Close() 關閉 StreamReader 對象和基礎流,並釋放任何與讀者相關的系統資源。 |
2 | public override int Peek() 返回下一個可用的字符,但不使用它。 |
3 | public override int Read() 從輸入流中讀取下一個字符,並把字符位置往前移一個字符。 |
例:對文件 Jamaica.txt 進行讀取
該文件內容:
Down the way where the nights are gay
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop
首先把文本文件放置到運行目錄下。
程序:
using System;
using System.IO;
namespace FileApplication
{
class Program
{
static void Main(string[] args)
{
try
{
// 創建一個 StreamReader 的實例來讀取文件
// using 語句也能關閉 StreamReader
// 感覺像是 python 中的 with open
using (StreamReader sr = new StreamReader("./jamaica.txt"))
{
string line;
// 從文件讀取並顯示行,直到文件的末尾
while ((line = sr.ReadLine()) != null) // 每次讀取一行
{
Console.WriteLine(line); // 顯示這一行內容
}
}
}
catch (Exception e)
{
// 向用戶顯示出錯消息
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
}
}
運行結果:
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop
3.1.2 StreamWriter 類
StreamWriter 類繼承自抽象類 TextWriter,表示編寫器寫入一系列字符。
StreamWriter 類中一些常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public override void Close() 關閉當前的 StreamWriter 對象和基礎流。 |
2 | public override void Flush() 清理當前編寫器的所有緩衝區,使得所有緩衝數據寫入基礎流。 |
3 | public virtual void Write(bool value) 把一個布爾值的文本表示形式寫入到文本字符串或流。(繼承自 TextWriter。) |
4 | public override void Write( char value ) 把一個字符寫入到流。 |
5 | public virtual void Write( decimal value ) 把一個十進制值的文本表示形式寫入到文本字符串或流。 |
6 | public virtual void Write( double value ) 把一個 8 字節浮點值的文本表示形式寫入到文本字符串或流。 |
7 | public virtual void Write( int value ) 把一個 4 字節有符號整數的文本表示形式寫入到文本字符串或流。 |
8 | public override void Write( string value ) 把一個字符串寫入到流。 |
9 | public virtual void WriteLine() 把行結束符寫入到文本字符串或流。 |
例:使用 StreamWriter 類向文件寫入文本數據
using System;
using System.IO;
namespace FileApplication
{
class Program
{
static void Main(string[] args)
{
string[] names = new string[] {"Zara Ali", "Nuha Ali"};
// 通過 StreamWriter 類的實例化進行打開文件
using (StreamWriter sw = new StreamWriter("names.txt"))
{
foreach (string s in names) // 取得列表中一個元素
{
sw.WriteLine(s); // 寫入文件一行
}
}
// 從文件中讀取並顯示每行
string line = "";
// 通過 StreamReader 類的實例化進行打開文件
using (StreamReader sr = new StreamReader("names.txt"))
{
while ((line = sr.ReadLine()) != null) // 每次讀取一行
{
Console.WriteLine(line); // 顯示該行內容
}
}
Console.ReadKey();
}
}
}
運行結果:
Zara Ali
Nuha Ali
3.2 C# 二進制文件的讀寫
BinaryReader 和 BinaryWriter 類用於二進制文件的讀寫。
3.2.1 BinaryReader 類
BinaryReader 類用於從文件讀取二進制數據。
一個 BinaryReader 對象通過向它的構造函數傳遞 FileStream 對象而被創建。
BinaryReader 類中常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public override void Close() 關閉 BinaryReader 對象和基礎流。 |
2 | public virtual int Read() 從基礎流中讀取字符,並把流的當前位置往前移。 |
3 | public virtual bool ReadBoolean() 從當前流中讀取一個布爾值,並把流的當前位置往前移一個字節。 |
4 | public virtual byte ReadByte() 從當前流中讀取下一個字節,並把流的當前位置往前移一個字節。 |
5 | public virtual byte[] ReadBytes( int count ) 從當前流中讀取指定數目的字節到一個字節數組中,並把流的當前位置往前移指定數目的字節。 |
6 | public virtual char ReadChar() 從當前流中讀取下一個字節,並把流的當前位置按照所使用的編碼和從流中讀取的指定的字符往前移。 |
7 | public virtual char[] ReadChars( int count ) 從當前流中讀取指定數目的字節,在一個字符數組中返回數組,並把流的當前位置按照所使用的編碼和從流中讀取的指定的字符往前移。 |
8 | public virtual double ReadDouble() 從當前流中讀取一個 8 字節浮點值,並把流的當前位置往前移八個字節。 |
9 | public virtual int ReadInt32() 從當前流中讀取一個 4 字節有符號整數,並把流的當前位置往前移四個字節。 |
10 | public virtual string ReadString() 從當前流中讀取一個字符串。字符串以長度作爲前綴,同時編碼爲一個七位的整數。 |
3.2.2 BinaryWriter 類
BinaryWriter 類用於向文件寫入二進制數據。
一個 BinaryWriter 對象通過向它的構造函數傳遞 FileStream 對象而被創建。
BinaryWriter 類中常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public override void Close() 關閉 BinaryWriter 對象和基礎流。 |
2 | public virtual void Flush() 清理當前編寫器的所有緩衝區,使得所有緩衝數據寫入基礎設備。 |
3 | public virtual long Seek( int offset, SeekOrigin origin ) 設置當前流內的位置。 |
4 | public virtual void Write( bool value ) 把一個單字節的布爾值寫入到當前流中,0 表示 false,1 表示 true。 |
5 | public virtual void Write( byte value ) 把一個無符號字節寫入到當前流中,並把流的位置往前移一個字節。 |
6 | public virtual void Write( byte[] buffer ) 把一個字節數組寫入到基礎流中。 |
7 | public virtual void Write( char ch ) 把一個 Unicode 字符寫入到當前流中,並把流的當前位置按照所使用的編碼和要寫入到流中的指定的字符往前移。 |
8 | public virtual void Write( char[] chars ) 把一個字符數組寫入到當前流中,並把流的當前位置按照所使用的編碼和要寫入到流中的指定的字符往前移。 |
9 | public virtual void Write( double value ) 把一個 8 字節浮點值寫入到當前流中,並把流位置往前移八個字節。 |
10 | public virtual void Write( int value ) 把一個 4 字節有符號整數寫入到當前流中,並把流位置往前移四個字節。 |
11 | public virtual void Write( string value ) 把一個以長度爲前綴的字符串寫入到 BinaryWriter 的當前編碼的流中,並把流的當前位置按照所使用的編碼和要寫入到流中的指定的字符往前移。 |
例:讀取和寫入二進制數據
using System;
using System.IO;
namespace BinaryFileApplication
{
class Program
{
static void Main(string[] args)
{
BinaryWriter bw;
BinaryReader br;
int i = 25;
double d = 3.14157;
bool b = true;
string s = "I am happy";
// 創建文件
try
{
bw = new BinaryWriter(new FileStream("mydata",
FileMode.Create));
}
catch (IOException e)
{
Console.WriteLine(e.Message + "\n Cannot create file.");
return;
}
// 寫入文件
try
{
bw.Write(i);
bw.Write(d);
bw.Write(b);
bw.Write(s);
}
catch (IOException e)
{
Console.WriteLine(e.Message + "\n Cannot write to file.");
return;
}
bw.Close();
// 讀取文件
try
{
br = new BinaryReader(new FileStream("mydata",
FileMode.Open));
}
catch (IOException e)
{
Console.WriteLine(e.Message + "\n Cannot open file.");
return;
}
try
{
i = br.ReadInt32();
Console.WriteLine("Integer data: {0}", i);
d = br.ReadDouble();
Console.WriteLine("Double data: {0}", d);
b = br.ReadBoolean();
Console.WriteLine("Boolean data: {0}", b);
s = br.ReadString();
Console.WriteLine("String data: {0}", s);
}
catch (IOException e)
{
Console.WriteLine(e.Message + "\n Cannot read from file.");
return;
}
br.Close();
Console.ReadKey();
}
}
}
運行結果:
Integer data: 25
Double data: 3.14157
Boolean data: True
String data: I am happy
總結:
這裏的核心在於,寫入和讀取各個元素的順序不能改變,否則用 ReadDouble 讀取存入的 int 數據就會出錯。
3.3 Windows 文件系統的操作
使用DirectoryInfo 類和 FileInfo 類來搓做目錄和文件。
3.3.1 DirectoryInfo 類
DirectoryInfo 類派生自 FileSystemInfo 類。
提供了各種用於創建、移動、瀏覽目錄和子目錄的方法。
該類不能被繼承。
DirectoryInfo 類中一些常用的屬性:
序號 | 屬性 & 描述 |
---|---|
1 | Attributes 獲取當前文件或目錄的屬性。 |
2 | CreationTime 獲取當前文件或目錄的創建時間。 |
3 | Exists 獲取一個表示目錄是否存在的布爾值。 |
4 | Extension 獲取表示文件存在的字符串。 |
5 | FullName 獲取目錄或文件的完整路徑。 |
6 | LastAccessTime 獲取當前文件或目錄最後被訪問的時間。 |
7 | Name 獲取該 DirectoryInfo 實例的名稱。 |
DirectoryInfo 類中一些常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public void Create() 創建一個目錄。 |
2 | public DirectoryInfo CreateSubdirectory( string path ) 在指定的路徑上創建子目錄。指定的路徑可以是相對於 DirectoryInfo 類的實例的路徑。 |
3 | public override void Delete() 如果爲空的,則刪除該 DirectoryInfo。 |
4 | public DirectoryInfo[] GetDirectories() 返回當前目錄的子目錄。 |
5 | public FileInfo[] GetFiles() 從當前目錄返回文件列表。 |
3.3.2 FileInfo 類
FileInfo 類派生自 FileSystemInfo 類。
提供了用於創建、複製、刪除、移動、打開文件的屬性和方法,且有助於 FileStream 對象的創建。
該類不能被繼承。
FileInfo 類中一些常用的屬性:
序號 | 屬性 & 描述 |
---|---|
1 | Attributes 獲取當前文件的屬性。 |
2 | CreationTime 獲取當前文件的創建時間。 |
3 | Directory 獲取文件所屬目錄的一個實例。 |
4 | Exists 獲取一個表示文件是否存在的布爾值。 |
5 | Extension 獲取表示文件存在的字符串。 |
6 | FullName 獲取文件的完整路徑。 |
7 | LastAccessTime 獲取當前文件最後被訪問的時間。 |
8 | LastWriteTime 獲取文件最後被寫入的時間。 |
9 | Length 獲取當前文件的大小,以字節爲單位。 |
10 | Name 獲取文件的名稱。 |
FileInfo 類中一些常用的方法:
序號 | 方法 & 描述 |
---|---|
1 | public StreamWriter AppendText() 創建一個 StreamWriter,追加文本到由 FileInfo 的實例表示的文件中。 |
2 | public FileStream Create() 創建一個文件。 |
3 | public override void Delete() 永久刪除一個文件。 |
4 | public void MoveTo( string destFileName ) 移動一個指定的文件到一個新的位置,提供選項來指定新的文件名。 |
5 | public FileStream Open( FileMode mode ) 以指定的模式打開一個文件。 |
6 | public FileStream Open( FileMode mode, FileAccess access ) 以指定的模式,使用 read、write 或 read/write 訪問,來打開一個文件。 |
7 | public FileStream Open( FileMode mode, FileAccess access, FileShare share ) 以指定的模式,使用 read、write 或 read/write 訪問,以及指定的分享選項,來打開一個文件。 |
8 | public FileStream OpenRead() 創建一個只讀的 FileStream。 |
9 | public FileStream OpenWrite() 創建一個只寫的 FileStream。 |
例:
using System;
using System.IO;
namespace WindowsFileApplication
{
class Program
{
static void Main(string[] args)
{
// 創建一個 DirectoryInfo 對象
DirectoryInfo mydir = new DirectoryInfo(@"./");
// 獲取當前目錄中的文件以及它們的名稱和大小
FileInfo [] f = mydir.GetFiles();
foreach (FileInfo file in f)
{
Console.WriteLine("File Name: {0} Size: {1}",
file.Name, file.Length);
}
Console.ReadKey();
}
}
}
運行結果:
顯示當前目錄的所有文件名,及各個文件大小。