溫故而知新之C#中的Stream篇
TextWriter 和 StreamWriter
目錄:
為何介紹TextWriter?
TextWriter的構造,常用屬性和方法
IFormatProvider的簡單介紹
如何理解StreamWriter?
StreamWriter屬性
StreamWriter示例
本章總結
為何介紹TextWriter?
就像上篇講述的一樣,對于重要的基礎技術,我們一定要刨根問底,這樣在面對將來可能很復雜的業(yè)務或技術時才能游刃有余,
甚至可以創(chuàng)新出新的解決方案,言歸正傳,想了解StreamWriter 必須了解其父親TextWriter的結構和使用方法。
那么微軟為什么要創(chuàng)建立這個抽象類呢?看下圖
的確可以這樣理解C,C++ ,XAML,Html一切可以寫在文本上寫的語言都可以用Text這個詞在抽象,(千萬別小看記事本,它才是元老?。?/p>
聰明的你想到了,今后我們可以自定義一些自己Writer類來實現(xiàn)我們特定的寫功能。現(xiàn)在我們只要理解TextWriter是一個抽象的文本寫入器,
可以在文本上寫入我們想要的格式,可以通過微軟派生類或著自定義派生類來實現(xiàn)TextWriter的功能。只要你有足夠的想象力就能在創(chuàng)新
出一個新的派生類。
TextWriter的構造,常用屬性和方法
以下是TextWriter構造函數(shù):
和所有的抽象類一樣,該類不能直接實例化,它有2個構造函數(shù)
特別我想說下第二個構造函數(shù),大家發(fā)現(xiàn)這個構造有個IFomatProvider類型的參數(shù), 這個是什么東東?
IFormatProvider接口的簡單介紹
其實IFormatProvider接口 從字面上就能理解了,一個格式化的提供者
大家記得我們常用的string.format(“{0:P}”,data);么? IFormatProvider在這里被隱式的調用了
關于隱式調用的各種方式,用個簡單的例子向大家說明下:
- //有關數(shù)字格式化隱性使用IFomatProvider的例子
- #iftrue
- //貨幣
- Console.WriteLine(string.Format("顯示貨幣格式{0:c3}",12));
- //十進制
- Console.WriteLine("顯示貨幣十進制格式{0:d10}", 12);
- //科學計數(shù)法
- Console.WriteLine("科學計數(shù)法{0:e5}",12);
- //固定點格式
- Console.WriteLine("固定點格式 {0:f10}",12);
- //常規(guī)格式
- Console.WriteLine("常規(guī)格式{0:g10}",12);
- //數(shù)字格式(用分號隔開)
- Console.WriteLine("數(shù)字格式 {0:n5}:",666666666);
- //百分號格式
- Console.WriteLine("百分號格式(不保留小數(shù)){0:p0}",0.55);
- //16進制
- Console.WriteLine("16進制{0:x0}", 12);
- //0定位器 此示例保留5位小數(shù),如果小數(shù)部分小于5位,用0填充
- Console.WriteLine("0定位器{0:000.00000}",1222.133);
- //數(shù)字定位器
- Console.WriteLine("數(shù)字定位器{0:(#).###}", 0200.0233000);
- //小數(shù)
- Console.WriteLine("小數(shù)保留一位{0:0.0}", 12.222);
- //百分號的另一種寫法,注意小數(shù)的四舍五入
- Console.WriteLine("百分號的另一種寫法,注意小數(shù)的四舍五入{0:0%.00}", 0.12345);
- Console.WriteLine(" ");
- #endif
輸出結果:
也就是說IFormatProvider 提供了一個格式化的工具。
讓我們通過NumberFormatInfo類來溫故下:
這個密封類實現(xiàn)了IFormatProvider接口,主要實現(xiàn)了一個數(shù)字格式化的類,下面是一些規(guī)定的格式說明符:
c、C |
貨幣格式。關聯(lián)的屬性包括: |
d、D |
十進制格式。 |
e、E |
科學計數(shù)(指數(shù))格式。 |
f、F |
固定點格式。 |
g、G |
常規(guī)格式。 |
n、N |
數(shù)字格式。 |
p、P |
百分比格式。 |
讓我們用簡單易懂的代碼來實現(xiàn)下NumberFormatInfo 如何使用:
- #iftrue
- //顯性使用IFomatProvider
- Console.WriteLine("顯性使用IFomatProvider的例子");
- //實例化numberFomatProvider對象
- NumberFormatInfo numberFomatProvider = newNumberFormatInfo();
- //設置該provider對于貨幣小數(shù)的顯示長度
- numberFomatProvider.CurrencyDecimalDigits = 10;
- //注意:我們可以使用C+數(shù)字形式來改變provider提供的格式
- Console.WriteLine(string.Format(numberFomatProvider, "provider設置的貨幣格式{0:C}", 12));
- Console.WriteLine(string.Format(numberFomatProvider, "provider設置的貨幣格式被更改了:{0:C2}", 12));
- Console.WriteLine(string.Format(numberFomatProvider, "默認百分號和小數(shù)形式{0:p2}", 0.12));
- //將小數(shù) “.”換成"?"
- numberFomatProvider.PercentDecimalSeparator = "?";
- Console.WriteLine(string.Format(numberFomatProvider, "provider設置的百分號和小數(shù)形式{0:p2}", 0.12));
- Console.ReadLine();
- #endif
輸出結果:
正如上述代碼所表示的,IFormatProvider提供用于檢索控制格式化的對象的機制。我們甚至可以自定義provider類來實現(xiàn)特殊的
字符串格式化,關于這個重要的知識點我會在另一篇文章中詳細介紹并且自定義一個簡單的FormatInfo類
言歸正傳讓我們理解下TextWriter的幾個重要屬性
*1:Encoding: 可以獲得當前TextWriter的Encoding
*2:FormatProvider: 可以獲得當前TextWriter的IFormatProvider
*3:NewLine: 每當調用WriteLine()方法時,行結束符字符串都會寫入到文本流中,該屬性就是讀取
該結束符字符串
方法:
*1:Close():關閉TextWriter并且釋放TextWriter的資源
*2:Dispose(): 釋放TextWriter所占有的所有資源(和StreamReader相似,一旦TextWriter被釋放,它所占有的資源例如Stream會一并釋放)
*3:Flush(): 和Stream類中一樣,將緩沖區(qū)所有數(shù)據(jù)立刻寫入文件(基礎設備)
*4:Write()方法的重載(這個方法重載太多了,所以這里就不全寫出了,大家可以參考最后一個例子的打印結果)
*5:WriteLine()方法的重載:和Write()方法相比區(qū)別在于每個重載執(zhí)行完畢之后會附加寫入一個換行符
如何理解StreamWriter?
首先我們先了解下StreamWriter的概念:實現(xiàn)一個 TextWriter,使其以一種特定的編碼向流中寫入字符。
那會有很多朋友會疑惑,StreamWriter和TextWriter有什么區(qū)別?
其實從名字定義我們便可區(qū)分了,TextWriter分別是對連續(xù)字符系列處理的編寫器,而StreamWriter通過特定的編碼和流的方式對數(shù)據(jù)進行處理的編寫器
StreamWriter的構造函數(shù)
*1:public StreamWriter(string path);
參數(shù)path表示文件所在的位置
*2:public StreamWriter(Stream stream, Encoding encoding);
參數(shù)Stream 表示可以接受stream的任何子類或派生類,Encoding表示讓StreamWriter 在寫操作時使用該encoding進行編碼操作
*3:public StreamWriter(string path, bool append);
第二個append參數(shù)非常重要,當append參數(shù)為true時,StreamWriter會通過path去找當前文件是否存在,如果存在則進行append或overwrite的操作,否則創(chuàng)建新的文件
*4:public StreamWriter(Stream stream, Encoding encoding, int bufferSize);
bufferSize參數(shù)設置當前StreamWriter的緩沖區(qū)的大小
StreamWriter的屬性
StreamWriter的方法大多都繼承了TextWriter 這里就不在重復敘述了,這里就簡單介紹下StreamWriter獨有的屬性
*1:AutoFlush: 這個值來指示每次使用streamWriter.Write()方法后直接將緩沖區(qū)的數(shù)據(jù)寫入文件(基礎流)
*2:BaseStream: 和StreamReader相似可以取出當前的Stream對象加以處理
StreamWriter示例
- conststringtxtFilePath = "D:\TextWriter.txt";
- staticvoidMain(string[] args)
- {
- NumberFormatInfo numberFomatProvider = newNumberFormatInfo();
- //將小數(shù) “.”換成"?"
- numberFomatProvider.PercentDecimalSeparator = "?";
- StreamWriterTest test = newStreamWriterTest(Encoding.Default, txtFilePath, numberFomatProvider);
- //StreamWriter
- test.WriteSomthingToFile();
- //TextWriter
- test.WriteSomthingToFileByUsingTextWriter();
- Console.ReadLine();
- }
- }
- ///<summary>
- ///TextWriter和StreamWriter的舉例///</summary>
- publicclassStreamWriterTest
- {
- ///<summary>
- ///編碼///</summary>
- privateEncoding _encoding;
- ///<summary>
- ///IFomatProvider///</summary>
- privateIFormatProvider _provider;
- ///<summary>
- ///文件路徑///</summary>
- privatestring_textFilePath;
- publicStreamWriterTest(Encoding encoding, stringtextFilePath)
- : this(encoding, textFilePath, null)
- {
- }
- publicStreamWriterTest(Encoding encoding, stringtextFilePath, IFormatProvider provider)
- {
- this._encoding = encoding;
- this._textFilePath = textFilePath;
- this._provider = provider;
- }
- ///<summary>
- ///我們可以通過FileStream 或者 文件路徑直接對該文件進行寫操作///</summary>
- publicvoidWriteSomthingToFile()
- {
- //獲取FileStream
- using(FileStream stream = File.OpenWrite(_textFilePath))
- {
- //獲取StreamWriter
- using(StreamWriter writer = newStreamWriter(stream, this._encoding))
- {
- this.WriteSomthingToFile(writer);
- }
- //也可以通過文件路徑和設置bool append,編碼和緩沖區(qū)來構建一個StreamWriter對象
- using(StreamWriter writer = newStreamWriter(_textFilePath, true, this._encoding, 20))
- {
- this.WriteSomthingToFile(writer);
- }
- }
- }
- ///<summary>
- ///具體寫入文件的邏輯///</summary>
- ///<param name="writer">StreamWriter對象</param>
- publicvoidWriteSomthingToFile(StreamWriter writer)
- {
- //需要寫入的數(shù)據(jù)
- string[] writeMethodOverloadType =
- {
- "1.Write(bool);",
- "2.Write(char);",
- "3.Write(Char[])",
- "4.Write(Decimal)",
- "5.Write(Double)",
- "6.Write(Int32)",
- "7.Write(Int64)",
- "8.Write(Object)",
- "9.Write(Char[])",
- "10.Write(Single)",
- "11.Write(Char[])",
- "12.Write(String)",
- "13Write(UInt32)",
- "14.Write(string format,obj)",
- "15.Write(Char[])"
- };
- //定義writer的AutoFlush屬性,如果定義了該屬性,就不必使用writer.Flush方法
- writer.AutoFlush = true;
- writer.WriteLine("這個StreamWriter使用了{0}編碼", writer.Encoding.HeaderName);
- //這里重新定位流的位置會導致一系列的問題//writer.BaseStream.Seek(1, SeekOrigin.Current);
- writer.WriteLine("這里簡單演示下StreamWriter.Writer方法的各種重載版本");
- writeMethodOverloadType.ToList().ForEach
- (
- (name) => { writer.WriteLine(name); }
- );
- writer.WriteLine("StreamWriter.WriteLine()方法就是在加上行結束符,其余和上述方法是用一致");
- //writer.Flush();
- writer.Close();
- }
- publicvoidWriteSomthingToFileByUsingTextWriter()
- {
- using(TextWriter writer = newStringWriter(_provider))
- {
- writer.WriteLine("這里簡單介紹下TextWriter 怎么使用用戶設置的IFomatProvider,假設用戶設置了NumberFormatInfoz.PercentDecimalSeparator屬性");
- writer.WriteLine("看下區(qū)別吧 {0:p10}", 0.12);
- Console.WriteLine(writer.ToString());
- writer.Flush();
- writer.Close();
- }
- }
- }
StreamWriter輸出結果:
TextWriter 輸出結果
相信大家看完這個示例后能對StreamWriter和TextWriter有一個更深的理解
本章總結
本章講述了 TextWriter 和 StreamWriter的一些基本的概念操作和區(qū)別,還有略帶介紹了IFomartProvider接口的基本作用,
由于IFomartProvider也是非常重要的一個接口,我也會單獨寫一篇關于它的博文,至此關于流的一些準備工作已經完成,
下一章節(jié)將正式介紹Stream的子類,也是很關鍵的FileStream類,謝謝大家支持!


2019-06-18 10:31:23
2009-08-25 17:59:49




