【问题标题】:how to get the filename of a thrown IOException in java?如何在java中获取抛出的IOException的文件名?
【发布时间】:2017-10-31 11:48:33
【问题描述】:

我有一个 try 块,它可以处理很多文件打开/关闭/读取/写入(多个文件)。

看起来像:

try {
    // commands
}
catch (IOException e) {
    System.err.println("Error: " + e);
}

主要问题是,如果出现错误,e.toString() 不包含有关引发异常的文件名的信息。

我可以分别检查每个读/写/打开/关闭操作,然后知道错误发生在哪个文件上,但这似乎违背了拥有优雅的 try-catch 结构的目的。

还有其他出路吗?我只是希望能够打印在 try 块中 e 出错的文件名。

编辑:也许我应该明确在哪种情况下会出现此问题。当我解析命令行参数、输入/输出文件等时会发生这种情况。我将文件名传递给可能返回 IO 错误的各种函数和方法。要求我通过打印错误和具有该错误的文件名来处理任何文件问题的通用方法似乎是合理的。我知道 IOException 比使用文件处理 IO 更广泛,但考虑到 IOException 是一个专门的异常类,拥有一个返回发生错误的 IO 源的方法肯定是有意义的。

【问题讨论】:

  • 你肯定有 File 范围内的对象。
  • 将每个操作隔离在它自己的 try-catch 块中,而不是尝试使用单个 catch all
  • @MadProgrammer 这听起来更像是问题而不是解决方案。如果有一个单一的包罗万象,它可能会使原始的File 对象仍在范围内。我希望你的意思是嵌套 try-catch,否则你刚刚推荐了一个反模式。
  • @EJP 从问题的声音来看,他们有多个文件被读取和写入 - 但我可能是错的 - 我更喜欢尽可能隔离责任,因为它更容易识别问题并处理它。它们是否嵌套取决于要求,但通常是的......
  • 也许他们让用户选择文件,并且它们处于一个合理的数据结构中,只是碰巧很难读取。例如,一棵树:IOException 可能来自一个文件,但您看到的只是它的祖父目录。

标签: java ioexception


【解决方案1】:

您不知道 - 如您所知,IOException 没有关于生成异常的 File 的信息。它的目的太笼统了。如果您自己滚动,则可以捕获相关信息并捕获您自己的异常。

在处理您的输入的各种方法中,将相关部分包装在 try/catch 块中,捕获 IOException,并使用附加数据抛出您自己的部分。

这是一个完整的程序,演示了基本思想。

class FooException extends Exception { 
    private static final long serialVersionUID = 2816777468035627105L;
    private final String filename; 
    private final Throwable cause; 

    public FooException(String filename) { 
        this(filename, null); 
    }

    public FooException(String filename, Throwable cause) { 
        this.filename = filename; 
        this.cause = cause; 
    }

    @Override
    public String getMessage() { 
        return "Error reading file"; 
    }

    @Override
    public Throwable getCause() {
        return cause; 
    }

    public String getFilename() { 
        return filename; 
    }
}

public class Soj25375647 {    
    public static void main(String[] args) {
         try {
             throwsAnException();
             // Do other things that might throw my exception
         } catch (FooException e) { 
             System.err.printf("File: %s, error: %s, caused by %s%n", e.getFilename(), e, e.getCause());
         }
    }

    public static void throwsAnException() throws FooException { 
        try { 
            int x = 2 / 0;
        } catch (ArithmeticException e) { 
            throw new FooException("bob.file", e);   
        }
    }
}

输出

File: bob.file, error: soj25375647.FooException: Error reading file, caused by java.lang.ArithmeticException: / by zero

另见Exception-Handling Antipatterns

【讨论】:

    【解决方案2】:

    我想我明白这里发生了什么。你可能有这样的事情:

    try {
        for (int i = 0; i < something; i++) {
            File f = getSomeFile(i);
            // Operations that might throw an IOException
        }
    }
    catch (IOException e) {
        // handle
    }
    

    这不是一个好主意;正如您所说,您不知道导致错误的文件。而是尝试这样的事情:

    for (int i = 0; i < something; i++) {
        File f = getSomeFile(i);
        try {
            // Operations that might throw an IOException
        }
        catch (IOException e) {
            // handle
            break;
        }
    }
    

    这样,当错误被抛出时你仍然有f,但它也会像原始代码一样在错误时跳出循环。希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      • 2017-05-24
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多