大家好,我用TCP接收一个大文件,Socket另外一端持续发送Stream,我服务端不断接收并且写入文件,如果文件超过一定大小,例如大于1G,程序就会发生OutofMemoryError错误,内存溢出了,如何解决这个问题呢?下面是接收socket流并且写入文件的代码?请问有什么方法可以避免OutofMemoryError?谢谢
File file = FileHelper.newFile(fileName);
        FileOutputStream fos= new FileOutputStream(file); 
sb.setLength(0);
        while (true) {
                int read = 0;
                if (in != null) {
                    read = in.read(buf);
                }
                passedlen += read;
                if (read == -1) {
                    break;
                }
                sb.append("passedlen|len:"+passedlen+"|"+len+" percentage:" +  String.format("%.5f", passedlen*100.0/len)+ "%\n\r\n");
                System.out.println("percentage:" +  String.format("%.5f", passedlen*100.0/len) + "%\n");
printMessage();
fos.write(buf, 0, read);
}
        if(fos!=null)
        {
         fos.close();
        }outofmemoryerrortcpsocketfile

解决方案 »

  1.   

    这个输出流是会随时写入到硬盘的,看楼主的代码sb是StringBuilder的对象吗?如是的话不要累积append,是不是它溢出了?
      

  2.   

    java.io.InputStream in = ......
    java.io.OutputStream out = .....这里面的 in/out 可以是文件流,字符串流,其他实现此类的流....用法: byte[] buffer = new byte[1024 * n];
     int len = -1;
     while((len = in.read(buffer)) != -1) {
         out.write(buffer,0,len);
     }
     
    这样,不管是 1G 还是 100G 的文件,都不会内存溢出了。 int bytes = in.read(bytes
      

  3.   

    把语句:sb.setLength(0);
    放在循环里试试
      

  4.   

    目测应该是这个passedlen溢出了你每次读完都累加读的个数。当读完之后就是文件的长度,但是由于文件太大了,
    导致这个passedlen超出了int的表示范围,你用long类型的试试
      

  5.   

    看起来像是sb这个对象存的东西太多了,
    如果printMessage()这个方法没有每次都把sb清空的话,
    多半是要内存溢出的,
    建议每次把这种日志存到日志文件或者数据库里,
    不要用一个StringBuffer全部存下来
    如果实在用就设置-Xmx2g,不过这样治标不治本迟早还是会OOM的