簡體   English   中英

Java:將long型數組有效地轉換為字節型數組

[英]Java: Efficiently converting an array of longs to an array of bytes

我有多個要寫入磁盤的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 []視為一系列字節有效。

有趣的是,在讀取文件時,很容易使用Buffers將byte[]為long:

LongBuffer longs = ByteBuffer.wrap(byteArray).asLongBuffer();

...但是我似乎找不到找到相反方向的功能。

我了解從longbyte轉換時有字節順序的注意事項,但我相信我已經解決了這些問題:我正在使用上面顯示的Buffer框架,無論本機字節順序如何,該框架默認為big endian。

不,沒有簡單的方法可以將long[]轉換為byte[]

最好的選擇可能是用BufferedOutputStream包裹FileOutputStream ,然后寫出每個long的單個byte值(使用按位運算符)。

另一個選擇是創建一個ByteBuffer並將您的long值放入ByteBuffer ,然后將其寫入FileChannel 這可以為您處理字節順序轉換,但會使緩沖更加復雜。

關於效率,事實上,許多細節幾乎沒有什么不同。 硬盤是迄今為止涉及到的最慢的部分,而且在將單個字節寫入磁盤所需的時間中,您可能已經將數千乃至數百萬個字節轉換為long。 每一個性能測試在這里也不會告訴你的執行表現什么,但對硬盤的性能。 毫無疑問,應該制定專門的基准,分別比較不同的轉換策略和不同的書寫方式。

假設主要目標是一種允許方便轉換且不會造成不必要開銷的功能,我想提出以下方法:

可以創建一個足夠大的ByteBuffer ,將其視為LongBuffer ,使用bulk LongBuffer#put(long[])方法(該方法需要進行字節序轉換,並盡可能有效地做到這一點),以及最后,使用FileChannel將原始ByteBuffer (現在已用long值填充)寫入文件。

遵循這個想法,我認為這種方法很方便並且(很可能)相當有效:

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的內存開銷會非常大)

在這里操作。

想到一個辦法: ByteBuffer.asLongBuffer()返回的實例ByteBufferAsLongBufferB ,它包裝的ByteBuffer在一個接口作為處理數據的類long s,而正確管理字節順序。 可以擴展ByteBufferAsLongBufferB ,並添加一個方法來返回原始字節緩沖區( protected )。

但這似乎深奧而令人費解,我覺得必須有一種更簡單的方法。 要么是這樣,要么是我的方法存在缺陷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM