【Java从入门到大牛】File和IO流上篇

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Java从入门到大牛
🌠 首发时间:2023年8月9日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生

目录

  • 存储数据的方案
  • File
    • 创建对象
    • 常用方法1:判断文件类型、获取文件信息
    • 常用方法2:创建文件、删除文件
    • 常用方法3:遍历文件夹
  • 前置知识:方法递归
    • 认识递归的形式
    • 应用、执行流程、算法思想
    • 案例:文件搜索
    • 案例:删除非空文件夹
    • 案例:啤酒问题
  • 前置知识:字符集
    • 常见字符集介绍
    • 总结
    • 字符集的编码、解码操作
  • IO流
  • IO流-字节流
    • 文件字节输入流:每次读取一个字节
    • 文件字节输入流:每次读取多个字节
    • 文件字节输入流:一次读取完全部字节
    • 文件字节输出流:写字节出去
    • 案例:文件复制
  • 释放资源的方式
    • try-catch-finally
    • try-with-resource

存储数据的方案

double money = 9999.5;							// 变量
int[] age = new int[100];						// 数组
Student s = new Student();						// 对象
List<Student> students = new ArrayList<>();		// 集合

上面这些都是内存中的数据容器,它们记住的数据,在断点或者程序终止时会丢失

有些数据想长久保存起来,该怎么办 ?

  • 文件是非常重要的存储方式,在计算机硬盘中
  • 即便断电或者程序终止了,存储在硬盘文件中的数据也不会丢失

File

File 是 java.io 包下的类,File 类的对象,用于代表当前操作系统的文件(可以是文件或者文件夹)

注意:File 类只能对文件本身进行操作,不能读写文件里面存储的数据

IO流

用于读写数据的,可以读写文件或者网络中的数据…

File

创建对象

创建File类的对象
在这里插入图片描述

  • File 对象既可以代表文件,也可以代表文件夹
  • File 封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许是不存在的

绝对路径、相对路径

  • 绝对路径:从盘符开始

    File f1 = new File("D:\\soft\\QQ");
    
  • 相对路径:不带盘符,默认直接到当前工程下的目录寻找文件

    File f2 = new File("模块名\\a.txt");
    

具体应用

import java.io.File;/*** 目标:掌握File创建对象,代表具体文件的方案*/
public class FileTest1 {public static void main(String[] args) {// 创建一个File对象,指代某个具体的文件File f1 = new File("D:/resource/a.txt");      // 方式一:最常用
//         File f1 = new File("D:\\resource\\ab.txt");           // 方式二:第一个反斜杠用来转义
//         File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");    // 方式三:File.separator表示分隔符 "\"System.out.println(f1.length());    // 文件大小// 创建一个File对象,指代某个文件夹File f2 = new File("D:/resource");System.out.println(f2.length());    // 文件夹的大小,不是计算其包括的所有文件的大小// 注意:File对象可以指代一个不存在的文件路径File f3 = new File("D:/resource/b.txt");System.out.println(f3.length());System.out.println(f3.exists());    // false// 我现在要定位的文件是在模块中,应该怎么定位呢?// 绝对路径:带盘符的,不推荐使用// File f4 = new File("D:\\code\\javasepromax\\file-io-app\\src\\c.txt");// 相对路径(重点):不带盘符,默认是直接去工程下寻找文件的File f4 = new File("file-io-app\\src\\itheima.txt");System.out.println(f4.length());}
}

常用方法1:判断文件类型、获取文件信息

File提供的判断文件类型、获取文件信息功能
在这里插入图片描述

具体应用

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;/**目标:掌握File提供的判断文件类型、获取文件信息功能*/
public class FileTest2 {public static void main(String[] args) throws UnsupportedEncodingException {// 1.创建文件对象,指代某个文件File f1 = new File("D:/resource/a.txt");// 2、public boolean exists():判断当前文件对象,对应的文件路径是否存在,存在返回trueSystem.out.println("f1.exists: " + f1.exists());// 3、public boolean isFile() : 判断当前文件对象指代的是否是文件,是文件返回true,反之System.out.println("f1.isFile: " + f1.isFile());// 4、public boolean isDirectory(): 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之System.out.println("f1.isDirectory: " + f1.isDirectory());// 5.public String getName():获取文件的名称(包含后缀)System.out.println("f1.getName: " + f1.getName());// 6.public long length():获取文件的大小,返回字节个数System.out.println("f1.length: " + f1.length());// 7.public long lastModified():获取文件的最后修改时间long time = f1.lastModified();SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");System.out.println("f1.lastModified: " + sdf.format(time));// 8.public String getPath():获取创建文件对象时,使用的路径File f2 = new File("D:\\resource\\ab.txt");File f3 = new File("file-io-app\\src\\itheima.txt");System.out.println("f2.getPath: " + f2.getPath());System.out.println("f3.getPath: " + f3.getPath());// 9.public String getAbsolutePath():获取绝对路径System.out.println("f2.getAbsolutePath: " + f2.getAbsolutePath());System.out.println("f3.getAbsolutePath: " + f3.getAbsolutePath());}
}

在这里插入图片描述

常用方法2:创建文件、删除文件

File类创建文件的功能
在这里插入图片描述

File类删除文件的功能
在这里插入图片描述

注意:delete 方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站

具体应用

import java.io.File;/*** 目标:掌握File创建和删除文件相关的方法*/
public class FileTest3 {public static void main(String[] args) throws Exception {// 1、public boolean createNewFile():创建一个新文件(文件内容为空),创建成功返回true,反之File f1 = new File("D:/code/aa.txt");System.out.println(f1.createNewFile());// 2、public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹File f2 = new File("D:/code/aaa");System.out.println(f2.mkdir());// 3、public boolean mkdirs():用于创建文件夹,注意:可以创建多级文件夹File f3 = new File("D:/code/bbb/ccc/ddd/eee/fff/ggg");System.out.println(f3.mkdirs());// 3、public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹System.out.println(f1.delete());System.out.println(f2.delete());File f4 = new File("D:/code");System.out.println(f4.delete());}
}

常用方法3:遍历文件夹

File类提供的遍历文件夹的功能
在这里插入图片描述

使用listFiles方法时的注意事项:

  • 当主调是文件,或者路径不存在时,返回 null
  • 当主调是空文件夹时,返回一个长度为 0 的数组
  • 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在 File 数组中返回
  • 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在 File 数组中返回,包含隐藏文件
  • 当主调是一个文件夹,但是没有权限访问该文件夹时,返回 null

具体应用

import java.io.File;
import java.io.IOException;
import java.util.Arrays;/*** 目标:掌握File提供的遍历文件夹的方法*/
public class FileTest4 {public static void main(String[] args) throws IOException {File f1 = new File("D:/code/aaa");f1.mkdir();for (int i = 1; i < 4; i++) {File f2 = new File("D:/code/aaa/a" + i + ".txt");if(!f2.createNewFile()) System.out.println("Failed to createNewFile!");}// 1、public String[] list():获取当前目录下所有的 "一级文件名称"到一个字符串数组中去返回String[] names = f1.list();for (String name : names) {System.out.println(name);}// 2、public File[] listFiles():(重点)获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)File[] files = f1.listFiles();for (File file : files) {System.out.println(file.getAbsolutePath());}File f3 = new File("D:/code/aaa");File[] files1 = f3.listFiles();System.out.println(Arrays.toString(files1));}
}

在这里插入图片描述

前置知识:方法递归

认识递归的形式

什么是方法递归 ?

  • 递归是一种算法,在程序设计语言中广泛应用
  • 从形式上看,方法调用自身的形式称为方法递归(recursion)

递归的形式

  • 直接递归:方法自己调用自己
  • 间接递归:方法调用其他方法,其他方法又回调方法自己

使用方法递归时需要注意的问题:

递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误

应用、执行流程、算法思想

案例导学-计算 n 的阶乘

需求:计算 n 的阶乘,例如 5 的阶乘 = 1 * 2 * 3 * 4 * 5

分析

  1. 假如我们认为存在一个公式是 f(n) = 1 * 2 * 3 * … * (n-1) * n
  2. 那么公式等价形式就是:f(n) = f(n-1) * n
  3. 如果求的是 1-5 的阶乘,我们如何手算出它的结果:f(5) = f(4) * 5,f(4) = f(3) * 4,…,f(2) = f(1) * 2,f(1) = 1,然后依次递归回来算出结果

具体实现

/*** 目标:掌握递归的应用,执行流程和算法思想。*/
public class RecursionTest1 {public static void main(String[] args) {System.out.println("5的阶乘是:" + f(5));}public static int f(int n){// 终结点if(n == 1){return 1;}else {return f(n - 1) * n;}}
}

在这里插入图片描述

递归算法三要素:

  1. 递归的公式:f(n) = f(n-1) * n
  2. 递归的终结点:f(1)
  3. 递归的方向必须走向终结点

案例-猴子吃桃问题

猴子第一天摘下若干桃子,当即吃了一半,觉得好不过瘾,于是又多吃了一个;第二天又吃了前天剩余桃子数量的一半,觉得好不过瘾,于是又多吃了一个;以后每天都是吃前天剩余桃子数量的一半,觉得好不过瘾,又多吃了一个;等到第10天的时候发现桃子只有1个了。

需求:请问猴子第一天摘了多少个桃子?

分析

整体来看,每一天都是做同一个事件,典型的规律化问题,考虑递归三要素:

  • 递归公式: f(n) = (f(n + 1) + 1) * 2
  • 递归终结点:f(10) = 1
  • 递归方向:从第一天到第十天
/*猴子吃桃问题*/
public class RecursionTest2 {public static void main(String[] args) {System.out.println("猴子第一天摘了" + f(1) + "个桃子");// 验证结果double num = f(1);for (int i = 1; i < 11; i++) {System.out.print("第" + i + "天一开始有" + num + "个桃子");num = num / 2 - 1;if (num >= 0) System.out.println(", 吃完还剩" + num + "个桃子");}}public static double f(double n) {if (n == 10) {return 1;} else {return (f(n + 1) + 1) * 2;}}
}
/*思路分析:f(2) = f(1) / 2 - 1;f(3) = f(2) / 2 - 1;f(4) = f(3) / 2 - 1;...f(9) = f(8) / 2 - 1;f(10) = f(9) / 2 - 1 = 1;*/

在这里插入图片描述

案例:文件搜索

案例:文件搜索

需求:从 D 盘中,搜索 “QQ.exe” 这个文件,找到后直接输出其位置

分析

  1. 先找出 D 盘下的所有一级文件对象
  2. 遍历全部一级文件对象,判断是否是文件
  3. 如果是文件,判断是否是自己想要的
  4. 如果是文件夹,需要继续进入到该文件夹,重复上述过程

代码实现

import java.io.File;/*** 目标:掌握文件搜索的实现*/
public class RecursionTest3 {public static void main(String[] args) throws Exception {searchFile(new File("D:/") , "QQ.exe");}/*** 去目录下搜索某个文件* @param dir  目录* @param fileName 要搜索的文件名称*/public static void searchFile(File dir, String fileName) throws Exception {// 1、把非法的情况都拦截住if(dir == null || !dir.exists() || dir.isFile()){return; // 代表无法搜索}// 2、dir不是null,存在,一定是目录对象// 获取当前目录下的全部一级文件对象File[] files = dir.listFiles();// 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象if(files != null && files.length > 0){// 4、遍历全部一级文件对象。for (File f : files) {// 5、判断文件是否是文件,还是文件夹if(f.isFile()){// 是文件,判断这个文件名是否是我们要找的if(f.getName().contains(fileName)){System.out.println("找到了:" + f.getAbsolutePath());// 拓展:启动QQRuntime runtime = Runtime.getRuntime();runtime.exec(f.getAbsolutePath());}}else {// 是文件夹,继续重复这个过程(递归)searchFile(f, fileName);}}}}
}

在这里插入图片描述

案例:删除非空文件夹

需求

删除非空文件夹

分析

  1. File 默认不可以直接删除非空文件夹
  2. 所有我们需要遍历文件夹,先删除里面的内容,再删除自己

代码实现

import java.io.File;/*** 删除非空文件夹*/
public class RecursionTest4 {public static void main(String[] args) throws Exception {createTestFile();File dir = new File("D:/test007");deleteDir(dir);     // 可以先注释这一行,到 D盘查看非空文件夹是否创建成功}// 创建用来删除的非空文件夹public static void createTestFile() throws Exception {// 创建多级文件夹File f1 = new File("D:/test007/aaa/bbb/ccc/ddd/eee");if (!f1.mkdirs()) return;// 创建一级文件夹File f2 = new File("D:/test007/fff");if (!f2.mkdir()) return;// 再随便添加一些文件for (int i = 1; i < 4; i++) {File f = new File("D:/test007/t00" + i + ".txt");if (!f.createNewFile()) return;}File f3 = new File("D:/test007/aaa/a.jpg");if (!f3.createNewFile()) return;System.out.println("非空文件夹创建成功!");}// 删除非空文件夹public static void deleteDir(File dir) {if (dir == null || !dir.exists()) {return;}// 是一个文件if (dir.isFile()) {if(dir.delete()) System.out.println("文件" + dir.getName() + "删除成功!");return;}// 是文件夹File[] files = dir.listFiles();     // 尝试取出所有一级文件对象// 取出一级文件对象失败if (files == null) {return;}// 取出成功,但是空文件夹if (files.length == 0) {if(dir.delete()) System.out.println("文件" + dir.getName() + "删除成功!");return;}// 是非空文件夹for (File file : files) {if (file.isFile()) {    // 是文件,直接删除if (file.delete()) System.out.println("文件" + file.getName() + "删除成功!");} else {deleteDir(file);    // 是文件夹,递归删除}}// 最后还剩下一个空文件夹,记得删除if(dir.delete()) System.out.println("文件" + dir.getName() + "删除成功!");}
}

执行结果

在这里插入图片描述

案例:啤酒问题

需求

啤酒 2 元 1 瓶,4 个盖子可以换一瓶,2 个空瓶可以换一瓶,请问 10 元钱可以喝多少瓶酒,剩余多少空瓶和盖子

代码实现

public class RecursionTest5 {public static int totalNumber;      // 总酒数public static int lastBottleNumber; // 每轮剩余瓶子数public static int lastCoverNumber;  // 每轮剩余盖子数public static void main(String[] args) {buy(10);System.out.println("总酒数: " + totalNumber);System.out.println("剩余瓶子数: " + lastBottleNumber);System.out.println("剩余盖子数: " + lastCoverNumber);}// 买酒public static void buy(int money) {// 有多少钱先买酒int buyNumber = money / 2;      // 可买酒数totalNumber += buyNumber;// 瓶子和盖子还可以换酒int allBottleNumber = buyNumber + lastBottleNumber;     // 当前总瓶子数int allCoverNumber = buyNumber + lastCoverNumber;       // 当前总盖子数int allMoney = 0;       // 记录下次买酒还有多少钱// 瓶子换酒if (allBottleNumber >= 2) {allMoney += (allBottleNumber / 2) * 2;}lastBottleNumber = allBottleNumber % 2;// 盖子换酒if (allCoverNumber >= 4) {allMoney += (allCoverNumber / 4) * 2;}lastCoverNumber = allCoverNumber % 4;// 如果钱还够买酒, 继续买if (allMoney >= 2) {buy(allMoney);}}
}

执行结果

在这里插入图片描述

前置知识:字符集

常见字符集介绍

在这里插入图片描述

标准ASCII字符集

  • ASCII(American Standard Code for Information Interchange):美国信息交换标准代码,包括了英文、符号等
  • 标准 ASCII 使用 1 个字节存储一个字符,首尾是 0,总共可表示 128 个字符
    在这里插入图片描述

GBK字符集(汉字内码扩展规范,国标)

  • 汉字编码字符集,包含了 2 万多个汉字等字符,GBK 中一个中文字符编码成两个字节的形式存储
  • 注意:GBK 兼容了 ASCII 字符集
  • GBK 规定:汉字的第一个字节的第一位必须是 1

Unicode字符集(统一码,也叫万国码)

Unicode 是国际组织规定的,可以容纳世界上所有文字、符号的字符集

UTF-8字符集

  • 是 Unicode 字符集的一种编码方案,采取可变长编码方案,共分为四个长度区:1 个字节、2 个字节、3 个字节、4 个字节

  • 英文字符、数字等只占 1 个字节(兼容标准 ASCII 编码),汉字字符占用 3 个字节

  • 注意:技术人员在开发时都应该使用 UTF-8 编码!

    在这里插入图片描述

总结

  • ASCII 字符集:只有英文、数字、符号等,占 1 个字节
  • GBK 字符集:汉字占 2 个字节,英文、数字占 1 个字节
  • UTF-8 字符集:汉字占 3 个字节,英文、数字占 1 个字节
  • 字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码
  • 英文、数字一般不会乱码,因为很多字符集都兼容了 ASCII 编码

字符集的编码、解码操作

什么是编码 ?

把字符按照指定的字符集编码成字节

什么是解码 ?

把字节按照指定的字符集编码解码成字符

Java 代码完成对字符的编码
在这里插入图片描述
Java 代码完成对字符的解码

在这里插入图片描述

具体应用

import java.util.Arrays;/*** 目标:掌握如何使用Java代码完成对字符的编码和解码*/
public class Test {public static void main(String[] args) throws Exception {// 1、编码String data = "a我b";byte[] bytes = data.getBytes(); // 默认是按照平台字符集(UTF-8)进行编码的。System.out.println(Arrays.toString(bytes));// 按照指定字符集进行编码byte[] bytes1 = data.getBytes("GBK");System.out.println(Arrays.toString(bytes1));// 2、解码String s1 = new String(bytes); // 按照平台默认编码(UTF-8)解码System.out.println(s1);String s2 = new String(bytes1, "GBK");System.out.println(s2);}
}

在这里插入图片描述

IO流

什么是IO流 ?

输入输出流,用来读写数据的

在这里插入图片描述

如何学习IO流 ?

  1. 先搞清楚 IO 流的分类、体系
  2. 再挨个学习每个 IO 流的作用、用法

IO流的分类

在这里插入图片描述

IO 流总体来看就有四大流:字节输入流、字节输出流、字符输入流、字符输出流

  • 字节输入流 InputStream:以内存为基准,来自磁盘文件 / 网络中的数据以字节的形式读入到内存中去的流
  • 字节输出流 OutputStream:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流
  • 字符输入流 Reader:以内存为基准,来自磁盘文件 / 网络中的数据以字符的形式读入到内存中去的流
  • 字符输出流 Writer:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络中去的流

IO流-字节流

文件字节输入流:每次读取一个字节

IO流的体系

在这里插入图片描述

FileInputStream(文件字节输入流)

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
在这里插入图片描述

注意事项

使用 FileInputStream 每次读取一个字节,读取性能较差,并且读取汉字输出会乱码

具体应用

准备一个测试文本文件:

在这里插入图片描述

import java.io.*;/*** 目标:掌握文件字节输入流,每次读取一个字节*/
public class FileInputStreamTest1 {public static void main(String[] args) throws Exception {// 1、创建文件字节输入流管道,与源文件接通// InputStream is = new FileInputStream(new File("file-io-app/src/test1.txt"));// 简化写法:推荐使用InputStream is = new FileInputStream(("file-io-app/src/test1.txt"));// 2、开始读取文件的字节数据// public int read():每次读取一个字节返回,如果没有数据了,返回-1int b; // 用于记住读取的字节while ((b = is.read()) != -1){System.out.print((char) b);}// 读取数据的性能很差!// 读取汉字输出会乱码!!无法避免的!!// 流使用完毕之后,必须关闭!释放系统资源!is.close();}
}

在这里插入图片描述

文件字节输入流:每次读取多个字节

FileInputStream(文件字节输入流)

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
在这里插入图片描述

注意事项

使用 FileInputStream 每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码

具体应用

import java.io.FileInputStream;
import java.io.InputStream;/*** 目标:掌握使用FileInputStream每次读取多个字节*/
public class FileInputStreamTest2 {public static void main(String[] args) throws Exception {// 1、创建一个字节输入流对象代表字节输入流管道与源文件接通InputStream is = new FileInputStream("file-io-app/src/test1.txt");// 2、开始读取文件中的字节数据:每次读取多个字节//  public int read(byte b[]) throws IOException//  每次读取多个字节到字节数组中去,返回读取的字节数量,读取完毕会返回-1byte[] buffer = new byte[3];int len; // 记住每次读取了多少个字节while ((len = is.read(buffer)) != -1){// 注意:读取多少,倒出多少。String rs = new String(buffer, 0 , len);System.out.print(rs);}// 性能得到了明显的提升!!// 但是这种方案也不能避免读取汉字输出乱码的问题!!is.close(); // 关闭流}
}

在这里插入图片描述

文件字节输入流:一次读取完全部字节

方式一:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节
在这里插入图片描述

方式二:Java 官方为 InputStream 提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回
在这里插入图片描述

直接把文件数据全部读取到一个字节数组可以避免乱码,是否还存在问题 ?

  • 如果文件过大,创建的字节数组也会过大,就可能引起内存溢出的问题

读写文本内容更适合用字符流,字节流适合做数据的转移,如:文件复制等

具体应用

在这里插入图片描述

import java.io.*;/*** 目标:使用文件字节输入流一次读取完文件的全部字节*/
public class FileInputStreamTest3 {public static void main(String[] args) throws Exception {// 1、一次性读取完文件的全部字节到一个字节数组中去// 创建一个字节输入流管道与源文件接通InputStream is1 = new FileInputStream("file-io-app/src/test2.txt");// 2、方式一:准备一个字节数组,大小与文件的大小正好一样大File f = new File("file-io-app/src/test2.txt");long size = f.length();byte[] buffer1 = new byte[(int) size];int len = is1.read(buffer1);System.out.println(new String(buffer1));System.out.println("---------------------------------");// 方式二:使用Java提供的方法InputStream is2 = new FileInputStream("file-io-app/src/test2.txt");byte[] buffer2 = is2.readAllBytes();System.out.println(new String(buffer2));// 关闭流is1.close();is2.close();}
}

在这里插入图片描述

文件字节输出流:写字节出去

FileOutputStream(文件字节输出流)

作用:以内存为基准,把内存中的数据以字节的形式写出到文件中

在这里插入图片描述

具体应用

import java.io.*;/*** 目标:掌握文件字节输出流FileOutputStream的使用*/
public class FileOutputStreamTest4 {public static void main(String[] args) throws Exception {// 1、创建一个字节输出流管道与目标文件接通// 覆盖管道:覆盖之前的数据
//        OutputStream os =
//                new FileOutputStream("file-io-app/src/testOut.txt");// 追加数据的管道OutputStream os =new FileOutputStream("file-io-app/src/testOut.txt", true);// 2、开始写字节数据出去os.write(97); // 97就是一个字节,代表aos.write('b'); // 'b'也是一个字节byte[] bytes = "我爱你中国abc".getBytes();os.write(bytes);os.write("\n".getBytes());          // 换行符os.write(bytes, 0, 15);     // 一个汉字占3个字节os.close(); // 关闭流}
}

在这里插入图片描述

案例:文件复制

在这里插入图片描述

字节流非常适合做一切文件的复制操作。任何文件的底层都是字节,字节流做复制,是一字不漏地转移完全部字节,只要复制后的文件格式一致就没问题

具体应用

import java.io.*;/*** 目标:使用字节流完成对文件的复制操作*/
public class CopyTest5 {public static void main(String[] args) throws Exception {// 需求:复制照片// 1、创建一个字节输入流管道与源文件接通InputStream is = new FileInputStream("file-io-app/src/1.png");// 2、创建一个字节输出流管道与目标文件接通OutputStream os = new FileOutputStream("file-io-app/src/copy.png");// 3、创建一个字节数组,负责转移字节数据byte[] buffer = new byte[1024];// 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少int len; // 记住每次读取了多少个字节while ((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}os.close();is.close();System.out.println("复制完成!!");}
}

在这里插入图片描述

释放资源的方式

try-catch-finally

try {...
} catch(IOException e) {e.printStackTrace();
} finally {...
}

finally 代码区的特点:无论 try 中的程序是正常执行了,还是出现了异常,最后都一定会执行 finally 区,除非 JVM 终止

作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)

具体应用

/*** 目标:认识try-catch-finally*/
public class Test1 {public static void main(String[] args) {try {System.out.println(10 / 2);// return;          // 跳出方法的执行// System.exit(0);  // 虚拟机}catch (Exception e){e.printStackTrace();} finally {System.out.println("===finally执行了一次===");}System.out.println(div(10, 2));}public static int div(int a, int b){try {return a / b;}catch (Exception e){e.printStackTrace();return -1; // 代表的是出现异常}finally {// 千万不要在finally中返回数据!return 111;}}
}

手动释放资源

/*** 目标:掌握释放资源的方式*/
public class Test2 {public static void main(String[] args)  {InputStream is = null;OutputStream os = null;try {// 1、创建一个字节输入流管道与源文件接通is = new FileInputStream("file-io-app/src/1.png");// 2、创建一个字节输出流管道与目标文件接通os = new FileOutputStream("file-io-app/src/copy.png");// 3、创建一个字节数组,负责转移字节数据byte[] buffer = new byte[1024];// 4、从字节输入流中读取字节数据,写出去到字节输出流中int len; // 记住每次读取了多少个字节while ((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}System.out.println("复制完成!!");} catch (IOException e) {e.printStackTrace();} finally {// 释放资源的操作try {if(os != null) os.close();} catch (IOException e) {e.printStackTrace();}try {if(is != null) is.close();} catch (IOException e) {e.printStackTrace();}}}
}

try-with-resource

JDK 7 开始提供了更简单的资源释放方案:try-with-resource

try(定义资源1; 定义资源2; ...) {可能出现异常的代码;
} catch(异常类名 变量名) {异常的处理代码;
}

上述资源使用完毕后,会自动调用其 close() 方法,完成对资源的释放

  • () 中只能放置资源,否则报错

  • 什么是资源呢?

  • 资源一般指的是最终实现了 AutoCloseable 接口

    public abstract class InputStream implements Closeable {}
    public abstract class OutputStream implements Closeable, Flushable {}
    public interface Closeable extends AutoCloseable {}
    

具体应用

public class MyConnection implements AutoCloseable{@Overridepublic void close() throws Exception {System.out.println("释放了与某个硬件的链接资源~~~~");}
}
import java.io.*;/*** 目标:掌握释放资源的方式:try-with-resource*/
public class Test3 {public static void main(String[] args)  {try (// 注意:这里只能放置资源对象(流对象)// 1、创建一个字节输入流管道与源文件接通InputStream is = new FileInputStream("file-io-app/src/1.png");// 2、创建一个字节输出流管道与目标文件接通OutputStream os = new FileOutputStream("file-io-app/src/copy.png");MyConnection conn = new MyConnection();){// 3、创建一个字节数组,负责转移字节数据byte[] buffer = new byte[1024];// 4、从字节输入流中读取字节数据,写出去到字节输出流中int len; // 记住每次读取了多少个字节while ((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}System.out.println("复制完成!!");} catch (Exception e) {e.printStackTrace();}}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/59027.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Easys Excel的表格导入(读)导出(写)-----java

一,EasyExcel官网: 可以学习一些新知识: EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 二,为什么要使用easyexcle excel的一些优点和缺点 java解析excel的框架有很多 &#xff1a; poi jxl,存在问题&#xff1a;非常的消耗内存&#xff0c; easyexcel 我们…

Llama 2 with langchain项目详解(一)

Llama 2 with langchain项目详解(一) 2023年2月25日,美国Meta公司发布了Llama 1开源大模型。随后,于2023年7月18日,Meta公司发布了Llama 2开源大模型,该系列包括了70亿、130亿和700亿等不同参数规模的模型。相较于Llama 1,Llama 2的训练数据增加了40%,上下文长度提升至…

Arduino 项目笔记 | Arduino LED Memory Game 颜色记忆游戏机

成果展示 颜色记忆游戏机 &#xff5c; Arduino DIY 1. 线路链连接 1.1 原理图 1.2 PCB 免费PCB打样 Arduino LED Memory Game 颜色记忆机资料下载 1.3 烧录 Bootloader 第二部分&#xff1a;Burn bootloader 2. 程序实现 #define NOTE_B0 31 #define NOTE_C1 33 #define NOT…

JMeter启动时常见的错误

很多小伙伴在学工具这一块时&#xff0c;安装也是很吃力的一个问题&#xff0c;之前记得有说过怎么安装jmeter这个工具。那么你要启动jmeter的时候&#xff0c;一些粉丝就会碰到如下几个问题。 1.解压下载好的jmeter安装&#xff0c;Windows 平台&#xff0c;双击 jmeter/bin …

Python自动化测试用例:如何优雅的完成Json格式数据断言

目录 前言 直接使用 优化 封装 小结 进阶 总结 资料获取方法 前言 记录Json断言在工作中的应用进阶。 直接使用 很早以前写过一篇博客&#xff0c;记录当时获取一个多级json中指定key的数据&#xff1a; #! /usr/bin/python # coding:utf-8 """ aut…

IDEA设置项目编码格式【修改为GBK 或 UTF-8】

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 出现问题 IDEA导入Eclipse项目、出现编码格式问题。以下过程为将编码格…

动手吧,vue移动端消息滚动组件

先看效果图&#xff1a; 1、模板部分 <transition name"fade-sport"><div class"v-message-roll" v-show"visible"><svg class"v-icon" viewBox"0 0 1024 1024" version"1.1" xmlns"http://…

选读SQL经典实例笔记20_Oracle语法示例

1. 计算一年有多少天 1.1. sql select Days in 2005: ||to_char(add_months(trunc(sysdate,y),12)-1,DDD)as reportfrom dualunion allselect Days in 2004: ||to_char(add_months(trunc(to_date(01-SEP-2004),y),12)-1,DDD)from dual REPORT ----------------- Days in 200…

开发工具Eclipse的使用

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Eclipse是什么 二.使用Eclipse的…

一百四十一、Kettle——kettle8.2在Windows本地开启carte服务以及配置子服务器

一、目的 在kettle建好共享资源库后&#xff0c;为了给在服务器上部署kettle的carte服务躺雷&#xff0c;先在Windows本地测试一下怎么玩carte服务 二、Kettle版本以及在Windows本地安装路径 kettle版本是8.2 pdi-ce-8.2.0.0-342 kettle本地安装路径是D:\j…

安全渗透知识总结二

目录 一、html实体编码 1、Unicode字符编码 2、字符的数字表示 3、常见实体编码 4、url 协议 主机 http状态码 http常用的状态码 端口 常见协议端口 查询参数 锚点 url字符 urlcode字符 绝对url和相对url 二、字符编码 Ascll字符集 html字符集 html的url编码 …

RabbitMQ的6种工作模式

RabbitMQ的6种工作模式 官方文档&#xff1a; http://www.rabbitmq.com/ https://www.rabbitmq.com/getstarted.html RabbitMQ 常见的 6 种工作模式&#xff1a; 1、simple简单模式 1)、消息产生后将消息放入队列。 2)、消息的消费者监听消息队列&#xff0c;如果队列中…