Java: создать строку из массива байтов Latin-1 - PullRequest
3 голосов
/ 11 июля 2020

У меня есть массив byte[], содержащий символы в кодировке Latin-1, и я хочу создать из него Java String.

Я знаю, что могу сделать new String(bytes), но смотрю на реализацию код, он включает запутанные логики c: поиск имени кодировки по умолчанию, выделение декодера, передача байтового массива в декодер. Поэтому я подозреваю, что (по крайней мере, для коротких строк) быстрее работает следующее:

    char[] expanded = new char[bytes.length];
    for (int i=0; i<bytes.length; i++) {
        expanded[i] = (char)(bytes[i] & 0xff);
    }
    return new String(expanded);

Но это тоже не особенно эффективно: конструктор String(char[]) делает копию моего недавно созданного массива char[], просто на случай, если у меня хватит смелости изменить его позже.

Есть комментарии по любому из этих подходов? Есть ли способ лучше? (Примечание: большинство строк будут короткими. И я знаю, что могу провести микробенчмаркинг, и я знаю, что если бы я это сделал, был бы высокий риск получить неправильные ответы ...) `

Ответы [ 3 ]

5 голосов
/ 11 июля 2020

Вы пробовали это?

String str = new String(byteArray, StandardCharsets.ISO_8859_1);
3 голосов
/ 12 июля 2020

Если вы ориентируетесь на современные версии Java, используйте конструктор String(byte[], Charset). Он был сильно оптимизирован и позволит избежать создания объектов кодировщика и временных буферов для наиболее распространенных случаев использования.

new String(bytes, StandardCharsets.ISO_8859_1);

Если вы ориентируетесь на широкий спектр версий Java, включая Java 8 и более ранние используйте устаревший конструктор String(byte[],int):

new String(bytes, 0)

Этот вариант использования - единственная причина, по которой этот конструктор все еще существует и не может быть удален. Это самый быстрый и самый дешевый способ создания строки из байтов ASCII или iso8859-1.

См. Также комментарии в соответствующем отчете об ошибке https://bugs.openjdk.java.net/browse/JDK-6405064

Это правда, что при создании маленьких строк, содержащих только символы ASCII или Latin-1, устаревший конструктор является наиболее эффективным способом. Ряд разработчиков обнаружили этот факт, и поэтому существует критическая зависимость от этих конструкторов для продолжения работы. Это хороший повод для очернения, а не осуждения этих конструкторов. Мы могли бы больше поработать над повышением эффективности поиска Charset и построения String, тем самым избавив разработчиков от необходимости использовать хакерский метод производительности конструктора hibyte.

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

На практике эти конструкторы никогда не снимаются. Слишком много людей закричали бы.

2 голосов
/ 12 июля 2020

Начиная с java -9 существует конструктор, не являющийся publi c, который напрямую устанавливает значение и кодировщик, но это не publi c. Вы можете добраться до него, но, конечно, он может неожиданно сломаться.

    byte[] b = new byte[]{'a'};
    byte coder = 0; // latin_1

    Constructor<String> cons = String.class.getDeclaredConstructor(byte[].class, byte.class);
    cons.setAccessible(true);
    String result = cons.newInstance(b, coder);

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