C#文件操作、讀取文件、Debug/Trace類(lèi)用法
1、文件操作
這段代碼在 System.Private.CoreLib 下,對(duì) System.IO.File 中的代碼進(jìn)行精簡(jiǎn),供 CLR 使用。
當(dāng)使用文件時(shí),要提前判斷文件路徑是否存在,日常項(xiàng)目中要使用到文件的地方應(yīng)該不少,可以統(tǒng)一一個(gè)判斷文件是否存在的方法:
public static bool Exists(string? path)
{
try
{
// 可以將 string? 改成 string
if (path == null)
return false;
if (path.Length == 0)
return false;
path = Path.GetFullPath(path);
// After normalizing, check whether path ends in directory separator.
// Otherwise, FillAttributeInfo removes it and we may return a false positive.
// GetFullPath should never return null
Debug.Assert(path != null, "File.Exists: GetFullPath returned null");
if (path.Length > 0 && PathInternal.IsDirectorySeparator(path[^1]))
{
return false;
}
return InternalExists(path);
}
catch (ArgumentException) { }
catch (NotSupportedException) { } // Security can throw this on ":"
catch (SecurityException) { }
catch (IOException) { }
catch (UnauthorizedAccessException) { }
return false;
}建議項(xiàng)目中對(duì)路徑進(jìn)行最終處理的時(shí)候,都轉(zhuǎn)換為絕對(duì)路徑:
Path.GetFullPath(path)
當(dāng)然,相對(duì)路徑會(huì)被 .NET 正確識(shí)別,但是對(duì)于運(yùn)維排查問(wèn)題和各方面考慮,絕對(duì)路徑容易定位具體位置和排錯(cuò)。
在編寫(xiě)代碼時(shí),使用相對(duì)路徑,不要寫(xiě)死,提高靈活性;在運(yùn)行階段將其轉(zhuǎn)為絕對(duì)路徑;
上面的 NotSupportedException 等異常是操作文件中可能出現(xiàn)的各種異常情況,對(duì)于跨平臺(tái)應(yīng)用來(lái)說(shuō),這些異??赡芏际呛艹R?jiàn)的,提前將其異常類(lèi)型識(shí)別處理,可以?xún)?yōu)化文件處理邏輯以及便于篩查處理錯(cuò)誤。
2、讀取文件
這段代碼在 System.Private.CoreLib 中。
有個(gè)讀取文件轉(zhuǎn)換為 byte[] 的方法如下:
public static byte[] ReadAllBytes(string path)
{
// bufferSize == 1 used to avoid unnecessary buffer in FileStream
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1))
{
long fileLength = fs.Length;
if (fileLength > int.MaxValue)
throw new IOException(SR.IO_FileTooLong2GB);
int index = 0;
int count = (int)fileLength;
byte[] bytes = new byte[count];
while (count > 0)
{
int n = fs.Read(bytes, index, count);
if (n == 0)
throw Error.GetEndOfFile();
index += n;
count -= n;
}
return bytes;
}
}
可以看到 FileStream 的使用,如果單純是讀取文件內(nèi)容,可以參考里面的代碼:
FileStream fs = new FileStream(path,
FileMode.Open,
FileAccess.Read,
FileShare.Read,
bufferSize: 1)上面的代碼同樣也存在 File.ReadAllBytes 與之對(duì)應(yīng), File.ReadAllBytes 內(nèi)部是使用 InternalReadAllBytes 來(lái)處理文檔讀取:
private static byte[] InternalReadAllBytes(String path, bool checkHost)
{
byte[] bytes;
// 此 FileStream 的構(gòu)造函數(shù)不是 public ,開(kāi)發(fā)者不能使用
using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,
FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, checkHost)) {
// Do a blocking read
int index = 0;
long fileLength = fs.Length;
if (fileLength > Int32.MaxValue)
throw new IOException(Environment.GetResourceString("IO.IO_FileTooLong2GB"));
int count = (int) fileLength;
bytes = new byte[count];
while(count > 0) {
int n = fs.Read(bytes, index, count);
if (n == 0)
__Error.EndOfFile();
index += n;
count -= n;
}
}
return bytes;
}
這段說(shuō)明我們可以放心使用 File 靜態(tài)類(lèi)中的函數(shù),因?yàn)槔锩嬉呀?jīng)處理好一些邏輯了,并且自動(dòng)釋放文件。
如果我們手動(dòng) new FileStream ,則要判斷一些情況,以免使用時(shí)報(bào)錯(cuò),最好參考一下上面的代碼。
.NET 文件流緩存大小默認(rèn)是 4096 字節(jié):
internal const int DefaultBufferSize = 4096;
這段代碼在 File 類(lèi)中定義,開(kāi)發(fā)者不能設(shè)置緩存塊的大小,大多數(shù)情況下,4k 是最優(yōu)的塊大小。
ReadAllBytes 的文件大小上限是 2 GB。
3、Debug 、Trace類(lèi)
這兩個(gè)類(lèi)的命名空間為 System.Diagnostics,Debug 、Trace 提供一組有助于調(diào)試代碼的方法和屬性。
Debug 中的所有函數(shù)都不會(huì)在 Release 中有效,并且所有輸出流不會(huì)在控制臺(tái)顯示,必須注冊(cè)偵聽(tīng)器才能讀取這些流。
Debug 可以打印調(diào)試信息并使用斷言檢查邏輯,使代碼更可靠,而不會(huì)影響發(fā)運(yùn)產(chǎn)品的性能和代碼大小。
這類(lèi)輸出方法有 Write 、WriteLine 、 WriteIf 和 WriteLineIf 等,這里輸出不會(huì)直接打印到控制臺(tái)。
如需將調(diào)試信息打印到控制臺(tái),可以注冊(cè)偵聽(tīng)器:
ConsoleTraceListener console = new ConsoleTraceListener(); Trace.Listeners.Add(console);
注意, .NET Core 2.x 以上 Debug 沒(méi)有 Listeners ,因?yàn)?Debug 使用的是 Trace 的偵聽(tīng)器。
我們可以給 Trace.Listeners 注冊(cè)偵聽(tīng)器,這樣相對(duì)于 Debug 等效設(shè)置偵聽(tīng)器。
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Debug.WriteLine("aa");.NET Core 中的監(jiān)聽(tīng)器都繼承了 TraceListener,如 TextWriterTraceListener、ConsoleTraceListener、DefaultTraceListener。
如果需要輸出到文件中,可以自行繼承 TextWriterTraceListener ,編寫(xiě)文件流輸出,也可以使用 DelimitedListTraceListener。
示例:
TraceListener listener = new DelimitedListTraceListener(@"C:\debugfile.txt");
// Add listener.
Debug.Listeners.Add(listener);
// Write and flush.
Debug.WriteLine("Welcome");處理上述方法輸出控制臺(tái),也可以使用
ConsoleTraceListener console=... ...Listeners.Add(console); // 等效于 var console = new TextWriterTraceListener(Console.Out)
為了格式化輸出流,可以使用 一下屬性控制排版:
| 屬性 | 說(shuō)明 |
|---|---|
| AutoFlush | 獲取或設(shè)置一個(gè)值,通過(guò)該值指示每次寫(xiě)入后是否應(yīng)在 Flush() 上調(diào)用 Listeners。 |
| IndentLevel | 獲取或設(shè)置縮進(jìn)級(jí)別。 |
| IndentSize | 獲取或設(shè)置縮進(jìn)的空格數(shù)。 |
// 1.
Debug.WriteLine("One");
// Indent and then unindent after writing.
Debug.Indent();
Debug.WriteLine("Two");
Debug.WriteLine("Three");
Debug.Unindent();
// End.
Debug.WriteLine("Four");
// Sleep.
System.Threading.Thread.Sleep(10000);One
Two
Three
Four.Assert() 方法對(duì)我們調(diào)試程序很有幫助,Assert 向開(kāi)發(fā)人員發(fā)送一個(gè)強(qiáng)消息。在 IDE 中,斷言會(huì)中斷程序的正常操作,但不會(huì)終止應(yīng)用程序。
.Assert() 的最直觀效果是輸出程序的斷言位置。
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
int value = -1;
// A.
// If value is ever -1, then a dialog will be shown.
Debug.Assert(value != -1, "Value must never be -1.");
// B.
// If you want to only write a line, use WriteLineIf.
Debug.WriteLineIf(value == -1, "Value is -1.");---- DEBUG ASSERTION FAILED ---- ---- Assert Short Message ---- Value must never be -1. ---- Assert Long Message ---- at Program.Main(String[] args) in ...Program.cs:line 12 Value is -1.
Debug.Prinf() 也可以輸出信息,它跟 C 語(yǔ)言的 printf 函數(shù)行為一致,將后跟行結(jié)束符的消息寫(xiě)入,默認(rèn)行終止符為回車(chē)符后跟一個(gè)換行符。
在 IDE 中運(yùn)行程序時(shí),使用 Debug.Assert()、Trace.Assert() 等方法 ,條件為 false 時(shí),IDE 會(huì)斷言,這相當(dāng)于條件斷點(diǎn)。
在非 IDE 環(huán)境下,程序會(huì)輸出一些信息,但不會(huì)有中斷效果。
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.Assert(false);Process terminated. Assertion Failed at Program.Main(String[] args) in C:\ConsoleApp4\Program.cs:line 44
個(gè)人認(rèn)為,可以將 Debug、Trace 引入項(xiàng)目中,與日志組件配合使用。Debug、Trace 用于記錄程序運(yùn)行的診斷信息,便于日后排查程序問(wèn)題;日志用于記錄業(yè)務(wù)過(guò)程,數(shù)據(jù)信息等。
.Assert() 的原理, 在 true 時(shí)什么都不做;在 false 時(shí)調(diào)用 Fail 函數(shù);如果你不注冊(cè)偵聽(tīng)器的話(huà),默認(rèn)也沒(méi)事可做。
.Assert() 唯一可做的事情是等條件為 false 時(shí),執(zhí)行 Fail 方法,當(dāng)然我們也可以手動(dòng)直接調(diào)用 Fail 方法,F(xiàn)ail 的代碼如下:
public static void Fail(string message) {
if (UseGlobalLock) {
lock (critSec) {
foreach (TraceListener listener in Listeners) {
listener.Fail(message);
if (AutoFlush) listener.Flush();
}
}
}
else {
foreach (TraceListener listener in Listeners) {
if (!listener.IsThreadSafe) {
lock (listener) {
listener.Fail(message);
if (AutoFlush) listener.Flush();
}
}
else {
listener.Fail(message);
if (AutoFlush) listener.Flush();
}
}
}
}到此這篇關(guān)于C#文件操作、讀取文件、Debug/Trace類(lèi)用法的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法詳解
- C#利用File方法對(duì)文件的操作總結(jié)(字節(jié)寫(xiě)入和讀取)
- C#執(zhí)行EXE文件與輸出消息的提取操作
- c# 文件操作(移動(dòng),復(fù)制,重命名)
- C#操作INI配置文件示例詳解
- C#文件操作類(lèi)分享
- FtpHelper實(shí)現(xiàn)ftp服務(wù)器文件讀寫(xiě)操作(C#)
- C#操作本地文件及保存文件到數(shù)據(jù)庫(kù)的基本方法總結(jié)
- C#使用oledb操作excel文件的方法
- C#使用iTextSharp封裝的PDF文件操作類(lèi)實(shí)例
相關(guān)文章
C#給picturebox控件加圖片選中狀態(tài)的2個(gè)方法
C#給picturebox控件加圖片選中狀態(tài)的2個(gè)方法,需要的朋友可以參考一下2013-03-03
C#中WPF內(nèi)存回收與釋放LierdaCracker的實(shí)現(xiàn)
本文主要介紹了C#中WPF內(nèi)存回收與釋放LierdaCracker的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
WPF實(shí)現(xiàn)上下滾動(dòng)字幕效果
這篇文章主要為大家詳細(xì)介紹了WPF實(shí)現(xiàn)上下滾動(dòng)字幕效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
C#實(shí)體類(lèi)轉(zhuǎn)換的兩種方式小結(jié)
這篇文章主要介紹了C#實(shí)體類(lèi)轉(zhuǎn)換的兩種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
C# 實(shí)現(xiàn)Trim方法去除字符串前后的所有空格
這篇文章主要介紹了C# 實(shí)現(xiàn)Trim方法去除字符串前后的所有空格,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
使用C#給PDF文檔添加注釋的實(shí)現(xiàn)代碼
本文將實(shí)例講述C#中如何使用免費(fèi)組件給PDF文檔添加文本注釋?zhuān)ㄗ杂晌谋咀⑨?。自由文本注釋能允許我們自定義它的風(fēng)格和外觀,非常具有實(shí)用價(jià)值2017-01-01
用C#實(shí)現(xiàn)啟動(dòng)另一程序的方法實(shí)例
一段實(shí)例代碼,程序的目的是使用C#實(shí)現(xiàn)啟動(dòng)另一程序的方法。技術(shù)總監(jiān)給出了我們這樣一個(gè)有效的啟動(dòng)程序的有效方法,現(xiàn)在和大家分享下2013-07-07

