Исправление неправильно закодированной строки после факта - PullRequest
0 голосов
/ 25 сентября 2019

Основная проблема и вопрос:

При наличии искаженной строки, для которой известен фактический текст, возможно ли последовательно исправить искаженную строку?

СогласноNyerguds прокомментировал этот ответ :

Если строка является неправильным декодированием, выполненным просто 8-битным кодированием, и у вас есть кодировка, используемая для декодированияэто, вы можете обычно вернуть байты без какого-либо искажения.

(подчеркивает мое)

Что говорит о том, что бывают случаи, когда это не такможно получить исходные байты обратно.Это приводит меня к следующему вопросу: Существуют ли случаи, когда (неправильное) кодирование массива байтов является операцией с потерями и необратимой операцией?

Справочная информация: Я звонювнешняя библиотека C ++, которая где-то вызывает веб-API.Иногда эта библиотека дает мне слегка искаженный текст.В моем проекте на C # я пытаюсь найти способ последовательно обратить неправильное кодирование, но мне кажется, что я могу сделать это только часть времени.

Что я пробовал:

Кажется очевидным, что библиотека C ++ неправильно кодирует исходные байты, которые она позже передает мне в виде строки.Мой подход состоял в том, чтобы угадать кодировку, которую библиотека C ++ использовала для интерпретации исходных байтов источника.Затем я перебираю все возможные кодировки, переосмысливая, мы надеемся, «оригинальные» байты с другой кодировкой.

class TestCase
{
    public string Original { get; set; }
    public string Actual { get; set; }
    public List<string> Matches { get;} = new List<string>();
}

void Main()
{
    var testCases = new List<TestCase>()
    {
        new TestCase {Original = "窶弑-shaped", Actual = "“U-shaped"},
        new TestCase {Original = "窶廡窶・Type", Actual = "“F” Type"},
        new TestCase {Original = "Ko窶冩lau", Actual = "Ko’olau"},
        new TestCase {Original = "窶彗s is", Actual = "“as is"},
        new TestCase {Original = "窶從ew", Actual = "“new"},
        new TestCase {Original = "faテァade", Actual = "façade"}
    };

    var encodings = Encoding.GetEncodings().Select(x => x.GetEncoding()).ToList();
    foreach (var testCase in testCases)
    {
        foreach (var from in encodings)
        {
            foreach (var to in encodings)
            {
                // Guess the original bytes of the string
                var guessedSourceBytes = from.GetBytes(testCase.Original);
                // Guess what the bytes should have been interpreted as
                var guessedActualString = to.GetString(guessedSourceBytes);

                if (guessedActualString == testCase.Actual)
                {
                    testCase.Matches.Add($"Reversed using \"{from.CodePage} {from.EncodingName}\", reinterpreted as: \"{to.CodePage} {to.EncodingName}\"");
                }
            }
        }
    }
}

Results

Как мы видим выше,из шести тестовых случаев все, кроме одного (窶廡窶・) были успешными.В успешных случаях Shift-JIS (кодовая страница 932), казалось, приводил к правильной «исходной» последовательности байтов для UTF8.

Получение байтов Shift-JIS для 窶廡窶・ приводит к: E2 80 9C 46 E2 80 81 45.E2 80 9C совпадает с байтами UTF8 для левой двойной кавычки , что является правильным.Однако E2 80 81 - это em quad в UTF8, а не right double quotation mark, который я ожидаю.Повторная интерпретация всей последовательности байтов в UTF8 приводит к “F EType

Независимо от того, какую кодировку я использую для получения «оригинальных» байтов, и независимо от того, какую кодировку я использую для переинтерпретации упомянутых байтов, кажется, что комбинация не можетчтобы успешно преобразовать 窶廡窶・ в “F”.

Интересно, если я получу байты UTF8 для “F” Type и намеренно неверно интерпретирую эти байты как Shift-JIS, я получу обратно 窶廡窶・Type

Encoding.GetEncoding(932).GetString(Encoding.UTF8.GetBytes("“F” Type"))

Это наводит меня на мысль, что кодировка может на самом деле привести к потере данных.Я не очень хорошо разбираюсь в кодировке, поэтому кто-то может подтвердить, правильно ли сделан мой вывод, и если да, то почему происходит потеря данных?

1 Ответ

1 голос
/ 25 сентября 2019

Да, есть кодировки, которые не поддерживают все символы.Одним из наиболее распространенных примеров является ASCIIEncoding, который заменяет все символы вне стандартного диапазона ASCII на ?.

... Поскольку ASCII является 7-битной кодировкой, ASCIIсимволы ограничены младшими 128 символами Unicode, от U + 0000 до U + 007F.… Символы вне этого диапазона заменяются на знак вопроса (?) перед выполнением операции кодирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...