使用文本框中的ASCII/UTF8数据在ASCII中编写P6 .ppm.编码混乱

本文关键字:ASCII 混乱 P6 ppm 编码 UTF8 文本 数据 | 更新日期: 2023-09-27 18:14:44

我对我正在编写的小工具的编码有一些普遍的困惑。

首先,我很抱歉下面的代码有点混乱,但是到目前为止,我写的代码中,它是最接近实际工作的。

如果我使用以下代码:

/*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 ?? ?? ?? ??

使用文本框中的ASCII/UTF8数据在ASCII中编写P6 .ppm.编码混乱

ASCII是一个7位编码(字符值0到127)。字符的值大于127,确切的值取决于所使用的编码或代码页。(在代码页1252中,它的值为255)。当ASCII编码试图处理值大于127的字符时,它只写一个问号。

看起来您需要将高ASCII字符(字符值128到255)映射到单个字节。这就排除了使用UTF8, UTF32或UniCode编码,因为它们的GetBytes()方法将为大于127的单个字符值返回多个字节。

要将高ASCII字符映射到单个字节,请尝试像1252或437这样的代码页。如果它们不能提供所需的映射,这里列出了许多其他代码页。

下面是一个使用代码页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);
    }
  }
}