Mad*_*ist 9 java performance file-io android endianness
我需要将一个由4字节整数(小端)组成的二进制文件读入我的Android应用程序的2D数组中.我目前的解决方案如下:
DataInputStream inp = null;
try {
inp = new DataInputStream(new BufferedInputStream(new FileInputStream(procData), 32768));
}
catch (FileNotFoundException e) {
Log.e(TAG, "File not found");
}
int[][] test_data = new int[SIZE_X][SIZE_Y];
byte[] buffer = new byte[4];
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
for (int i=0; i < SIZE_Y; i++) {
for (int j=0; j < SIZE_X; j++) {
inp.read(buffer);
byteBuffer = ByteBuffer.wrap(buffer);
test_data[j][SIZE_Y - i - 1] = byteBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
}
}
Run Code Online (Sandbox Code Playgroud)
这对于2k*2k阵列来说非常慢,大约需要25秒.我可以在DDMS中看到垃圾收集器正在加班,所以这可能是缓慢的原因之一.
必须有一种更有效的方法来使用ByteBuffer将该文件读入数组,但我现在还没有看到它.关于如何提高速度的任何想法?
Mal*_*olm 12
为什么不读入4字节缓冲区然后手动重新排列字节?它看起来像这样:
for (int i=0; i < SIZE_Y; i++) {
for (int j=0; j < SIZE_X; j++) {
inp.read(buffer);
int nextInt = (buffer[0] & 0xFF) | (buffer[1] & 0xFF) << 8 | (buffer[2] & 0xFF) << 16 | (buffer[3] & 0xFF) << 24;
test_data[j][SIZE_Y - i - 1] = nextInt;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,假设read读取所有四个字节,但是当它不是时,你应该检查情况.这样你就不会在阅读过程中创建任何对象(因此垃圾收集器没有任何压力),你不会调用任何东西,你只需使用按位操作.
如果您使用的是支持内存映射文件的平台,请考虑使用MappedByteBuffer和来自java.nio的朋友
FileChannel channel = new RandomAccessFile(procData, "r").getChannel();
MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, 4 * SIZE_X * SIZE_Y);
map.order(ByteOrder.LITTLE_ENDIAN);
IntBuffer buffer = map.asIntBuffer();
int[][] test_data = new int[SIZE_X][SIZE_Y];
for (int i=0; i < SIZE_Y; i++) {
for (int j=0; j < SIZE_X; j++) {
test_data[j][SIZE_Y - i - 1] = buffer.get();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您需要跨平台支持或者您的平台缺少内存映射缓冲区,您可能仍希望避免使用IntBuffer自行执行转换.考虑删除BufferedInputStream,自己分配更大的ByteBuffer并获取数据的little-endian IntBuffer视图.然后在循环中将缓冲区位置重置为0,使用DataInputStream.readFully将大区域一次读入ByteBuffer,并将int值从IntBuffer中拉出.
| 归档时间: |
|
| 查看次数: |
12940 次 |
| 最近记录: |