【问题标题】:Java stream - too many open filesJava 流 - 打开的文件太多
【发布时间】:2017-03-28 13:09:55
【问题描述】:

我有一个程序会不时转到几个目录,并对这些目录中的文件进行某种处理。

问题是程序有时(每两天或三天)达到操作系统打开文件的限制。

它是一个在 RHEL 7 中运行的 spring-boot 应用程序。

获取文件的方法是这样的:

public File[] getFiles(String dir, int numberOfFiles) throws Exception {
    final Path baseDir = Paths.get(dir);
    List<File> filesFromPath = new ArrayList<File>();
    File[] files = null;

    final BiPredicate<Path, BasicFileAttributes> predicate = (path, attrs) -> attrs.isRegularFile()
            && String.valueOf(path).endsWith(".xml");

    List<Path> result;

    try (Stream<Path> fileStream = Files.find(baseDir, 1, predicate).limit(numberOfFiles).onClose(() -> LOG.debug("Closing file stream."))){
        result = fileStream.collect(Collectors.toList());

        result.forEach(path -> {
            path.toString();
            File file = path.toFile();
            LOG.info("adding {} to process.", file.getName());
            filesFromPath.add(file);
        });

        if (filesFromPath != null && !filesFromPath.isEmpty()) {
            files = filesFromPath.toArray(new File[filesFromPath.size()]);
        }

    } catch (Exception e) {
        LOG.error("Error during file opening/closing", e);
    }

    if (files != null) {
        return files;
    }

    return new File[0];
}

我正在使用 lsof 命令查看我有多少打开的文件,并且目录列表一直在增长。

我在 onClise 方法中添加了一个日志,并且每次打开流时都会调用它。

不应该尝试资源,关闭流吗?

[编辑]

还有另一种将处理后的文件移动到另一个文件夹的代码和平。这段代码没有使用流,除了丑陋之外,我找不到它有什么问题。

public void move(File file, String archivePath) throws IOException {
    File backupFile = new File(archivePath);
    if (!backupFile.exists()) {
        backupFile.mkdirs();
    }

    Path source = file.toPath();
    if (file.exists()) {
        Path target = Paths.get(archivePath + File.separator + file.getName());
        Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
        LOG.info("file {} moved to {}", file, archivePath);
    } else {
        LOG.info("unable to move the file: {} because it was already moved to {}", file, archivePath);
    }
}

[编辑 2]

所有文件都是这样处理的:

private void processFile(File[] files) throws Exception {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    XPath xpathParser = XPathFactory.newInstance().newXPath();

    for (int i = 0; i < files.length; i++) {

        File file = files[i];


        Document doc = db.parse(file);

        // DO STUFF
        fileUtils.move(file, processedPath);

    }

}

谢谢。

【问题讨论】:

  • 提供的代码中没有打开任何资源。您的问题出在其他地方。
  • “不应该尝试资源,关闭流吗?”只有当它退出时。你可能会在 try/catch 中打开很多文件。
  • 杰伊,我编辑了原始问题并添加了另一种方法。系统中没有更多处理文件的地方了。。谢谢你的回答。
  • 一定有别的地方,因为在你的第二个代码 sn-p 中没有调用 getFiles()。
  • getFiles() 在很多地方被调用。但是由于它返回一个 File[] 并且 File 没有“close()”,我到底应该怎么做呢?过程是:一旦我们从 getFiles() 接收到 File[],我们就会处理这些文件并调用 move() 将文件发送到新的目的地。

标签: java java-stream


【解决方案1】:

我遇到了同样的问题。在调用“解析”的情况下,打开了很多文件,我清楚地看到实现打开了一个输入流,但在失败的情况下可能不会关闭它。

【讨论】:

  • 这没有提供问题的答案。
猜你喜欢
  • 2013-04-02
  • 2015-12-17
  • 2011-06-29
  • 2011-09-10
  • 2011-05-16
  • 2012-08-14
  • 2015-10-28
  • 2013-11-15
相关资源
最近更新 更多