驽马十驾 驽马十驾

驽马十驾,功在不舍

目录
踩坑笔记-IO自行控制关闭
/    

踩坑笔记-IO自行控制关闭

开篇

最近翻阅之前代码笔记的时候,发现有1个关于IO关闭的问题可以分享给大家。

大概的业务逻辑是:解析XML后,然后将其移动到另外一个目录备份。

业务很简单,处理正常的XML也是没有问题的,但是测试时候发现,一旦XML解析出现问题,文件无法移动或者删除。

这到底是什么原因造成的了?

业务代码

简单的代码原型如下所示:

public static void main(String[] args) throws DocumentException {
    SAXReader saxReader = new SAXReader();
    File file=new File(" /Users/liuchunfu/GitProject/test.xml");
    Document read = saxReader.read(file);
    //todo something
    boolean delete = file.delete();
    System.out.println(delete);
}

请注意第4句代码:

Document read = saxReader.read(file);

test.xml正常的时候,文件肯定能正常删除。

一旦test.xml解析出问题,文件无法删除。

为什么会出现这个问题?

经过查看dom4j的源码,可以看到它的处理方式为:

public Document read(File file) throws DocumentException {
        try {
            InputSource source = new InputSource(new FileInputStream(file));
            if (this.encoding != null) {
                source.setEncoding(this.encoding);
            }
            String path = file.getAbsolutePath();
            //.....
        }
    }

请注意它的第3句代码:

InputSource source = new InputSource(new FileInputStream(file));

大家看出一点什么问题来没?

new FileInputStream(file) 根本没有关闭?

这个也算它的一个 bug吧,应该在内部将流关闭才好。

解决方法

public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader saxReader = new SAXReader();
        File file=new File(" /Users/liuchunfu/GitProject/test.xml");
        try (FileInputStream fis=new FileInputStream(file)){
            //传入流
            Document read = saxReader.read(fis);
            //todo ....
        } catch (Exception e) {
            e.printStackTrace();
        }
        file.delete();
    }

其实dom4j给我们提供了丰富的 API 其中就有直接传入 流的操作。

启发

当我们使用第三方API的时候,一定要自己留一个心眼,将更多的东西掌握到自己的手里,避免问题发生。

将文件交给第三方 API去进行处理的时候,建议最好自己控制流的关闭。

利用 JDK7 的 try-with-resources 很方便的控制流的操作。

骐骥一跃,不能十步。驽马十驾,功在不舍。