Преобразовать байт ASCII [] в строку - PullRequest
18 голосов
/ 04 февраля 2010

Я пытаюсь передать байт [], содержащий символы ASCII, в log4j, чтобы войти в файл, используя очевидное представление. Когда я просто передаю byt [], это, конечно, рассматривается как объект, и журналы довольно бесполезны. Когда я пытаюсь преобразовать их в строки, используя new String(byte[] data), производительность моего приложения уменьшается вдвое.

Как я могу эффективно передать их, не затрачивая примерно 30 мс времени на преобразование их в строки.

Кроме того, почему они так долго конвертируются?

Спасибо.

Редактировать

Я должен добавить, что я предпочитаю задержку здесь - и да, 30us действительно имеет значение! Кроме того, эти массивы варьируются от ~ 100 до нескольких тысяч байт.

Ответы [ 5 ]

17 голосов
/ 04 февраля 2010

ASCII - это одна из немногих кодировок, которая может быть преобразована в / из UTF16 без арифметического или табличного поиска, поэтому возможно преобразование вручную:

String convert(byte[] data) {
    StringBuilder sb = new StringBuilder(data.length);
    for (int i = 0; i < data.length; ++ i) {
        if (data[i] < 0) throw new IllegalArgumentException();
        sb.append((char) data[i]);
    }
    return sb.toString();
}

Но убедитесь, что оно действительно равно ASCII, иначе вы получите мусор.

14 голосов
/ 04 февраля 2010

То, что вы хотите сделать, это отложить обработку массива byte [] до тех пор, пока log4j не решит, что он действительно хочет записать сообщение. Таким образом, вы можете войти в систему на уровне DEBUG, например, во время тестирования, а затем отключить его во время производства. Например, вы могли бы:

final byte[] myArray = ...;
Logger.getLogger(MyClass.class).debug(new Object() {
    @Override public String toString() {
        return new String(myArray);
    }
});

Теперь вы не платите штраф за скорость, если только не регистрируете данные, потому что метод toString не вызывается до тех пор, пока log4j не решит, что он действительно запишет сообщение!

Теперь я не уверен, что вы подразумеваете под «очевидным представлением», поэтому я предположил, что вы имеете в виду преобразование в строку, переосмысливая байты в качестве кодировки символов по умолчанию. Теперь, если вы имеете дело с двоичными данными, это явно бесполезно. В этом случае я бы предложил использовать Arrays.toString (byte []) для создания отформатированной строки по линиям

[54, 23, 65, ...]
8 голосов
/ 04 февраля 2010

Если ваши данные на самом деле являются ASCII (то есть 7-битными данными), то вам следует использовать new String(data, "US-ASCII") вместо того, чтобы использовать кодировку платформы по умолчанию. Это может быть быстрее, чем пытаться интерпретировать его как кодировку по умолчанию для вашей платформы (это может быть UTF-8, требующий большего самоанализа).

Вы также можете ускорить это, избегая попадания Charset-Lookup каждый раз, кэшируя экземпляр Charset и вызывая вместо него new String(data, charset).

Сказав это: прошло очень и очень много времени с тех пор, как я видел реальные данные ASCII в производственной среде

1 голос
/ 04 февраля 2010

Половина производительности? Насколько велик этот байтовый массив? Если это, например, 1 МБ, то, безусловно, нужно учитывать больше факторов, чем просто «преобразование» из байтов в символы (хотя это должно быть достаточно быстро). Запись 1 МБ данных вместо «просто» 100 байт (которые может генерировать byte[].toString()) в файл журнала , очевидно, займет некоторое время. Файловая система диска не так быстра, как оперативная память.

Вам нужно изменить строковое представление массива байтов. Может быть, с более конфиденциальной информацией, например, имя, связанное с ним (имя файла?), его длина и так далее. В конце концов, что этот байтовый массив на самом деле представляет?

Редактировать : Я не помню, чтобы видел фразу "приблизительно 30us" в вашем вопросе, возможно, вы отредактировали ее в течение 5 минут после запроса, но это на самом деле микрооптимизация, и это, конечно, не должно вызывать «снижения производительности» в целом. Если вы не пишете их миллион раз в секунду (все же тогда, зачем вам это делать? Разве вы не злоупотребляете феноменом «регистрации»?).

1 голос
/ 04 февраля 2010
...