我有一个简单的java程序,它取决于输入流。我必须读取一个160 MB的ecg文件,它在普通的jvm上运行完美,但是当我在android中运行这个代码时,它根本无法分配160 MB并关闭我的应用程序。
这是一段剪辑代码:
// reads the ecg file into a stream and stores it in the InputArray
public byte[] readStream() throws IOException{
FileInputStream inputFile = new FileInputStream(getDataPath());
setBytesToSkip(0);
inputFile.skip(getBytesToSkip());
setLengthOfInputFile(inputFile.available());
byte[] InputArray = new byte[getLengthOfInputFile()];
setInputArray(InputArray);
inputFile.read(getInputArray());
inputFile.close();
return inputArray;
}
// writes the bytes of the inputArray into a buffer bb
public ByteBuffer bufferStream(byte[] array){
inputArray = array;
setBufferOffset(0);
setBufferByteReadLength(getLengthOfInputFile());
ByteBuffer bb = ByteBuffer.allocateDirect(getBufferByteReadLength());
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(getInputArray(), getBufferOffset(), getBufferByteReadLength());
return bb;
}
我也尝试使用DirectBuffer超过正常堆但仍然出现memmory错误,如:
dalvikvm-heap PID:1715 Out of memory on a 167230992-byte allocation
有没有办法以更有效的方式处理输入流的数据?或者我可以将一些存储器例如一个sdcard作为“堆”吗?
最好的问候Lorezo
答案 0 :(得分:1)
VM堆将无法分配大小为160 MB的对象,因为许多设备具有32或64 MB堆。尝试循环读取文件(例如4MB块)并跳过下一次迭代中已读取的字节数。
答案 1 :(得分:1)
一般来说,这是错误的做法。这些设备没有足够的内存可供应用程序使用,如果需要,您需要记住,您需要与手机上运行的所有其他应用程序共享该内存。但是,这里有一些我立即注意到的事情。
首先,你试图分配160MB两次!
来到这里:
byte[] InputArray = new byte[getLengthOfInputFile()];
再来一次:
ByteBuffer bb = ByteBuffer.allocateDirect(getBufferByteReadLength());
您可以尝试重新排列此代码,这样就不会分配内存两次。
您还需要在清单中设置android:largeHeap="true"
。