新的FileOutputStream很慢,有更好的方法吗?

时间:2014-06-12 15:32:38

标签: java io

我正在写一堆相对较小的文件(每个约50k左右)。

写入所有这些文件的总处理时间约为400秒。

我进行了一些检查,看看花费的时间最多,总共400秒,将数据写入文件花了12秒,花了380秒才完成这段代码:

fos = new FileOutputStream(fileObj);

我希望文件的写入和关闭占用大部分时间,但看起来只是创建FileOutputStream到目前为止花费了大量时间。

有没有更好的方法来创建我的文件或文件创建通常只是一个缓慢的操作?这是数千个文件的总时间,而不仅仅是单个文件的时间。

2 个答案:

答案 0 :(得分:1)

您所看到的是非常正常的行为,而不是特定于Java的行为。

创建文件时,文件系统需要向其结构添加文件条目,并在此过程中修改现有结构(例如包含文件的目录)以记录新条目。

在典型的硬盘上,这需要一些头部移动,单个搜索需要大约几毫秒的时间。另一方面,一旦开始写入文件,文件系统将以线性方式(尽可能长)将新块分配给文件,因此您可以编写大约驱动器可以处理的最大速度的顺序数据。

对速度进行重大改进的唯一方法是使用速度更快的设备(例如SSD驱动器)。

你几乎可以在任何地方观察到这种效果,Windows资源管理器和类似工具都表现出相同的行为:大型文件的复制速度接近设备限制,而大量小文件的速度非常慢。

答案 1 :(得分:-1)

要避免这个问题并在所有文件中花费相同的时间,当您指定文件的路径删除扩展名时,当您完成复制该文件时,请使用之前使用的扩展名重命名该文件。这是一个例子:

public static void copiarArchivo(String pathOrigen, String pathDestino)
{       
    InputStream in = null;
    OutputStream out = null;

    // ultPunto has the index where the last point is in the name of the 
    // file. Before of the last point is the fileName after is the extension 
    int ultPunto = pathDestino.lastIndexOf(".");
    // take the extension of the file
    String extension = pathDestino.substring(ultPunto, pathDestino.length());
    // take the fileName without extension
    String pathSinExtension = pathDestino.substring(0, ultPunto);

    try 
    {
        in = new FileInputStream(pathOrigen);
        // creates the new file without extension cause it is faster as    
        // expleanied below
        out = new FileOutputStream(pathSinExtension);

        byte[] buf = new byte[buffer];
        int len;

        // binary copy of the content file
        while ((len = in.read(buf)) > 0) 
        {
            out.write(buf, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    // when the finished is copyed or and exception occour the streams must 
    // be closed to save resources
    finally
    {
        try 
        {
            if(in != null )
                in.close();
            if(out != null)
                out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    // the file was copyed with out extension and it must be added after the 
    // fileName 
    new File(pathSinExtension).renameTo(new File(pathSinExtension + extension));
}

其中pathOrigen是您要复制的文件的路径,pathDestino是将要复制的路径。