2011-11-13 2 views
0

У меня есть общее недоумение с кодировкой на маленьком инструменте, который я пишу.Написание P6 .ppm в ASCII с использованием данных ASCII/UTF8 из текстового поля. Кодирование путаницы?

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

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

/*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) до одиночных байтов. Это исключает использование UTF8, UTF32 или UniCode кодировок, так как их 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 уже не существует и не была пуста. Благодарим за предоставленные ссылки на кодовые страницы и ваши объяснения, поэтому это имеет гораздо больше смысла!Я также чувствую, что этот инструмент выиграет от выбора кодировки. Еще раз благодарю вас за то, что вы нашли время ответить на мой вопрос и проделать лишнюю милю, написав очень хороший код C# – chrispepper1989

Смежные вопросы