繁体   English   中英

将ASCII byte []转换为String

[英]Convert ASCII byte[] to String

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

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

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

谢谢。

编辑

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

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();
}

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

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

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

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

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

[54, 23, 65, ...]

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

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

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

表现减半? 这个字节数组有多大? 如果它是例如1MB,那么肯定有更多的因素需要考虑,而不仅仅是从字节“转换”到字符(虽然它应该足够快)。 1MB数据而不是“仅”100 byte[].toString()byte[].toString() 。toString( byte[].toString()可能生成) 写入日志文件显然需要一些时间。 磁盘文件系统没有RAM内存快。

您需要更改字节数组的字符串表示形式。 也许有一些更敏感的信息,例如与之关联的名称(文件名?),其长度等等。 毕竟,该字节数组实际代表什么?

编辑 :我不记得在你的问题中看过“大约30us”的短语,也许你在询问后的5分钟内编辑了它,但这实际上是微观优化,它一定不会导致“减半的表现”。 除非你每秒写入一百万次(那么,你为什么要这样做呢?难道你没有过度使用“记录”现象吗?)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM