将ASCII byte []转换为String

jwo*_*ard 19 java ascii log4j bytearray

我试图将包含ASCII字符的byte []传递给log4j,使用明显的表示法登录到文件中.当我简单地传入byt []时,它当然被视为一个对象,并且日志非常无用.当我尝试使用它们将它们转换为字符串时new String(byte[] data),我的应用程序的性能减半.

如何有效地传递它们,而不会导致将它们转换为字符串的大约30us时间代价.

另外,为什么转换它们需要这么长时间?

谢谢.

编辑

我应该补充一点,我在这里选择延迟 - 是的,30us确实有所作为!而且,这些数组从~100一直到几千字节不等.

fin*_*nnw 17

ASCII是少数可以转换为UTF16 /从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();
}
Run Code Online (Sandbox Code Playgroud)

但要确保它确实 ASCII,否则你最终会变成垃圾.


Ste*_*ker 14

你想要做的是延迟处理byte []数组,直到log4j确定它实际上想要记录消息.这样,您可以在DEBUG级别将其记录,例如,在测试期间,然后在生产期间禁用它.例如,您可以:

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

现在你不支付速度惩罚,除非你实际记录数据,因为在log4j决定它实际上会记录消息之前不会调用toString方法!

现在我不确定"明显的表示"是什么意思所以我假设您的意思是通过将字节重新解释为默认字符编码来转换为String.现在,如果你正在处理二进制数据,这显然是毫无价值的.在这种情况下,我建议使用Arrays.toString(byte [])来创建一个格式化的字符串

[54, 23, 65, ...]
Run Code Online (Sandbox Code Playgroud)

  • 很好,使用异步记录器可以将转换从关键路径移开. (2认同)

Joa*_*uer 8

如果您的数据实际上是ASCII(即7位数据),那么您应该使用new String(data, "US-ASCII")而不是依赖于平台默认编码.这可能比尝试将其解释为您的平台默认编码(可能是UTF-8,需要更多内省)更快.

您还可以通过缓存Charset实例并调用new String(data, charset)来避免每次Charset-Lookup命中来加快速度.

话虽如此:自从我在生产环境中看到真正的ASCII数据以来,已经很长很长时间了

  • 先生,取决于你所处的生产环境.我每天都看到它. (2认同)