我正在尝试向log4j传递一个包含ASCII字符的byte[],以便使用明显的表示形式登录到一个文件中。当我只是简单地传入byt[]时,它当然会被当作一个对象来处理,而日志是非常无用的。当我尝试使用new String(byte[] data)
将它们转换为字符串时,我的应用程序的性能降低了一半。
我如何才能有效地传递它们,而不会招致将它们转换为字符串的大约30us的时间惩罚。
另外,为什么转换它们需要这么长时间?
谢谢。
编辑
我应该补充说,我在这里选择了延迟-是的,30us确实是有影响的!此外,这些数组的大小从~100一直到几千字节不等。
发布于 2010-02-05 01:59:39
您想要做的是延迟byte[]数组的处理,直到log4j确定它实际上想要记录消息。这样,您可以在调试级别记录它,例如,在测试时,然后在生产期间禁用它。例如,您可以:
final byte[] myArray = ...;
Logger.getLogger(MyClass.class).debug(new Object() {
@Override public String toString() {
return new String(myArray);
}
});
现在,除非实际记录数据,否则不会造成速度损失,因为直到log4j决定实际记录消息时,才会调用toString方法!
现在我不确定你所说的“明显的表示”是什么意思,所以我假设你的意思是通过将字节重新解释为默认的字符编码来转换为字符串。现在,如果您处理的是二进制数据,这显然是毫无价值的。在这种情况下,我建议使用[Arrays.toString(byte[])](http://java.sun.com/j2se/1.5.0/docs/api/java/util/Arrays.html#toString(byte[]%29)创建如下所示的格式化字符串
[54, 23, 65, ...]
发布于 2010-02-05 02:00:22
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,否则你将以垃圾告终。
发布于 2010-02-05 02:01:25
如果您的数据实际上是ASCII码(即7位数据),那么您应该使用new String(data, "US-ASCII")
而不是依赖于平台默认编码。这可能比试图将其解释为您的平台默认编码(可能是UTF-8,这需要更多自省)更快。
您还可以通过缓存Charset
实例并调用new String(data, charset)
来避免每次命中字符集查找,从而加快速度。
话虽如此:我已经很长时间没有在生产环境中看到真实的ASCII数据了
https://stackoverflow.com/questions/2201930
复制相似问题