使用 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().
问题描述
我有一个 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().