(轉)C# 溫故而知新:Stream篇(三)

(本文轉自)http://www.cnblogs.com/JimmyZheng/archive/2012/03/25/2416841.html

C# 溫故而知新:Stream篇(

TextWriter 和 StreamWriter

目錄:

  • 爲何介紹TextWriter?
  • TextWriter的構造,常用屬性和方法
  •             IFormatProvider的簡單介紹
  • 如何理解StreamWriter?
  • StreamWriter屬性
  • StreamWriter示例
  • 本章總結

 

 

 

爲何介紹TextWriter?

就像上篇講述的一樣,對於重要的基礎技術,我們一定要刨根問底,這樣在面對將來可能很複雜的業務或技術時才能遊刃有餘,

甚至可以創新出新的解決方案,言歸正傳,想了解StreamWriter 必須瞭解其父親TextWriter的結構和使用方法。

那麼微軟爲什麼要創建立這個抽象類呢?看下圖

   

的確可以這樣理解C,C++ ,XAML,Html一切可以寫在文本上寫的語言都可以用Text這個詞在抽象,(千萬別小看記事本,它纔是元老啊),

聰明的你想到了,今後我們可以自定義一些自己Writer類來實現我們特定的寫功能。現在我們只要理解TextWriter是一個抽象的文本寫入器,

可以在文本上寫入我們想要的格式,可以通過微軟派生類或着自定義派生類來實現TextWriter的功能。只要你有足夠的想象力就能在創新

出一個新的派生類。

 

 

TextWriter的構造,常用屬性和方法

以下是TextWriter構造函數:

和所有的抽象類一樣,該類不能直接實例化,它有2個構造函數

 

特別我想說下第二個構造函數,大家發現這個構造有個IFomatProvider 類型的參數, 這個是什麼東東?

    

IFormatProvider接口的簡單介紹

其實IFormatProvider接口 從字面上就能理解了,一個格式化的提供者

大家記得我們常用的string.format(“{0:P}”,data);麼? IFormatProvider在這裏被隱式的調用了

關於隱式調用的各種方式,用個簡單的例子向大家說明下:

複製代碼
            //有關數字格式化隱性使用IFomatProvider的例子
#if true
//貨幣
Console.WriteLine(string.Format("顯示貨幣格式{0:c3}",12));
//十進制
Console.WriteLine("顯示貨幣十進制格式{0:d10}", 12);
//科學計數法
Console.WriteLine("科學計數法{0:e5}",12);
//固定點格式
Console.WriteLine("固定點格式 {0:f10}",12);
//常規格式
Console.WriteLine("常規格式{0:g10}",12);
//數字格式(用分號隔開)
Console.WriteLine("數字格式 {0:n5}:",666666666);
//百分號格式
Console.WriteLine("百分號格式(不保留小數){0:p0}",0.55);
//16進制
Console.WriteLine("16進制{0:x0}", 12);
// 0定位器 此示例保留5位小數,如果小數部分小於5位,用0填充
Console.WriteLine("0定位器{0:000.00000}",1222.133);
//數字定位器
Console.WriteLine("數字定位器{0:(#).###}", 0200.0233000);
//小數
Console.WriteLine("小數保留一位{0:0.0}", 12.222);
//百分號的另一種寫法,注意小數的四捨五入
Console.WriteLine("百分號的另一種寫法,注意小數的四捨五入{0:0%.00}", 0.12345);
Console.WriteLine("\n\n");
#endif
複製代碼

輸出結果:

也就是說IFormatProvider 提供了一個格式化的工具

讓我們通過NumberFormatInfo類來溫故下:

這個密封類實現了IFormatProvider接口,主要實現了一個數字格式化的類,下面是一些規定的格式說明符:

c、C

貨幣格式。關聯的屬性包括:

d、D

十進制格式。

e、E

科學計數(指數)格式。

f、F

固定點格式。

g、G

常規格式。

n、N

數字格式。

p、P

百分比格式。

                  讓我們用簡單易懂的代碼來實現下NumberFormatInfo 如何使用:

複製代碼
#if true
//顯性使用IFomatProvider
Console.WriteLine("顯性使用IFomatProvider的例子");
//實例化numberFomatProvider對象
NumberFormatInfo numberFomatProvider = new NumberFormatInfo();
//設置該provider對於貨幣小數的顯示長度
numberFomatProvider.CurrencyDecimalDigits = 10;
//注意:我們可以使用C+數字形式來改變provider提供的格式
Console.WriteLine(string.Format(numberFomatProvider, "provider設置的貨幣格式{0:C}", 12));
Console.WriteLine(string.Format(numberFomatProvider, "provider設置的貨幣格式被更改了:{0:C2}", 12));
Console.WriteLine(string.Format(numberFomatProvider, "默認百分號和小數形式{0:p2}", 0.12));
//將小數 “.”換成"?"
numberFomatProvider.PercentDecimalSeparator = "?";
Console.WriteLine(string.Format(numberFomatProvider, "provider設置的百分號和小數形式{0:p2}", 0.12));
Console.ReadLine();
#endif
複製代碼

                 輸出結果:

                 正如上述代碼所表示的,IFormatProvider提供用於檢索控制格式化的對象的機制。我們甚至可以自定義provider類來實現特殊的

                 字符串格式化關於這個重要的知識點我會在另一篇文章中詳細介紹並且自定義一個簡單的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類中一樣,將緩衝區所有數據立刻寫入文件(基礎設備)

*4:Write()方法的重載(這個方法重載太多了,所以這裏就不全寫出了,大家可以參考最後一個例子的打印結果

*5:WriteLine()方法的重載:和Write()方法相比區別在於每個重載執行完畢之後會附加寫入一個換行符

          

 

如何理解StreamWriter?

首先我們先了解下StreamWriter的概念:實現一個 TextWriter,使其以一種特定的編碼向流中寫入字符。

那會有很多朋友會疑惑,StreamWriter和TextWriter有什麼區別?

其實從名字定義我們便可區分了,TextWriter分別是對連續字符系列處理的編寫器,而StreamWriter通過特定的編碼和流的方式對數據進行處理的編寫器

StreamWriter的構造函數

*1:public StreamWriter(string path);

  參數path表示文件所在的位置

*2:public StreamWriter(Stream stream, Encoding encoding);

  參數Stream 表示可以接受stream的任何子類或派生類,Encoding表示讓StreamWriter 在寫操作時使用該encoding進行編碼操作

*3:public StreamWriter(string path, bool append);

 第二個append參數非常重要,當append參數爲true時,StreamWriter會通過path去找當前文件是否存在,如果存在則進行append或overwrite的操作,否則創建新的文件

*4:public StreamWriter(Stream stream, Encoding encoding, int bufferSize);

bufferSize參數設置當前StreamWriter的緩衝區的大小

 

        

StreamWriter的屬性

StreamWriter的方法大多都繼承了TextWriter 這裏就不在重複敘述了,這裏就簡單介紹下StreamWriter獨有的屬性

*1:AutoFlush: 這個值來指示每次使用streamWriter.Write()方法後直接將緩衝區的數據寫入文件(基礎流)

*2:BaseStream: 和StreamReader相似可以取出當前的Stream對象加以處理

 

StreamWriter示例

複製代碼
  const string txtFilePath = "D:\\TextWriter.txt";

static void Main(string[] args)
{

NumberFormatInfo numberFomatProvider = new NumberFormatInfo();
//將小數 “.”換成"?"
numberFomatProvider.PercentDecimalSeparator = "?";
StreamWriterTest test = new StreamWriterTest(Encoding.Default, txtFilePath, numberFomatProvider);
//StreamWriter
test.WriteSomthingToFile();
//TextWriter
test.WriteSomthingToFileByUsingTextWriter();
Console.ReadLine();
}
}

/// <summary>
/// TextWriter和StreamWriter的舉例
/// </summary>
public class StreamWriterTest
{
/// <summary>
/// 編碼
/// </summary>
private Encoding _encoding;

/// <summary>
/// IFomatProvider
/// </summary>
private IFormatProvider _provider;

/// <summary>
/// 文件路徑
/// </summary>
private string _textFilePath;


public StreamWriterTest(Encoding encoding, string textFilePath)
: this(encoding, textFilePath, null)
{

}

public StreamWriterTest(Encoding encoding, string textFilePath, IFormatProvider provider)
{
this._encoding = encoding;
this._textFilePath = textFilePath;
this._provider = provider;
}

/// <summary>
/// 我們可以通過FileStream 或者 文件路徑直接對該文件進行寫操作
/// </summary>
public void WriteSomthingToFile()
{
//獲取FileStream
using (FileStream stream = File.OpenWrite(_textFilePath))
{
//獲取StreamWriter
using (StreamWriter writer = new StreamWriter(stream, this._encoding))
{
this.WriteSomthingToFile(writer);
}

//也可以通過文件路徑和設置bool append,編碼和緩衝區來構建一個StreamWriter對象
using (StreamWriter writer = new StreamWriter(_textFilePath, true, this._encoding, 20))
{
this.WriteSomthingToFile(writer);
}
}
}

/// <summary>
/// 具體寫入文件的邏輯
/// </summary>
/// <param name="writer">StreamWriter對象</param>
public void WriteSomthingToFile(StreamWriter writer)
{
//需要寫入的數據
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();
}

public void WriteSomthingToFileByUsingTextWriter()
{
using (TextWriter writer = new StringWriter(_provider))
{
writer.WriteLine("這裏簡單介紹下TextWriter 怎麼使用用戶設置的IFomatProvider,假設用戶設置了NumberFormatInfoz.PercentDecimalSeparator屬性");
writer.WriteLine("看下區別吧 {0:p10}", 0.12);
Console.WriteLine(writer.ToString());
writer.Flush();
writer.Close();
}

}
}
複製代碼

StreamWriter輸出結果:

TextWriter 輸出結果

相信大家看完這個示例後能對StreamWriter和TextWriter有一個更深的理解

 

本章總結

本章講述了 TextWriter 和 StreamWriter的一些基本的概念操作和區別,還有略帶介紹了IFomartProvider接口的基本作用,

由於IFomartProvider也是非常重要的一個接口,我也會單獨寫一篇關於它的博文,至此關於流的一些準備工作已經完成,

下一章節將正式介紹Stream的子類,也是很關鍵的FileStream類,謝謝大家支持!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章