使用 Inputstream 将二进制数据转换为 long[],同时保持原始顺序

Convert binary data to long[] using Inputstream while mainting original order

问题描述

我有一个 2mb 的文件,其中只包含二进制数据。我只需要将此文件转换为 long[],同时保持数据在该文件中的顺序。由于该文件是在 Android 上读取的,因此我只能以 InputStream 的身份访问该文件。我拼命想要完成的最后一件事(也是我将数据置于压缩二进制数据格式的原因)是尽可能快地完成它。

Android

的工作代码

因为我无法在 android 上获得 File 并且只能使用 resource 并将文件表示为 InputStream 我必须为我的桌面编写以使用InputStream 而不是一个文件。在我的移动旗舰上 phone 使用此代码平均花费 61 毫秒:

DataInputStream dis = new DataInputStream(context.getResources().openRawResource(fileID));
int bytesOfBinaryFile = dis.available();
byte[] bytes = new byte[bytesOfBinaryFile];
dis.readFully(bytes);
int longCount = bytesOfBinaryFile / 8;
long[] array = new long[longCount];
bytesToLongArray(bytes, array);

其中 bytesToLongArray(bytes, array) 为:

private void bytesToLongArray(byte[] bytes, long[] longs) {
    int numberOfLongs = longs.length;
    int head = 0;
    long l;
    for (int i = 0; i < numberOfLongs; i++) {
        l = ((bytes[head] & 0xFFL) << 56) |
                ((bytes[head + 1] & 0xFFL) << 48) |
                ((bytes[head + 2] & 0xFFL) << 40) |
                ((bytes[head + 3] & 0xFFL) << 32) |
                ((bytes[head + 4] & 0xFFL) << 24) |
                ((bytes[head + 5] & 0xFFL) << 16) |
                ((bytes[head + 6] & 0xFFL) <<  8) |
                ((bytes[head + 7] & 0xFFL) <<  0) ;
        longs[i] = l;
        head += 8;
    }
}

类似的桌面工作代码

仅供参考和比较,我包含此代码。我让它在我的桌面上运行得非常快(只需要大约 3.5 毫秒)将 2mb 文件加载到 long[]:

String fileName = "example";
FileInputStream fip = new FileInputStream(fileName);
FileChannel fc = fip.getChannel();
double bytesOfBinaryFile = fc.size();
int longCount = (int) bytesOfBinaryFile / 8;
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY,
        0L, fc.size());
LongBuffer lb = mbb.asLongBuffer(); 
long[] array = long[longCount];
lb.get(array);

问题

不知道有没有人知道更快的方法或者改进我现在方法的方法。我希望性能还有改进的空间。

这可能是您要查找的内容:

 ByteBuffer byteBuffer = ByteBuffer.wrap (byte[] array);
 LongBuffer longBuffer = byteBuffer.asLongBuffer ()
 long[] longArray =  longBuffer.array();

http://developer.android.com/reference/java/nio/ByteBuffer.html#asLongBuffer%28%29

也许这个循环会更快:

for(int i=0; i<bytes.length; ++i) {
  longs[i >> 3] |= (bytes[i] & 0xFFL) <<  ((7-(i & 3))<<3);
}

或者如果你想使用不同的字节顺序 - 第一个字节是 long 中最低的 - 而不是这个(少一个减法运算):

for(int i=0;i<bytes.length;++i) {
  longs[i >> 3] |= (bytes[i] & 0xFFL) <<  ((i & 3)<<3);
}

但请注意,bytes.length 必须能被 8 整除,否则您需要在 longs 数组中增加一个 long。

数组中的 long 也必须初始化为零。但据我所知,它会在您分配数组时自动完成。

全部扔掉,将 InputStream 包裹在 BufferedInputStream, 中,将其包裹在 DataInputStream, 中并使用 readLong().