我正在尋找一種可靠的方法來重置StreamReader以便開始使用,特別是當他的基礎BaseStream以BOM開頭時,但在沒有BOM時也必須工作。創建一個從流開頭讀取的新StreamReader也是可以接受的。當他的BaseStream具有BOM時,將StreamReader返回到開始
可以使用任何編碼創建原始StreamReader,並將detectEncodingFromByteOrderMarks設置爲true或false。另外,可以在讀取之前或之前沒有調用重置。
流可以是隨機文本,以字節0xef,0xbb,0xbf開頭的文件可以是帶有BOM或以有效字符序列開頭的文件(例如,如果ISO-8859-1編碼是使用),取決於StreamReader創建時使用的參數。
我見過other solutions,但是當BaseStream以BOM開始時,它們不能正常工作。 StreamReader會記住它已經檢測到BOM,並且執行讀取操作時返回的第一個字符是特殊的BOM字符。
此外,我可以創建一個新的StreamReader,但我不知道是否將原始StreamReader創建時detectEncodingFromByteOrderMarks設置爲true或設置爲false。
這是我第一次嘗試:
//fails with TestMethod1
void ResetStream1(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr.DiscardBufferedData();
}
//fails with TestMethod2
void ResetStream2(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr = new StreamReader(sr.BaseStream, sr.CurrentEncoding, true);
}
//fails with TestMethod3
void ResetStream3(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr = new StreamReader(sr.BaseStream, sr.CurrentEncoding, false);
}
而這些都是thest方法:
Stream StreamWithBOM = new MemoryStream(new byte[] {0xef,0xbb,0xbf,(byte)'X'});
[TestMethod]
public void TestMethod1() {
StreamReader sr=new StreamReader(StreamWithBOM);
int before=sr.Read(); //reads X
ResetStream(ref sr);
int after=sr.Read();
Assert.AreEqual(before, after);
}
[TestMethod]
public void TestMethod2() {
StreamReader sr = new StreamReader(StreamWithBOM,Encoding.GetEncoding("ISO-8859-1"),false);
int before = sr.Read(); //reads ï
ResetStream(ref sr);
int after = sr.Read();
Assert.AreEqual(before, after);
}
[TestMethod]
public void TestMethod3() {
StreamReader sr = new StreamReader(StreamWithBOM, Encoding.GetEncoding("ISO-8859-1"), true);
int expected = (int)'X'; //no Read() done before reset
ResetStream(ref sr);
int after = sr.Read();
Assert.AreEqual(expected, after);
}
最後,我發現它通過了所有3次測試的解決方案(見我自己的答案) ,但我想看看是否可以採用更加優雅或快速的解決方案。
是的,但不要經常這樣做。 –
這裏的錯誤是什麼?和@HansPassant爲什麼不呢? – PsychoData