我有一个longs
数组我要写入磁盘。最有效的磁盘I / O函数采用字节数组,例如:
FileOutputStream.write(byte[] b, int offset, int length)
...所以我想首先将long[]
转换为byte[]
(每个long
为8个字节)。我很难找到一个干净的方法来做到这一点。
直接类型转换似乎不允许:
ConversionTest.java:6: inconvertible types
found : long[]
required: byte[]
byte[] byteArray = (byte[]) longArray;
^
通过迭代数组很容易进行转换,例如:
ByteBuffer bytes = ByteBuffer.allocate(longArray.length * (Long.SIZE/8));
for( long l: longArray )
{
bytes.putLong( l );
}
byte[] byteArray = bytes.array();
...然而,这似乎远不如简单地将long []视为一系列字节。
有趣的是,当阅读文件时,它很容易被“阉割”#34;从byte[]
到使用Buffers的长期:
LongBuffer longs = ByteBuffer.wrap(byteArray).asLongBuffer();
...但我似乎找不到任何相反方向的功能。
我了解从long
转换为byte
时会有端点注意事项,但我相信我已经解决了这些问题:我使用上面显示的Buffer框架,默认情况下到大端,不管本机字节顺序。
答案 0 :(得分:2)
不,没有一种简单的方法可以从long[]
转换为byte[]
。
您最好的选择可能是将FileOutputStream
包裹在BufferedOutputStream
中,然后为每个byte
写出单独的long
值(使用按位运算符)。
另一种选择是创建ByteBuffer
并将long
值放入ByteBuffer
,然后将其写入FileChannel
。这会为您处理字节顺序转换,但会使缓冲变得更加复杂。
答案 1 :(得分:1)
关于效率,很多细节实际上几乎没有什么区别。到目前为止,硬盘是这里涉及的最慢的部分,并且在将单个字节写入磁盘所需的时间内,您可以将数千甚至数百万字节转换为long。此处的每个性能测试都不会告诉您有关实现的性能的任何信息,而是关于硬盘的性能。有疑问,应该制作专门的基准,比较不同的转换策略,并分别比较不同的写作方法。
假设主要目标是允许方便转换并且不会产生不必要的开销的功能,我想提出以下方法:
可以创建一个足够大小的ByteBuffer
,将其视为LongBuffer
,使用批量LongBuffer#put(long[])
方法(处理必要的字节顺序转换,并将其作为尽管有效,但最后,使用ByteBuffer
将原始long
(现在填充FileChannel
值)写入文件。
遵循这个想法,我认为这种方法很方便,而且(很可能)效率很高:
private static void bulkAndChannel(String fileName, long longArray[])
{
ByteBuffer bytes =
ByteBuffer.allocate(longArray.length * Long.BYTES);
bytes.order(ByteOrder.nativeOrder()).asLongBuffer().put(longArray);
try (FileOutputStream fos = new FileOutputStream(fileName))
{
fos.getChannel().write(bytes);
}
catch (IOException e)
{
e.printStackTrace();
}
}
(当然,有人可能会争论是否分配“大”缓冲区是最好的想法。但是由于Buffer
类的便捷方法,这可以很容易地并且通过合理的努力来修改以写入“块“具有适当大小的数据,对于一个人真的想要写一个巨大的数组并且创建相应的ByteBuffer
的内存开销会非常大)
答案 2 :(得分:0)
OP在这里。
我想到了一种方法:ByteBuffer.asLongBuffer()
返回ByteBufferAsLongBufferB
的实例,这是一个将ByteBuffer包装在接口中的类,用于将数据视为long
在正确管理字节序的同时。我可以扩展ByteBufferAsLongBufferB
,并添加一个方法来返回原始字节缓冲区(protected
)。
但这似乎是如此深奥和令人费解,我觉得必须有一个更简单的方法。无论是那种,还是我的方法中的某些东西都是有缺陷的。