Open mozikun opened 6 years ago
We probably have to "buffer" files to disk...
I got the error too, Ubuntu Linux, OpenJDK 32bit 1.7, file uploaded is about 500Mb. System mem is 4G
I have the same problem too,hope soon...
I have the same problem too.
origin code:
fbuf = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, randomAccessFile.length());
private String saveTmpFile(ByteBuffer b, int offset, int len, String filename_hint) {
String path = "";
if (len > 0) {
FileOutputStream fileOutputStream = null;
try {
TempFile tempFile = this.tempFileManager.createTempFile(filename_hint);
ByteBuffer src = b.duplicate();
fileOutputStream = new FileOutputStream(tempFile.getName());
FileChannel dest = fileOutputStream.getChannel();
src.position(offset).limit(offset + len);
dest.write(src.slice());
path = tempFile.getName();
} catch (Exception var13) {
throw new Error(var13);
} finally {
NanoHTTPD.safeClose(fileOutputStream);
}
}
return path;
}
origin code 2 can optimization ?? or origin code 1 can optimization ??
I solve this problem ,modify origin code.
//success 随机读写 + buffer. 成功。1G file memory just used 50mb.
public void onCopyOTAFile(RandomAccessFile rafi,String destPath,int offset,int len) throws IOException {
// 2、自己处理Buffer(RandomAccessFile): 0.13s
// String srcFile = "/Users/macpro/Downloads/00111-BXMJ_2G_DVT_2.6.2.63.d.s.d_06240942-ota.zip"; // String destFile = "/Users/macpro/Downloads/copy-BXMJ_2G_DVT_2.6.2.63.d.s.d_06240942-ota.zip"; File file = new File(destPath); if (file.exists())file.delete(); // RandomAccessFile rafi = new RandomAccessFile(srcFile, "r"); RandomAccessFile rafo = new RandomAccessFile(destPath, "rw"); // int len = 1024 1024 1024;//总大小。需要读取的大小 // int offset = 2;//读取的偏移量
int bufferSize = 1024 * 1024;//
byte[] buf = new byte[bufferSize];
long start = System.currentTimeMillis();
try {
rafi.seek(0);
rafi.skipBytes(offset);
int c = 0;
//第一次读取,
if (len <= bufferSize){//读取的总量 < filesize,所以做截取
c = rafi.read(buf,0,len);
}else {
c = rafi.read(buf);
}
int count = c;
while (c > 0) {
//写入
if (c == buf.length) {
rafo.write(buf);
} else {
rafo.write(buf, 0, c);
}
if (count >= len){ //读取,写入完成。
break;
}
//读取
if (count + bufferSize >=len){//读取的总量 < filesize,所以做截取
int currentlen = len - count;
c = rafi.read(buf,0,currentlen);
}else {
c = rafi.read(buf);
}
count = count+c;
}
}catch (Exception e){
e.printStackTrace();
}finally {
rafi.close();
rafo.close();
}
System.out.println("Spend: " + (double) (System.currentTimeMillis() - start) / 1000 + "s");
}
1个 G file oom
channel().map .this method is for get buffer .this buffer for get boundary and real file position. so ,you gan open little buffer.for get real file position.
When I upload 1GB file to android devices by nanohttpd, android devices will OOM.
It maybe that call FileChannel.map() load the 1GB file to ByteBuffer cause out of memory.
How can I fix the problem? Thank you!
ByteBuffer fbuf = null; if (baos != null) { fbuf = ByteBuffer.wrap(baos.toByteArray(), 0, baos.size()); Log.d(TAG, "fbuf1 -- baos != null"); } else {//READ_ONLY fbuf = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, randomAccessFile.length()); randomAccessFile.seek(0); Log.d(TAG, "fbuf2 -- baos == null"); // executed }
09-19 14:10:05.056 W/System.err( 1576): java.io.IOException: mmap failed: ENOMEM (Out of memory)
09-19 14:10:05.071 W/System.err( 1576): at java.nio.MemoryBlock.mmap(MemoryBlock.java:125)
09-19 14:10:05.071 W/System.err( 1576): at java.nio.FileChannelImpl.map(FileChannelImpl.java:257)
09-19 14:10:05.071 W/System.err( 1576): at httpserver.NanoHTTPD$HTTPSession.parseBody(NanoHTTPD.java:1080)