Преобразуйте Unicode в ASCII, не изменяя длину строки (в Java)

Что лучший способ состоит в том, чтобы преобразовать строку от Unicode до ASCII, не изменяя, это - длина (который очень важен в моем случае)? Также символы без любых проблем преобразования должны быть в тех же позициях как в исходной строке. Таким образом, "Ä" должен быть преобразован в "A" и не что-то загадочное, которое имеет больше символов.

Править:
@novalis - Такие символы (например, азиатских языков) должны просто быть преобразованы в некоторых заполнителей. Я не также интересуюсь теми словами или что они имеют в виду.

@MtnViewMark - Я должен сохранить количество всех символов и положение ASCII доступные символы при любом обстоятельстве.

Здесь еще некоторая информация: у Меня есть некоторые инструменты анализа текста, которые могут только обработать строки ASCII. Большая часть текста, который должен быть обработан, находится на английском языке, но некоторые содержат не символы ASCII. Я не интересуюсь теми словами, но я должен быть уверен, что слова, которыми я интересуюсь (те, которые только содержат символы ASCII) в тех же положениях после преобразования строк.

9
задан Zardoz 19 January 2010 в 20:54
поделиться

4 ответа

Как указано в Это Ответ, следующий код должен Работа:

    String s = "口水雞 hello Ä";

    String s1 = Normalizer.normalize(s, Normalizer.Form.NFKD);
    String regex = "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+";

    String s2 = new String(s1.replaceAll(regex, "").getBytes("ascii"), "ascii");

    System.out.println(s2);
    System.out.println(s.length() == s2.length());

Выход

??? hello A
true

, поэтому сначала вы удалите диабристы, преобразующие в ASCII. Символы без ASCII станут вопросительными знаками.

14
ответ дан 4 December 2019 в 07:47
поделиться

Не видя вашего кода, я не могу быть уверен. Однако пытались ли вы поместить зеленые элементы в тэги и пометить их как четкие: оба;? Это может переместить их в 3-й ряд. Это то, что вы должны проверить.

-121--4716542-

Вот еще один способ, который использует 2-элементный конструктор данных. Для его инициализации не требуется никаких функций. Нет кода третьей стороны (Boost), нет статических функций или объектов, нет трюков, просто C++:

#include <map>
#include <string>

typedef std::map<std::string, int> MyMap;

const MyMap::value_type rawData[] = {
   MyMap::value_type("hello", 42),
   MyMap::value_type("world", 88),
};
const int numElems = sizeof rawData / sizeof rawData[0];
MyMap myMap(rawData, rawData + numElems);

Так как я написал этот ответ C++ 11 вышел. Теперь можно непосредственно инициализировать контейнеры STL с помощью новой функции перечислять инициализатора:

const MyMap myMap = { {"hello", 42}, {"world", 88} };
-121-2005776-

Используйте java.text.Normalizer.normalize () с помощью Normalizer.Form.NFD , а затем отфильтруйте символы, не относящиеся к ASCII.

8
ответ дан 4 December 2019 в 07:47
поделиться

Предостережение: я не знаю Java. Немного о наборах символов.

Вы не указываете, какой именно набор символов вы используете.

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

Единственное известное мне исключение - это строка UTF-8, содержащая только символы ASCII: эта строка уже будет идентична как в UTF-8, так и в ASCII, потому что UTF-8 использует многобайтовые символы только при необходимости. (Я не знаю о других вариантах Unicode, могут быть другие динамические).

Единственный обходной путь, который я вижу, - это добавление пробела к любому специальному символу, который был заменен символом ASCII, но это испортит строку ( Göteborg в UTF8 должно было стать Go теборг , чтобы сохранить длину).

Может быть, вы хотите уточнить, чего вы хотите / должны достичь, чтобы люди здесь могли предложить обходные пути.

2
ответ дан 4 December 2019 в 07:47
поделиться

Одна из проблем с Нормализатором заключается в том, что до Java 1.6 он находится в пакете sun.text, тогда как в 1.6 он находится в пакете java.text, и его подпись метода изменилась. Поэтому, если ваше приложение должно работать на обеих платформах, вам придется использовать отражение.

Альтернативное индивидуальное решение описано как techniwue 3 здесь

2
ответ дан 4 December 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: