InputStream 必须用 try/catch 捕捉? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Richard14
V2EX    Java

InputStream 必须用 try/catch 捕捉?

  •  
  •   Richard14 2022 年 7 月 18 日 3706 次点击
    这是一个创建于 1372 天前的主题,其中的信息可能已经有所发展或是发生改。

    根据廖雪峰教学文章中提供的代码,

    https://www.liaoxuefeng.com/wiki/1252599548343744/1298069163343905

    我在使用 FileInputStrem 打开和关闭文件时都必须添加 trycatch

    InputStream input = new FileInputStream("src/readme.txt"); input.close() 

    否则编译器就会提示 java: 未报告的异常错误 java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出。这导致一个读取文件的逻辑要三次 trycatch ,非常不优雅。

    根据其后文的描述可以采用

    try (InputStream input = new FileInputStream("src/readme.txt")) { } 

    的方式让编译器自动补全 finally 后的 close ,但是我尝试其代码编译器仍提示必须捕捉 Exception 。

    请问这是由于 jdk 版本不同引发的从错误吗? javaer 正常打开和关闭文件的姿势是什么样的

    21 条回复    2022-07-19 22:31:33 +08:00
    dcsuibian
        1
    dcsuibian  
       2022 年 7 月 18 日
    try{

    }catch(Exception e){
    throw new RuntimeException(e);
    }
    seanzxx
        2
    seanzxx  
       2022 年 7 月 18 日
    正常的呀,Java 有一种叫做 checked exception 的东西,就是一定要处理,否则编译不过
    你这个打开读到的语句至少有两种异常要处理,FileNotFoundException, IOException
    857681664
        3
    857681664  
       2022 年 7 月 18 日
    1. java 的几个关于 ioexception 的都是 checkedException, 需要显示捕获或者在调用方法上声明 throws, 如果觉得分开 3 次 try catch 繁琐,可以把几个 io 操作放一个大的 try catch 里
    2. try-with-resource 语法是 jdk1.7 之后才有的,你可以看一下自己的 jdk 版本是否符合要求,如果是用 IDEA, 看看是否设置了 language level 是不是 1.7+
    chendy
        4
    chendy  
       2022 年 7 月 18 日
    try with resources 是编译器自动补全 finally 后的 close ,并没有补 catch ,所以还是需要自己 catch 的
    Zerek
        5
    Zerek  
       2022 年 7 月 18 日
    有个东西叫做 lombok

    https://blog.51cto.com/attilax2/3655310
    //Lombok ?
    对冗长的 try/catch/finally 的一次包
    清单 6. 使用 @Cleanup 注释
    public static void main(String[] args) throws IOException {
    @Cleanup InputStream in = new FileInputStream(args[0]);
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    //write file code goes here
    }
    Dockerfile
        6
    Dockerfile  
       2022 年 7 月 18 日
    三次 trycatch 是怎么来的?
    像这种文本文件我都是 Files.readString()一把梭

    try (InputStream input = new FileInputStream("src/readme.txt")) {
    }
    这种写法是 try-with-resource, 你用这种就不用手动执行 close 操作了,也只是一次 trycatch 阿,哪来的三次?
    dcsuibian
        7
    dcsuibian  
       2022 年 7 月 18 日   1
    @dcsuibian 转成 RuntimeException 然后抛,或者打印一下日志再抛。留给最上层处理。

    Java 的检查型异常是个没啥用的东西,其它语言都没有采用这种机制( C++:???)。
    最不实用的地方在于:就算你捕获到了这个异常,你也不知道怎么处理。

    网络、文件很容易出问题,但出问题了咋整,再试几次?试过几次还是不行呢?万一在 close 的时候出现异常呢?
    看看那些 ORM 框架、或者文件操作工具库,很明显底层一定会有 IO 操作,但他们就不会在方法上加一堆 throws 。
    XXWHCA
        8
    XXWHCA  
       2022 年 7 月 18 日
    Java 的 io 操作就按着模版代码写吧,没有什么好办法,流读写,关闭输入输出流,三次 try-catch 是最基本的,最多使用 StreamUtil.close(stream)。
    大部分流都是需要 close 的,只有一部分内存流可以忽略,例如 ByteArrayXxxStream ,StringReader 等。
    像文件读写复制什么的,只能靠工具方法来减少模版代码的编写
    matepi
        9
    matepi  
       2022 年 7 月 18 日
    @dcsuibian 要么抓明确的 IOException ,要抓上层就抓 Throwable ,抓 Exception 总感觉会漏

    可以看一下这里,为什么要抓 Throwable
    t/638609
    dcsuibian
        10
    dcsuibian  
       2022 年 7 月 18 日
    @matepi 随手写的,平时用的就是具体异常(反正 try/catch 是 IDE 写的)。

    Exception 比起 Throwable 来说,漏掉的就是 Error 。但 Error 本身就是那些严重到程序员无法处理的错误了。
    [When to catch java.lang.Error?]( https://stackoverflow.com/questions/352780/when-to-catch-java-lang-error)

    我一般将 Error 看作是系统崩坏。
    比如某个接口抛出了 Exception ,我可能还 catch 一下,打个日志,返回个错误信息,至少其它接口还能用。
    而如果捕获到一个 Error ,我认为 jvm 就不可靠了,直接挂了吧。
    aguesuka
        11
    aguesuka  
       2022 年 7 月 18 日   1
    @dcsuibian 可以用 uncheckedioexception, 语义比 RuntimeException 好
    zed1018
        12
    zed1018  
       2022 年 7 月 18 日
    @matepi 在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面
    yungo8
        13
    yungo8  
       2022 年 7 月 18 日 via Android
    v 站大佬多呀,提的问题也都很好,今天又学习到了
    ychost
        14
    ychost  
       2022 年 7 月 18 日
    @SneakThrows 用这个注解
    blankmiss
        15
    blankmiss  
       2022 年 7 月 18 日
    @ychost 这个注解好像是为了骗过编译器来着
    ErnestSu
        16
    ErnestSu  
       2022 年 7 月 19 日
    @zed1018
    在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面
    ---------------------
    调用定制系统的 api ,不一定所有版本有这个实现,所有定制系统的 api ,我都会 catch Throwable
    nothingistrue
        17
    nothingistrue  
       2022 年 7 月 19 日
    try (InputStream input = new FileInputStream("src/readme.txt")) {

    }catch (IOException e){

    }

    这才是正确的用法,因为 try-with-resources 只是自动调用 close (以及将 finally 当中抛出的异常转移到 try 当中抛出), 但不隐藏异常,对于 IOException 这种受检异常,你必须自己处理。
    nothingistrue
        18
    nothingistrue  
       2022 年 7 月 19 日
    @zed1018
    @ErnestSu
    重点不是是否 catch ,是 catch 之后不能即不处理又不 throw 。
    shily
        19
    shily  
       2022 年 7 月 19 日 via iPhone
    kotlin 解君愁
    night98
        20
    night98  
       2022 年 7 月 19 日
    try with resource 的功能是自动关闭流,和异常捕获没有半毛钱关系,在 Java 中受检异常是必须要被处理的,嫌麻烦直接用 hutool 的文件工具类
    ychost
        21
    ychost  
       2022 年 7 月 19 日
    @blankmiss 这个原理是改了你的代码,自动加了 try/catch 并抛了一个 RuntimeException
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     951 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 59ms UTC 21:11 PVG 05:11 LAX 14:11 JFK 17:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86