Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么FileOutputStream不抛出OutOfMemoryException_Java_Io_Buffer - Fatal编程技术网

Java 为什么FileOutputStream不抛出OutOfMemoryException

Java 为什么FileOutputStream不抛出OutOfMemoryException,java,io,buffer,Java,Io,Buffer,我在Windows(64位)和Linux(32位)上都试过下面的代码 我确信,如果没有BufferedOutputStream,代码一定会抛出OfMemoryException,但事实并非如此 为什么呢?谁在那里对磁盘进行{caching/buffer/steaming} 如果与答案相关,您能否描述完整的流程(JavaAPI->系统调用) 这段代码使用NIO吗 /我很困惑 import java.io.DataOutputStream; import java.io.FileOutputStre

我在Windows(64位)和Linux(32位)上都试过下面的代码

我确信,如果没有BufferedOutputStream,代码一定会抛出OfMemoryException,但事实并非如此

为什么呢?谁在那里对磁盘进行{caching/buffer/steaming}

如果与答案相关,您能否描述完整的流程(JavaAPI->系统调用)

这段代码使用NIO吗

/我很困惑

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class WriteHugeFileToDisk {
    private static int BYTE = 1;
    private static int KILBYTE = BYTE * 1024;
    private static int MEGABYTE = KILBYTE * 1024;
    private static int GIGABYTE = MEGABYTE * 1024;
    private static long TERABYTE = GIGABYTE * 1024L;

    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(args[0]);
        DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);

        byte[] buffer = new byte[MEGABYTE];
        for(int i = 0; i < buffer.length; i++) {
            buffer[i] = (byte)i;
        }

        for(long l = 0; l < 4000; l++) {
            dataOutputStream.write(buffer);
            ;
        }

    }
}
Linux:

java WriteHugeFileToDisk /mnt/hi.info

请注意:代码只为测试创建了一个4GB的文件,文件中包含了大量的数据。

为什么它会抛出一个
OutOfMemoryException
?它只是在写磁盘。如果
FileOutputStream
DataOutputStream
有一些缓冲(我没有检查),我不会感到惊讶,但它们肯定不需要缓冲您编写的所有内容

这段代码没有直接使用NIO,尽管如果一些内部内容使用了NIO,我也不会感到惊讶。至于涉及到什么系统调用以及何时-这将是特定于实现的,但重要的是要认识到,无论是
DataOutputStream
还是
FileOutputStream
都不能缓冲所有内容。您向它们写入一些数据,其中一些数据可能会写入磁盘。如果刷新或关闭流,则应使迄今为止写入的所有数据都进入磁盘。如果您不刷新或关闭流,我希望只缓存一小部分(同样是特定于实现的),如果有的话


请注意,
BufferedOutputStream
确实引入了缓存,但只满足您的要求(或默认设置)。同样,它不会缓冲所有内容,除非您要求的缓冲区与您在数据方面写入的缓冲区一样多。

缓冲流是一个流包装器,它(很明显)在将数据传递到底层流之前将数据缓冲到内存中。当与文件流结合使用时,这会提供更好的性能,因为读取或写入硬盘驱动器会带来大量开销。通过将原本效率低下的多个读写操作折叠为一个高效、更大的读写操作,缓冲允许您显著减少读写次数。但是,它对应用程序的良好运行不是至关重要的。它只是帮助您减少对物理设备的访问

Java没有比其他语言更直接地访问计算机的设备。在您的程序和硬盘上的位之间,仍然有几个层有权缓冲或缓存Java拼命从磁盘获取的内容。据我所知,操作系统可以(而且通常会)缓存或缓冲东西,一些硬件也会这样做


在Java操作的意义上,缓冲与对设备或任何流的读写的成功或失败无关。

这两条指令几乎不消耗内存并打开文件句柄

FileOutputStream fileOutputStream = new FileOutputStream(args[0]);
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
为存储在内存中的字节数组分配并填充1MB的数据

byte[] buffer = new byte[MEGABYTE];
for(int i = 0; i < buffer.length; i++) {
    buffer[i] = (byte)i;
}
byte[]buffer=新字节[MB];
for(int i=0;i
将此1MB数据写入输出文件4000次

for(long l = 0; l < 4000; l++) {
    dataOutputStream.write(buffer);
}
for(长l=0;l<4000;l++){
dataOutputStream.write(缓冲区);
}
结论:消耗1MB内存,将4GB数据写入文件。因此,除非您的内存非常少,否则无法抛出
OutOfMemoryException

谁在那里对磁盘进行{caching/buffer/steaming}


没有人。它直接写入磁盘。没有任何增量内存使用。

回答得好,我只想补充一点,缓冲的关键是性能。如果您写入的每个字节最终都是磁盘写入操作,那么速度会很慢。如果在磁盘上缓冲相当于一个块的数据,这将是一个巨大的改进。如果你开始缓冲千兆字节的数据,你就不会再看到每增加一兆字节的缓冲区大小有多大的改进了。@Mattias:True。当然,如果一个写调用已经在写一个兆字节,那么缓冲这些就没有什么意义了。
for(long l = 0; l < 4000; l++) {
    dataOutputStream.write(buffer);
}