how2j.cn


工具版本兼容问题
所有的流,无论是输入流还是输出流,使用完毕之后,都应该关闭。 如果不关闭,会产生对资源占用的浪费。 当量比较大的时候,会影响到业务的正常开展。
纠

本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



6分37秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器



步骤 1 : 在try中关闭   
步骤 2 : 在finally中关闭   
步骤 3 : 使用try()的方式   
步骤 4 : 练习-关闭流   
步骤 5 : 答案-关闭流   

在try的作用域里关闭文件输入流,在前面的示例中都是使用这种方式,这样做有一个弊端;
如果文件不存在,或者读取的时候出现问题而抛出异常,那么就不会执行这一行关闭流的代码,存在巨大的资源占用隐患。 不推荐使用
package stream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { try { File f = new File("d:/lol.txt"); FileInputStream fis = new FileInputStream(f); byte[] all = new byte[(int) f.length()]; fis.read(all); for (byte b : all) { System.out.println(b); } // 在try 里关闭流 fis.close(); } catch (IOException e) { e.printStackTrace(); } } }
步骤 2 :

在finally中关闭

edit 顶 折
这是标准的关闭流的方式
1. 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
2. 在finally关闭之前,要先判断该引用是否为空
3. 关闭的时候,需要再一次进行try catch处理

这是标准的严谨的关闭流的方式,但是看上去很繁琐,所以写不重要的或者测试代码的时候,都会采用上面的有隐患try的方式,因为不麻烦~
package stream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { File f = new File("d:/lol.txt"); FileInputStream fis = null; try { fis = new FileInputStream(f); byte[] all = new byte[(int) f.length()]; fis.read(all); for (byte b : all) { System.out.println(b); } } catch (IOException e) { e.printStackTrace(); } finally { // 在finally 里关闭流 if (null != fis) try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
步骤 3 :

使用try()的方式

edit 顶 折
把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
这种编写代码的方式叫做 try-with-resources, 这是从JDK7开始支持的技术

所有的流,都实现了一个接口叫做 AutoCloseable,任何类实现了这个接口,都可以在try()中进行实例化。 并且在try, catch, finally结束的时候自动关闭,回收相关资源。
package stream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class TestStream { public static void main(String[] args) { File f = new File("d:/lol.txt"); //把流定义在try()里,try,catch或者finally结束的时候,会自动关闭 try (FileInputStream fis = new FileInputStream(f)) { byte[] all = new byte[(int) f.length()]; fis.read(all); for (byte b : all) { System.out.println(b); } } catch (IOException e) { e.printStackTrace(); } } }
步骤 4 :

练习-关闭流

edit 顶 折  姿势不对,事倍功半! 点击查看做练习的正确姿势
把 拆分文件 中关闭流的风格,修改成 finally 方式

把 合并文件 中关闭流的风格,修改成 try() 方式
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费3个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费3个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

3分36秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


package stream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; public class TestStream { public static void main(String[] args) { int eachSize = 100 * 1024; // 100k File srcFile = new File("d:/eclipse.exe"); // splitFile(srcFile, eachSize); } /** * 拆分的思路,先把源文件的所有内容读取到内存中,然后从内存中挨个分到子文件里 * * @param srcFile * 要拆分的源文件 * @param eachSize * 按照这个大小,拆分 */ private static void splitFile(File srcFile, int eachSize) { if (0 == srcFile.length()) throw new RuntimeException("文件长度为0,不可拆分"); byte[] fileContent = new byte[(int) srcFile.length()]; // 为了在finally中关闭,需要声明在try外面 FileInputStream fis = null; try { fis = new FileInputStream(srcFile); fis.read(fileContent); } catch (IOException e) { e.printStackTrace(); } finally { // 在finally中关闭 try { if(null!=fis) fis.close(); } catch (IOException e) { e.printStackTrace(); } } int fileNumber; if (0 == fileContent.length % eachSize) fileNumber = (int) (fileContent.length / eachSize); else fileNumber = (int) (fileContent.length / eachSize) + 1; for (int i = 0; i < fileNumber; i++) { String eachFileName = srcFile.getName() + "-" + i; File eachFile = new File(srcFile.getParent(), eachFileName); byte[] eachContent; if (i != fileNumber - 1) eachContent = Arrays.copyOfRange(fileContent, eachSize * i, eachSize * (i + 1)); else eachContent = Arrays.copyOfRange(fileContent, eachSize * i, fileContent.length); // 为了在finally中关闭,声明在try外面 FileOutputStream fos = null; try { fos = new FileOutputStream(eachFile); fos.write(eachContent); System.out.printf("输出子文件%s,其大小是%,d字节%n", eachFile.getAbsoluteFile(), eachFile.length()); } catch (IOException e) { e.printStackTrace(); } finally { // finally中关闭 try { if(null!=fos) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 合并的思路,就是从eclipse.exe-0开始,读取到一个文件,就开始写出到 eclipse.exe中,直到没有文件可以读 * * @param folder * 需要合并的文件所处于的目录 * @param fileName * 需要合并的文件的名称 * @throws FileNotFoundException */ private static void murgeFile(String folder, String fileName) { File destFile = new File(folder, fileName); // 使用try-with-resource的方式自动关闭流 try (FileOutputStream fos = new FileOutputStream(destFile);) { int index = 0; while (true) { File eachFile = new File(folder, fileName + "-" + index++); if (!eachFile.exists()) break; // 使用try-with-resource的方式自动关闭流 try (FileInputStream fis = new FileInputStream(eachFile);) { byte[] eachContent = new byte[(int) eachFile.length()]; fis.read(eachContent); fos.write(eachContent); fos.flush(); } System.out.printf("把子文件 %s写出到目标文件中%n", eachFile); } } catch (IOException e) { e.printStackTrace(); } System.out.printf("最后目标文件的大小:%,d字节", destFile.length()); } }




问答区域    
2021-03-27 我的答案
thixin




我的答案
package ioStream;

import java.io.*;

public class Test2 {


    public static void main(String[] args) {
        String path = "D:/PN532工具.zip";

        chaifen(path, 1);   // 1表示已1m分割文件
        hebing(path);         // 合并文件

    }

    // finally方式
    public static void chaifen(String path, int l) {
        byte[] bts = new byte[1024 * 1024 * l];
        int len = 0;
        int i = 1;
        InputStream ips = null;
        try {
            ips = new FileInputStream(path);
            while ((len = ips.read(bts)) != -1) {
                OutputStream ots = null;
                try {
                    ots = new FileOutputStream(path + "-" + i);
                    ots.write(bts, 0, len);
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (ots != null) {
                        try {
                            ots.close();  // 关闭输入流
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                i++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ips != null) {
                try {
                    ips.close(); // 关闭输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

    // try()方式
    public static void hebing(String path) {
        int index = 1;
        File f;
        int len = 0;
        byte[] data = new byte[1024 * 100];
        try (FileOutputStream fos = new FileOutputStream(path)) {
            while ((f = new File(path + "-" + index)).exists()) {
                try (FileInputStream fis = new FileInputStream(f)) {
                    while ((len = fis.read(data)) != -1) {
                        fos.write(data, 0, len);
                    }
                    index++;
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

							


6 个答案

木宇
答案时间:2024-05-12
打卡

tuhui940924
答案时间:2022-10-21
拆分,合并

hoolich
答案时间:2022-04-01
/*/Users/chenqiang/Desktop/ 找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。 比如文件 eclipse.exe,大小是309k。 拆分之后,成为 eclipse.exe-0 eclipse.exe-1 eclipse.exe-2 eclipse.exe-3 */ package stream; import java.io.*; import java.util.Arrays; public class TestStream { /* * 拆分的思路,先把源文件的所有内容读取到内存中,然后从内存中挨个分到子文件里 * @param srcFile 要拆分的源文件 * @param eachSize 按照这个大小,拆分 */ /* * 合并的思路,就是从eclipse.exe-0开始,读取到一个文件,就开始写出到 eclipse.exe中,直到没有文件可以读 * @param folder * 需要合并的文件所处于的目录 * @param fileName * 需要合并的文件的名称 * @throws FileNotFoundException */ private static void murgeFile(String folder, String fileName) { try { // 合并的目标文件 File destFile = new File(folder, fileName); FileOutputStream fos = new FileOutputStream(destFile); int index = 0; while (true) { //子文件 File eachFile = new File(folder, fileName + "-" + index++); //如果子文件不存在了就结束 if (!eachFile.exists()) break; //读取子文件的内容 FileInputStream fis = new FileInputStream(eachFile); byte[] eachContent = new byte[(int) eachFile.length()]; fis.read(eachContent); // fis.close(); //把子文件的内容写出去 fos.write(eachContent); fos.flush(); System.out.printf("把子文件 %s写出到目标文件中%n", eachFile); } // fos.close(); System.out.printf("最后目标文件的大小:%,d字节", destFile.length()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void splitFile(File srcFile, int eachSize) { if (0 == srcFile.length()) throw new RuntimeException("文件长度为0,不可拆分"); byte[] fileContent = new byte[(int) srcFile.length()]; // 先把文件读取到数组中 FileInputStream fis = null; try { fis = new FileInputStream(srcFile); fis.read(fileContent); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 在finally 里关闭流 if (null != fis) try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } int filenumber;//设置文件数量 if(srcFile.length()%eachSize==0){ filenumber=(int)(srcFile.length()/eachSize); } else{ filenumber=(int)(srcFile.length()/eachSize)+1; } FileOutputStream fos = null; for(int i=0;i<filenumber;i++){ String eachFileName = srcFile.getName() + "-" + i; File eachFile = new File(srcFile.getParent(), eachFileName);//设置文件路径 byte[] eachContent; // 从源文件的内容里,复制部分数据到子文件 // 除开最后一个文件,其他文件大小都是100k // 最后一个文件的大小是剩余的 if (i != filenumber - 1) // 不是最后一个 eachContent = Arrays.copyOfRange(fileContent, eachSize * i, eachSize * (i + 1)); else // 最后一个 eachContent = Arrays.copyOfRange(fileContent, eachSize * i, fileContent.length); try { fos=new FileOutputStream(eachFile); fos.write(eachContent); fos.close(); System.out.printf("输出子文件%s,其大小是 %d字节%n", eachFile.getAbsoluteFile(), eachFile.length()); } catch(IOException e){ // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != fos) try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public static void main(String[] args) { murgeFile("/Users/chenqiang/Desktop", "手机样本.sql"); } }

惊世之梦
答案时间:2022-01-10
package com.how2j.IOtest3; import java.io.*; public class TestStream5 { public static void main(String[] args) { // 测试拆分文件 File file = new File("E:\\宝贝\\Win10版本一键转换.exe"); BufferedInputStream bis = null; try { bis = new BufferedInputStream(new FileInputStream(file)); // System.out.println(file.length()); String s = "filetest"; byte[] by = new byte[100 * 1024]; int len; int i = 1; while ((len = bis.read(by)) != -1) { s = s + i; File fileNew = new File("F:\\code\\IOtest\\" + s + ".exe"); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileNew)); bos.write(by, 0, len); bos.flush(); bos.close(); // System.out.println("输入的文件为: " + fileNew.getName() + "其大小为: " + fileNew.length() + "字节"); System.out.printf("输入的文件为: %s 其大小为: %d字节%n", fileNew.getName(), fileNew.length()); s = "filetest"; i++; } // System.out.println("拆分成功, 一共拆分成了" + (i - 1) + "个文件"); System.out.printf("拆分成功, 一共拆分成了%d个文件", (i - 1)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

szy000178519
答案时间:2021-10-22
KuroTT
答案时间:2021-07-16
供参考



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码 请至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2019-08-30 多个资源的try-with-resources
hugh95

只要在资源间加上“;”就好啦




1 个答案

gongming
答案时间:2022-04-29



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码 请至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2019-06-12 分分合合
2019-06-03 方法2中为什么声明在try里作用域无法达到finally?
2019-05-31 拆组文件的标准关闭流


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 7 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 中级-I/O-关闭流的方式 的提问

尽量提供截图、代码和异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图