Java FileOutputStream.close在写入大文件时速度非常慢

Java FileOutputStream.close在写入大文件时速度非常慢,java,fileoutputstream,Java,Fileoutputstream,我有一个通过TCP套接字接收文件的方法,使用以下代码: FileOutputStream fileStream = new FileOutputStream(filename.getName()); while (totalRead < size) { if (size - totalRead > CHUNKSIZE) { read = getInputStream().read(buffer, 0, CHUNKSIZE); } else {

我有一个通过TCP套接字接收文件的方法,使用以下代码:

FileOutputStream fileStream = new FileOutputStream(filename.getName());
while (totalRead < size) {
    if (size - totalRead > CHUNKSIZE) {
        read = getInputStream().read(buffer, 0, CHUNKSIZE);
    } else {
        read = getInputStream().read(buffer, 0, size - totalRead);
    }
    totalRead += read;
    fileStream.write(buffer, 0, read);
    fileStream.flush();

    if (System.currentTimeMillis() > nextPrint) {
        nextPrint += 1000;
        int speed = (int) (totalRead / (System.currentTimeMillis() - startTime));
        double procent = ((double)totalRead / size) * 100;
        gui.setStatus("Reciving: " + filename + " at " + speed + " kb/s, " + procent + "% complete");
    }
}
gui.setStatus("Reciving: " + filename + " complete.");
fileStream.close();
FileOutputStream fileStream=newfileoutputstream(filename.getName());
while(总读取<大小){
if(大小-totalRead>CHUNKSIZE){
read=getInputStream().read(缓冲区,0,CHUNKSIZE);
}否则{
read=getInputStream().read(缓冲区,0,大小-totalRead);
}
totalRead+=读取;
写入(缓冲区,0,读取);
flush();
if(System.currentTimeMillis()>nextPrint){
nextPrint+=1000;
int速度=(int)(totalRead/(System.currentTimeMillis()-startTime));
双进程=((双)总读取/大小)*100;
设置状态(“接收:“+filename+”以“+speed+”kb/s,“+procent+%完成”);
}
}
setStatus(“接收:“+filename+“complete”);
fileStream.close();

FileOutputStream.close在接收大文件时花费了很长时间,为什么?正如您所见,我正在刷新每个接收到的数据块的流。

取决于操作系统,
flush()
不再强制将数据写入操作系统。对于FileOutputStream,write()将所有数据传递给操作系统,因此flush()不执行任何操作。其中as
close()
可确保文件实际写入磁盘(或不取决于操作系统)。您可以在写入数据时查看磁盘是否仍处于繁忙状态

500 MB文件占用30秒意味着您正在以17 MB/s的速度写入。这听起来像是一个非常慢的磁盘,或者文件在网络共享/驱动器上


你可以试试这个

File file = File.createTempFile("deleteme", "dat"); // put your file here.
FileOutputStream fos = new FileOutputStream(file);
long start = System.nanoTime();
byte[] bytes = new byte[32 * 1024];
for (long l = 0; l < 500 * 1000 * 1000; l += bytes.length)
    fos.write(bytes);
long mid = System.nanoTime();
System.out.printf("Took %.3f seconds to write %,d bytes%n", (mid - start) / 1e9, file.length());
fos.close();
long end = System.nanoTime();
System.out.printf("Took %.3f seconds to close%n", (end - mid) / 1e9);

你可以从这个系统的速度上看出,即使是在关闭的时候,它也不会写入数据。i、 e.驱动器没有那么快。

我看到了使用filestream时的情况。我发现,如果您以读写方式打开文件,它会缓存所有内容,直到您关闭或处置文件后才会写入。弗拉什没有写信。但是,如果写入扩展了文件的大小,它将自动刷新


每次写入时仅以写入自动刷新方式打开。

真正的长时间是多长?如果在close()之前查看操作系统中的文件大小,它是什么样子的?当收到500Mb文件时,close大约需要30秒。我在接收文件时可以看到文件“增长”,因此每次刷新时它都会写入磁盘。但是,在调用close之前,它的最终大小是否正确?我的猜测是,在操作系统级别,它并没有真正刷新它,但我不能肯定。您的复制循环比必要的复杂得多。您所需要的只是“while((count=in.read(buffer))>0)out,write(buffer,0,count);”
flush()
FileOutputStream
不执行任何操作。它只在缓冲流上有用。啊,这是有意义的。当我在家里尝试同样的代码时,close()只花了几分之一秒,所以我猜学校的“问题”是因为网络挂载的家庭文件夹。不,
FileOutputStream.close
不能保证所有字节都被正确写入磁盘。但您可以保证所有字节都写入操作系统缓冲区。如果操作系统崩溃(如电源故障),则已从close()返回的FileOutputStream可能会丢失数据。如果关闭了该文件,程序可能会死机,除非出现其他问题,否则不会丢失数据。
Took 0.116 seconds to write 500,006,912 bytes
Took 0.002 seconds to close