2011-11-13 67 views
0

我正在編寫一個小工具,對編碼有一些普遍的困惑。使用來自Textbox的ASCII/UTF8數據以ASCII格式編寫P6 .ppm。編碼混淆?

首先,我很抱歉下面的代碼是一個小問題,但是我寫的代碼到目前爲止,它是最接近實際工作的代碼。

如果我使用下面的代碼:

/*create file*/ 
FileStream fileS = new FileStream(filename + ".ppm", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 8, FileOptions.None); 
/*create a binary writer*/ 
BinaryWriter bWriter = new BinaryWriter(fileS, Encoding.ASCII); 

/*write ppm header*/ 
string buffer = "P6 "; 
bWriter.Write(buffer.ToCharArray(), 0, buffer.Length); 
buffer = width.ToString() + " "; 
bWriter.Write(buffer.ToCharArray(), 0, buffer.Length); 
buffer = height.ToString() + " "; 
bWriter.Write(buffer.ToCharArray(), 0, buffer.Length); 
buffer = "255 "; 
bWriter.Write(buffer.ToCharArray(), 0, buffer.Length); 

/*write data out*/ 
byte[] messageByte = Encoding.UTF8.GetBytes(ppmDataBox.Text); 
bWriter.Write(messageByte, 0, messageByte.Length); 

/*close writer and bWriter*/ 
bWriter.Close(); 
fileS.Close(); 

那我得到的是保存在UTF-8格式的文件,如果我打開該文件,並將其重新保存爲ASCII我得到的PPM我期待。

但是如果我更改線路:

byte[] messageByte = Encoding.UTF8.GetBytes(ppmDataBox.Text); 

byte[] messageByte = Encoding.ASCII.GetBytes(ppmDataBox.Text); 

然後我得到保存在ASCII格式的文件,但該文件是錯誤的,顏色是錯誤的,基本數據在文件中與文本框中的數據不匹配。

我假設文本框是UTF-8,我粘貼到它的數據實際上是ASCII格式/字符,我首先需要將該ASCII轉換爲其對應的UTF-8 ...(也可以是這些字符的UTF-8版本)。然而,如果我完全誠實,這是我進入編碼世界的第一次冒險,我完全無能爲力。所以請讓我知道我是否在講垃圾。

這裏的是我粘貼到文本框中的數據類型的樣本:

ÿÿ ÿÿ ÿÿ ÿÿ aa aa aa ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ 

它意味着是黃色與黑色小方塊無處不在,但它出來的綠色,並在文件以ASCII格式創建數據最終看起來像這樣:

?? ?? ?? ?? aa aa aa ?? ?? ?? ?? 

回答

1

ASCII是一個7位編碼(字符值0直通127)。 ÿ字符的值大於127,具體值取決於使用哪種編碼或代碼頁。 (在code page 1252它有一個值255)。當ASCII編碼試圖處理一個值大於127的字符時,它只是寫一個問號。

看起來您需要將高位ASCII字符(字符值128到255)映射到單個字節。這排除了使用UTF8UTF32UniCode編碼,因爲他們的GetBytes會()方法用於單個字符值大於127

要映射高ASCII字符單字節,嘗試像1252或代碼頁將返回多個字節437。如果那些沒有給出所需的映射,那麼列出的許多其他代碼頁here

下面是使用代碼頁1252的例子:

using System; 
using System.IO; 
using System.Text; 

namespace ConsoleApplication6 
{ 
    public class Program 
    { 
    public static void Main(String[] args) 
    { 
     (new Program()).Run(); 
    } 

    public void Run() 
    { 
     this.SaveData(@"c:\temp\test.ppm", "ÿÿ ÿÿ ÿÿ ÿÿ aa aa aa ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿ", 100, 200, Encoding.GetEncoding(1252)); 
    } 

    private void SaveData(String filename, String data, Int32 width, Int32 height, Encoding encoding) 
    { 
     const Int32 bufferSize = 2048; 

     Directory.CreateDirectory(Path.GetDirectoryName(filename));  

     if (Path.GetExtension(filename).ToLower() != ".ppm") 
     filename += ".ppm"; 

     using (var fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize)) 
     { 
     using (var bw = new BinaryWriter(fs, encoding)) 
     { 
      var buffer = encoding.GetBytes(this.GetHeader(width, height)); 
      bw.Write(buffer); 

      buffer = encoding.GetBytes(data); 
      bw.Write(buffer); 
     } 
     } 
    } 

    private String GetHeader(Int32 width, Int32 height) 
    { 
     return String.Format("P6 {0} {1} 255 ", width, height); 
    } 
    } 
} 
+0

此代碼非常完美,並且也很寫得很好我想補充:)。我改變的唯一的事情是: 我添加了bw.close()和fs.close(), 檢查了dir字符串didnt已經存在並且不是空的。 感謝您提供代碼頁的鏈接和您的解釋,這使得現在更有意義!我也感覺這個工具會從編碼選擇中受益。 再次感謝您花時間回答我的問題,並通過撰寫一些非常好的C#代碼來加倍努力 – chrispepper1989