【发布时间】: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