關於BinaryReader讀取資料:在建構函式中指定編碼格式

來源:互聯網
上載者:User

問題描述:使用BinaryReader從檔案中讀取資料,開始在建立BinaryReader執行個體的時候,未指定編碼格式,結果能通過編譯,但是能在執行過程中會報錯如下:“未處理的異常:  System.ArgumentException: 輸出字元緩衝區太小,無法包含解碼後的字元,編碼“Unicode (UTF-8)”的操作回退“System.Text.DecoderReplacementFallback”。”

 

解決過程:

  首先附上建立檔案的代碼:

BinaryWriter

 1 using System;
 2 using System.IO;
 3 
 4 class binaryReader
 5 {
 6     static void Main ()
 7     {
 8         FileInfo f = new FileInfo("BinFile2.dat");
 9         BinaryWriter bw = new BinaryWriter(f.OpenWrite());
10 
11         Console.WriteLine("Base Stream is : {0}",bw.BaseStream);
12         
13         double aDouble = 1234.67;
14         int anInt = 32141;
15         char[] aCharArray = {'A','B','C'};
16         string aString = @"teststring";
17 
18         bw.Write(aDouble);
19         bw.Write(anInt);
20         bw.Write(aCharArray);
21         bw.Write(aString);
22         bw.Close();
23 
24     }
25 }

  然後附上BinaryReader測試代碼:

BinaryReader

 1 using System;
 2 using System.IO;
 3 using System.Text;
 4 
 5 class binaryReader
 6 {
 7     static void Main()
 8     {                
 9         FileInfo f2 = new FileInfo("BinFile2.dat");
10 
11                 BinaryReader br = new BinaryReader(f2.OpenRead());
12         //BinaryReader br = new BinaryReader(f2.OpenRead(),Encoding.Default);
13 
14         int temp = 0;
15         
16         while (br.PeekChar() != -1)
17         
18         {
19             Console.Write("{0,7:x}",br.ReadByte());
20 
21             if (++temp == 4)
22             {
23                 Console.WriteLine();
24                 temp = 0;
25             }
26             
27         }
28         Console.WriteLine();
29     }
30 }

  還有錯誤提示:

  由上,之輸出第一字元的16進位編碼,剩下的就開始報錯。但是覺得“字元緩衝區太小”是個很詭異的錯誤,然後就在網上搜了下,看看別人是怎麼做的。

  第一次,在CSDN上看見有人給出瞭解決的方案,如題目所言,在建立BinaryReader執行個體的時候,指定其編碼方式,就像上面代碼中注釋掉的那一行那樣,就能夠解決問題,將所有字元的16進位編碼正常輸出。

  這樣,問題首先集中到編碼上。預設的編碼方式有問題,必須指定,才能避免錯誤。那什麼樣的編碼是可行的,什麼樣的編碼有問題?在Encoding裡面,枚舉了六種編碼方式:UTF7、UTF8、Unicode、BigEndianUnicode、UTF32和Default。要說的是這裡的Default是指:System.Text.DBCSCodePageEncoding。接下來,我做了一個測試,枚舉每一種編碼方式,在上面的代碼中挨個試一遍。結果發現,在我寫的那個BinFile2.dat測試檔案上,除了UTF-8運行失敗外,其他的每種方式都是成功的(此處省略)。那麼,就可以推斷,不帶編碼指定的BinaryReader的建構函式預設使用的是UTF-8的編碼,而這樣在讀取過程中試有問題的。

  現在,至少知道用該用那種編碼了。

  問題再進一步,在函數塊內部,在讀取檔案的過程中,是哪個函數調用對編碼有“苛刻”的要求?在上面的函數塊中,只包含兩個方法的調用,一個是while語句中的PeekChar(),一個是Console.WriteLine()。我覺得後者的可能性不大,於是做了如下的測試:

BinaryReader2

 1 using System;
 2 using System.IO;
 3 using System.Text;
 4 
 5 class binaryReader
 6 {
 7     static void Main()
 8     {                
 9         FileInfo f2 = new FileInfo("BinFile2.dat");
10 
11         BinaryReader br = new BinaryReader(f2.OpenRead(),Encoding.Default);
12         int temp = 0;
13         int count=20;
14         while (count>0)
15         {
16             Console.Write("{0,7:x}",br.ReadByte());
17 
18             if (++temp == 4)
19             {
20                 Console.WriteLine();
21                 temp = 0;
22             }
23             
24                         count--;
25         }
26         Console.WriteLine();
27     }
28 }

  結果,除了沒能完全輸出字元之外,運行正常,於是,問題集中在了PeekChar()上面。上面用它來判斷檔案的邊界,MSDN中描述“下一個可用的字元,或者,如果沒有可用字元或者流不支援尋找時為 -1。”也就是說,PeekChar()在判斷是否到邊界的過程中,有一個預讀的過程,結合上面的編碼的問題,可以猜測,在它預讀的時候由於編碼的不合適,導致在該方法內部的緩衝區的溢出。

  又在網上找到一文《不要使用PeekChar()判斷EOF》,文中只是說不要用PeekChar來判斷EOF,而是使用判斷條件 ( br.BaseStream.Position < br.BaseStream.Length),但是並沒有給出詳細的理由。

 

   而後,又發現了老外也在討論這個問題:http://bytes.com/topic/visual-basic-net/answers/349779-binaryreader-peekchar-argumentexception-conversion-buffer-overflow

  ……

  繼續深入下去,有兩個點要解決:1、UTF-8編碼的問題;2、PeekChar的工作詳細細節。

總結:通過以上的一系列做法,對BinaryReader的使用有了一些粗淺的瞭解,在使用過程中,能夠合理利用,避開容易出錯的地方,但是,根本的問題還未能真正解決。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

      更深入的明日再續。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.