Запись P6 .ppm в ASCII с использованием данных ASCII / UTF8 из Textbox. Кодировка Путаница? - PullRequest
0 голосов
/ 14 ноября 2011

У меня общая путаница с кодировкой небольшого инструмента, который я пишу.

Прежде всего, я прошу прощения за то, что следующий код немного забит, но из кода, который я написал до сих пор, он наиболее близок к реальной работе.

Если я использую следующий код:

/*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 ... -8 версия этих персонажей). Однако, если я полностью честен, это мое первое путешествие в мир кодирования, и я совершенно не понимаю. Поэтому, пожалуйста, дайте мне знать, если я говорю мусор.

Вот пример данных, которые я вставляю в текстовое поле:

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

он должен быть желтым с небольшими черными квадратами везде, но он становится зеленым, и когда файл создается в формате ASCII, данные в конечном итоге выглядят так:

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

1 Ответ

1 голос
/ 14 ноября 2011

ASCII - это 7-битная кодировка (значения символов от 0 до 127).Символ has имеет значение больше 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);
    }
  }
}
...