2011-11-13 25 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