Как мне перевести 8-битные символы в 7-битные? (то есть от Ü до U)

Я ищу псевдокод или пример кода для преобразования старших битовых символов ASCII (например, Ü, который расширен как ASCII 154) в U (который является ASCII 85).

Мое первоначальное предположение состоит в том, что, поскольку существует только около 25 символов ASCII, которые похожи на 7-разрядные символы ASCII, необходимо использовать массив перевода.

Дайте мне знать, если вы можете думать о чем-либо еще.

15 ответов

Решение

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

Используйте iconv, чтобы просто преобразовать вашу входную строку UTF-8 в 7bit ASCII.

В противном случае вы всегда прекратите использовать регистр углов: 8-битный ввод, использующий другую кодовую страницу с другим набором символов (таким образом, вообще не работающий с вашей таблицей преобразования), забыл отобразить последний глупый символ с ударением (вы отобразили все могилы / острый акцент, но забыл нанести на карту чешский карон или скандинавский '°') и т. д.

Конечно, если вы хотите применить решение к небольшой конкретной проблеме (создание файловых файлов, подходящих для файловой системы, для вашей музыкальной коллекции), ищите подходящие массивы (либо массив, который для каждого кода выше 128 отображает приближение ниже 128, как предложено JeeBee, или пары источник / цель, предложенные vIceBerg, в зависимости от того, какие функции подстановки уже доступны на выбранном вами языке), потому что они быстро взламываются вместе и быстро проверяют отсутствие элементов.

Для пользователей.NET статья в CodeProject (благодаря подсказке GvS) действительно отвечает на вопрос более правильно, чем любая другая, которую я видел до сих пор.

Однако код в этой статье (в решении № 1) громоздок. Вот компактная версия:

// Based on http://www.codeproject.com/Articles/13503/Stripping-Accents-from-Latin-Characters-A-Foray-in
private static string LatinToAscii(string inString)
{
    var newStringBuilder = new StringBuilder();
    newStringBuilder.Append(inString.Normalize(NormalizationForm.FormKD)
                                    .Where(x => x < 128)
                                    .ToArray());
    return newStringBuilder.ToString();
}

Чтобы немного расширить ответ, этот метод использует String.Normalize, который:

Возвращает новую строку, текстовое значение которой совпадает с этой строкой, но двоичное представление которой находится в указанной форме нормализации Unicode.

В частности, в этом случае мы используем NormalizationForm FormKD, описанные в тех же документах MSDN как таковые:

FormKD - указывает, что строка Unicode нормализована с использованием декомпозиции полной совместимости.

Для получения дополнительной информации о формах нормализации Unicode, см. Приложение № 15 Unicode.

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

Преобразование Ü в U действительно то, что вы хотели бы сделать? Я не знаю о других языках, но на немецком языке я стал бы Ue, стал бы oe и т. Д.

Я думаю, что вы просто не можете.

Я обычно делаю что-то подобное:

AccentString = 'ÀÂÄÉÈÊ [и все остальные]'
ConvertString = 'AAAEEE [и все остальные]'

Поиск символа в AccentString и замена его на тот же индекс в ConvertString

НТН

В кодовой странице 1251 символы кодируются двумя байтами: один для основного символа и один для варианта. Затем, когда вы кодируете обратно в ASCII, сохраняются только базовые символы.

public string RemoveDiacritics(string text)
{

  return System.Text.Encoding.ASCII.GetString(System.Text.Encoding.GetEncoding(1251).GetBytes(text));

}

От: http://www.clt-services.com/blog/post/Enlever-les-accents-dans-une-chaine-(proprement).aspx

Это действительно зависит от природы ваших исходных строк. Если вы знаете кодировку строки и знаете, что это 8-битная кодировка - например, ISO Latin 1 или аналогичная - тогда достаточно простого статического массива:

static const char xlate[256] = { ..., ['é'] = 'e', ..., ['Ü'] = 'U', ... }
...
new_c = xlate[old_c];

С другой стороны, если у вас другая кодировка или вы используете строки в кодировке UTF-8, вы, вероятно, найдете функции из библиотеки ICU очень полезными.

Вы, кажется, прибили это, я думаю. 128-байтовый массив байтов, индексированный символами &127, содержащий соответствующий 7-битный символ для 8-битного символа.

Верхние 128 символов не имеют стандартных значений. Они могут принимать разные интерпретации (кодовые страницы) в зависимости от языка пользователя.

Например, см. Португальский против французского канадский

Если вы не знаете кодовую страницу, ваш "перевод" иногда будет неправильным.

Если вы собираетесь использовать определенную кодовую страницу (например, исходную кодовую страницу IBM), тогда будет работать массив перевода, но для истинных международных пользователей это будет много неправильно.

Это одна из причин, почему юникод предпочтительнее старой системы кодовых страниц.

Строго говоря, ASCII составляет всего 7 бит.

Хм, а почему бы просто не изменить кодировку строки с помощью iconv?

На CodeProject есть статья, которая выглядит хорошо.

Также меня заинтересовал переход с использованием кодовой страницы 1251 (см. Другой ответ).

Мне не нравятся таблицы преобразования, так как количество символов в Юникоде настолько велико, что вы легко пропускаете один.

Я использую эту функцию, чтобы исправить переменную с ударением, чтобы передать функцию мыла из VB6:

Function FixAccents(ByVal Valor As String) As String

    Dim x As Long
    Valor = Replace(Valor, Chr$(38), "&#" & 38 & ";")

    For x = 127 To 255
        Valor = Replace(Valor, Chr$(x), "&#" & x & ";")
    Next

    FixAccents = Valor

End Function

И внутри функции мыла я делаю это (для переменной Filename):

FileName = HttpContext.Current.Server.HtmlDecode(FileName)

Массив поиска - это, вероятно, самый простой и быстрый способ сделать это. Это один из способов преобразования, скажем, ASCII в EBCDIC.

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

Попробуйте программу uni2ascii.

Другие вопросы по тегам