Java基础 - 10 - File、IO流(一)

File:代表文本

IO流:读写数据 

 一. File

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

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

1.1 创建File类的对象

构造器说明
public File(String pathname)根据文件路径创建文件对象
public File(String parent, String child)根据父路径和子路径名字创建文件对象
public File(File parent, String child)根据父路径对应文件对象和子路径名字创建文件对象

注意

        · File对象既可以代表文件,也可以代表文件夹

        · File封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许是不存在的

绝对路径、相对路径

        绝对路径:从盘符开始

        相对路径:不带盘符,默认直接到当前工程下的目录寻找文件

public class demo {
    public static void main(String[] args) {
        //文件路径名:
        //路径分隔符: 三种写法
        File f1 = new File("D:/zm/1.txt"); //指代某个具体的文件
        //File f1 = new File("D:\\zm\\1.txt");
        //File f1 = new File("D:"+File.separator+"zm"+File.separator+"1.txt");
        System.out.println(f1.length()); //文件大小

        File f2 = new File("D:/zm"); //指代某个文件夹
        System.out.println(f2.length());

        File f3 = new File("D:/zm/2.txt"); //指代某个不存在的文件
        System.out.println(f3.length()); //0
        System.out.println(f3.exists()); //false 不存在

        //绝对路径:带盘符的
        //File f4 = new File("D:\\code\\IJProject\\demo\\src\\wosun.txt");
        //相对路径:不带盘符,默认是直接去工程下寻找文件
        File f4 = new File("demo\\src\\wosun.txt");
        System.out.println(f4.length());
    }
}

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

方法名称说明
public boolean exists()判断当前文件对象,对应的文件路径是否存在,存在返回true
public boolean isFile()判断当前文件对象指代的是否是文件,是文件返回true,反之false
public boolean isDirectory()判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之false
public String getName()获取文件的名称(包含后缀)
public long length()获取文件的大小,返回字节个数
public long lastModified()获取文件的最后修改时间

public String getPath()

获取创建文件对象时,使用的路径
public String getAbsolutePath()获取绝对路径
public class demo {
    public static void main(String[] args) {
        //创建文件对象,指代某个文件
        File f1 = new File("D:/zm/1.txt");
        //创建文件对象,指代某个文件夹(不存在的)
        File f2 = new File("D:/wosun");

        //1.public boolean exists() 判断当前文件对象,对应的文件路径是否存在,存在返回true
        System.out.println(f1.exists()); //true
        System.out.println(f2.exists()); //false

        //2.public boolean isFile() 判断当前文件对象指代的是否是文件,是文件返回true,反之false
        System.out.println(f1.isFile()); //true

        //3.public boolean isDirectory() 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之false
        System.out.println(f1.isDirectory()); //false

        //4.public String getName() 获取文件的名称(包含后缀)
        System.out.println(f1.getName()); //1.txt

        //5.public long length() 获取文件的大小,返回字节个数
        System.out.println(f1.length());

        //6.public long lastModified() 获取文件的最后修改时间
        System.out.println(f1.lastModified());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(f1.lastModified()));

        //7.public String getPath() 获取创建文件对象时,使用的路径
        System.out.println(f1.getPath()); //创建的时候是绝对路径就是绝对路径

        File f3 = new File("src\\wosun.txt"); //创建的时候是相对路径就是相对路径
        System.out.println(f3.getPath());

        //8.public String getAbsolutePath() 获取绝对路径
        System.out.println(f3.getAbsolutePath());
    }
}

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

方法名称说明
public boolean createNewFile()创建一个新文件(文件内容为空),创建成功返回true,反之false
public boolean mkdir()用于创建文件夹,注意:只能创建一级文件夹
public boolean mkdirs()用于创建文件夹,注意:可以创建多级文件夹
public boolean delete()删除文件或空文件夹,注意:不能删除非空文件夹

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

public class demo {
    public static void main(String[] args) throws IOException {
        File f1 = new File("D:/zm/2.txt"); // 不存在的文件
        File f2 = new File("D:/zm/bbb/ccc/ddd"); //三级文件夹
        File f3 = new File("D:/zm/aaa"); //一级文件夹

        //1.public boolean createNewFile() 创建一个新文件(文件内容为空),创建成功返回true,反之false
        System.out.println(f1.createNewFile()); //不存在则创建成功,存在则创建失败

        //2.public boolean mkdir() 用于创建文件夹,注意:只能创建一级文件夹
        System.out.println(f2.mkdir()); //false
        System.out.println(f3.mkdir()); //true

        //3.public boolean mkdirs() 用于创建文件夹,注意:可以创建多级文件夹
        System.out.println(f2.mkdirs()); //true

        //4.public boolean delete() 删除文件或空文件夹,注意:不能删除非空文件夹
        System.out.println(f1.delete());
        System.out.println(f3.delete());
        System.out.println(f2.delete()); //删除"D:/zm/bbb/ccc/ddd"中的最后的空文件夹ddd
    }
}

1.4 常见方法:遍历文件夹

方法名称说明
public String[] list()获取当前目录下所有的“一级文件名称”到一个字符串数组中去返回
public File[] listFiles()获取当前目录下所有的“一级文件对象”到一个文件对象数组中去返回

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

· 当主调是文件,或者路径不存在时,返回null

· 当主调是空文件夹,返回一个长度为0的数组

· 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回

· 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件

· 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null

public class demo {
    public static void main(String[] args) throws IOException {
        File f1 = new File("D:/zm");
        //1.public String[] list() 获取当前目录下所有的“一级文件名称”到一个字符串数组中去返回
        String[] nameList = f1.list();
        for (String s : nameList) {
            System.out.println(s); //文件名称 eg:1.txt
        }

        //2.public File[] listFiles() 获取当前目录下所有的“一级文件对象”到一个文件对象数组中去返回

        //使用listFiles方法时的注意事项:
        //· 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
        File[] files1 = f1.listFiles();
        for (File file : files1) {
            System.out.println(file); //文件对象 eg:D:\zm\1.txt
        }

        //· 当主调是文件,或者路径不存在时,返回null
        File f2 = new File("D:/zm/1.txt"); //主调是文件
        File[] files2 = f2.listFiles();
        System.out.println(files2); //null

        File f3 = new File("D:/recourse"); //路径不存在
        File[] files3 = f3.listFiles();
        System.out.println(files3); //null

        //· 当主调是空文件夹,返回一个长度为0的数组
        File f4 = new File("D:/zm/bbb"); //主调是空文件夹
        File[] files4 = f4.listFiles();
        System.out.println(Arrays.toString(files4)); //[]

        //· 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
        //· 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
        
    }
}

二. 方法递归

        · 递归是一种算法,在程序设计语言中广泛使用

        · 从形式上说:方法调用自身的形式称为方法递归(recursion)

递归的形式

        · 直接递归:方法自己调用自己

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

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

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

public class demo {
    public static void main(String[] args) {
        test1();  //java.lang.StackOverflowError 栈内存溢出错误
    }

    //直接方法递归
    public static void test1(){
        System.out.println("===test1===");
        test1();
    }

    //间接方法递归
    public static void test2(){
        System.out.println("===test2===");
        test3();
    }

    public static void test3(){
        test2();
    }
}

2.1 递归算法三要素

        · 递归的公式:f(n)=f(n-1)*n

        · 递归的终结点:f(1)

        · 递归的方向必须走向终结点

2.2 递归算法案例

2.2.1 案例:n的阶乘

public class demo {
    public static void main(String[] args) {
        System.out.println("6的阶乘:"+f(6));
    }

    public static int f(int n){
        //终结点
        if(n==1){
            return 1;
        }else{
            return f(n-1)*n;
        }
    }
}

2.2.2 案例:1-n的和

public class demo {
    public static void main(String[] args) {
        System.out.println("1-100的和:"+f(100));
    }

    public static int f(int n){
        //终结点
        if(n==1){
            return 1;
        }else{
            return f(n-1)+n;
        }
    }
}

2.2.3 猴子吃桃问题

public class demo {
    public static void main(String[] args) {
        // 猴子吃桃问题
        // f(10)=1
        // f(x)表示f(x+1)的前一天
        // f(x) = 2 * (f(x+1) + 1)
        // 求 f(1)
        System.out.println("猴子第一天摘的桃子个数:" + f(1));
    }

    public static int f(int n){
        //终结点
        if(n==10){
            return 1;
        }else{
            return 2 * (f(n+1) + 1);
        }
    }
}

2.2.4 啤酒问题

问题:啤酒2元一瓶,4个盖子可以换一瓶,2个瓶子可以换一瓶,10块钱可以喝到几瓶?

public class demo {
    public static int totalNum = 0;  //酒的总共数量
    public static int lastBottleNum = 0; //剩余的瓶子数
    public static int lastCoverNum = 0; //剩余的瓶盖数
    public static void main(String[] args) {
        //问题:啤酒2元一瓶,4个盖子可以换一瓶,2个瓶子可以换一瓶,10块钱可以喝到几瓶?
        buy(10);
        System.out.println("购买的酒的数量:"+totalNum);
        System.out.println("剩余瓶盖数:"+lastCoverNum);
        System.out.println("剩余瓶子数:"+lastBottleNum);
    }

    private static void buy(int money) {
        //买酒的数量
        int buyNum = money / 2;
        totalNum += buyNum;

        //当前剩余的瓶子数和瓶盖数
        lastBottleNum += buyNum;
        lastCoverNum += buyNum;

        int allMoney = 0; //可以换的钱数(4个盖子可值2元,2个瓶子可值2元)

        if(lastCoverNum >= 4){
            allMoney += (lastCoverNum/4)*2;
        }
        lastCoverNum = lastCoverNum % 4;

        if(lastBottleNum >= 2){
            allMoney += (lastBottleNum/2)*2;
        }
        lastBottleNum = lastBottleNum % 2;

        if(allMoney>=2){
            buy(allMoney);
        }
    }
}

2.3 递归与File

2.3.1 案例:文件搜索

public class demo {
    public static void main(String[] args) throws IOException {
        File dir = new File("D:/"); //要搜索的路径(目录)
        String fileName = "QQ.exe"; //要搜索的文件名
        searchFile(dir,fileName);
    }

    /**
     * 去目录下搜索某个文件
     * @param dir 目录
     * @param fileName 要搜索的文件名
     */
    public static void searchFile(File dir,String fileName) throws IOException {
        //拦截非法情况(路径为null,路径不存在)
        if(dir == null || !dir.exists()){
            return; //无法搜索
        }
        //指定路径是一个文件
        if(dir.isFile()){
            //判断该文件名是否是搜索的文件名
            if(dir.getName().equals(fileName)){
                //是,打印路径
                System.out.println(dir.getAbsolutePath());
                return; //跳出方法
            }else{
                return; //搜索失败
            }
        }

        //指定路径dir不是null,且存在,且是一个文件夹(目录)
        //获取当前目录下的全部一级文件对象
        File[] files = dir.listFiles();

        //判断当前目录下是否存在一级文件对象,是否可以拿到一级文件对象
        if(files != null && files.length > 0){
            //遍历全部一级文件对象
            for (File file : files) {
                //判断文件是文件还是文件夹
                if(file.isFile()){
                    //是文件
                    if(file.getName().equals(fileName)){
                        System.out.println(file.getAbsolutePath());

                        //启动该程序
                        Runtime runtime = Runtime.getRuntime();
                        runtime.exec(file.getAbsolutePath());

                        return; //结束方法
                    }
                }else if(file.isDirectory()){
                    //是文件夹  重复该过程
                    searchFile(file,fileName);
                }
            }
        }
    }
}

2.3.2 案例:删除文件夹

public class demo {
    public static void main(String[] args) throws IOException {
        File dir = new File("D:/桌面/aaa");
        //System.out.println(dir.delete());  //false 非空文件夹不能通过delete()方法删除
        deleteDir(dir);
    }

    //删除非空文件夹
    public static void deleteDir(File dir){
        //指定路径为null或不存在
        if(dir == null || !dir.exists()){
            System.out.println("删除失败,指定路径为null或不存在");
            return;
        }

        //指定路径是文件,直接删除
        if(dir.isFile()){
            dir.delete();
            return;
        }

        //dir存在且是文件夹
        //判断dir是否为空文件夹
            //提取dir目录下的一级文件对象
        File[] files = dir.listFiles();

        //files为null,没有删除权限
        if(files == null){
            System.out.println("没有删除权限");
            return;
        }

        //因为删除内容后依旧要删除自己,所以这一段代码可以省略
//        //files.length为0,说明dir是空文件夹
//        if(files.length == 0){
//            dir.delete();
//            return;
//        }

        //dir是一个有内容的文件夹(先删除里里面的内容再删除自己)
        //先删除里里面的内容
        for (File file : files) {
            if(file.isFile()){
                file.delete();
            }else{
                deleteDir(file);
            }
        }
        //再删除自己
        dir.delete();
    }
}

三. 字符集

3.1 标准ASCII字符集

· ASCII(American Standard Code for Information Interchange):美国信息交换标准代码,包括了英文、数字、符号等

· 标准ASCII使用1个字节存储一个字符,首尾是0,总共可表示128个字符

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

· 汉字编码字符集,包含了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储

· 注意:GBK兼容了ASCII字符集(英文、数字占1个字节)

· GBK规定:汉字的第一个字节的第一位必须是1

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

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

· UTF-32用4个字节表示一个字符(占存储空间,效率变低)

· UTF-8是Unicode字符集的一种编码方案,采用可变长编码方案,共分四个长度区:1个字节、2个字节、3个字节、4个字节

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

注意:

· 字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码

· 英文、数字一般不会乱码,因为很多字符集都兼容了ASCII编码

3.4 字符集的编码、解码

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

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

Java代码完成对字符的编码

String提供了如下方法说明
byte[] getBytes()使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
byte[] getBytes(String charsetName)使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中

Java代码完成对字符的解码

String提供了如下方法说明
String(byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的String
String(byte[] bytes, String charsetName)通过指定的字符集解码指定的字节数组来构造新的String
public class demo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //编码
        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));

        //解码
        String s1 = new String(bytes); //默认按照平台字符集(UTF-8)进行解码
        System.out.println(s1); //a我b

        String s2 = new String(bytes1); //默认按照平台字符集(UTF-8)进行解码
        System.out.println(s2); //a��b 因为bytes1按照GBK解码,所以按照UTF-8解码会出现乱码

        String s3 = new String(bytes1,"GBK"); //指定字符集解码
        System.out.println(s3); //a我b
    }
}

四. IO流

IO流:输入输出流,用于读写数据

        I指Input,称为输入流:负责把数据读到内存中去

        O指Output,称为输出流:负责写数据出去

IO流的应用场景

IO流的分类

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

4.1 FileInputStream(文件字节输入流)

· 作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去

构造器说明
public FileInputStream(File file)创建字节输入流管道与源文件接通
public FileInputStream(String pathname)创建字节输入流管道与源文件接通
方法名称说明
public int read()每次读取一个字节返回,如果发现没有数据可读会返回-1
public int read(byte[] buffer)每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1

4.1.1 每次读取一个字节read()

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

public class demo {
    public static void main(String[] args) throws Exception {
    //创建文件字节输入流管道,与源文件接通
        //public FileInputStream(File file) 创建字节输入流管道与源文件接通
        InputStream is = new FileInputStream(new File("demo/src/wosun.txt")); //多态
        //简化写法:推荐使用
        //public FileInputStream(String pathname) 创建字节输入流管道与源文件接通
        InputStream fis = new FileInputStream("demo\\src\\wosun.txt"); //多态

        //开始读取文件的字节数据
        //public int read()	每次读取一个字节返回,如果发现没有数据可读会返回-1
//        int b1 = fis.read();
//        System.out.println((char) b1); //读第一个字节
//
//        int b2 = fis.read();
//        System.out.println((char) b2); //读第二个字节
//
//        int b3 = fis.read();
//        System.out.println(b3); //如果发现没有数据可读会返回-1

        //使用循环改造上述代码
        int b; //用于记住读取的字节
        while((b = fis.read()) != -1){
            System.out.print((char) b);
        }

        //上述方法一次只读一个字节,读取数据的性能很差(频繁调用系统资源)
        //上述方法一次只读一个字节,会导致读取汉字输入会乱码!无法避免!
        //流使用完毕之后,必须关闭!释放系统资源!
        fis.close();
    }
}

4.1.2 每次读取多个字节read(byte[] buffer) 

· 使用FileInputStream的read(byte[] buffer)每次读取多个字节,读取性能得到提升,但读取汉字输出还是会乱码

public class demo {
    public static void main(String[] args) throws Exception {
        //创建一个字节输入流对象代表字节输入流管道与源文件接通
        InputStream fis = new FileInputStream("demo\\src\\wosun.txt"); //多态

        //开始读取文件的字节数据,每次读取多个字节
        // public int read(byte[] buffer)
        // 每次读取多个字节,用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1
        //byte[] buffer = new byte[1024];  //每次可以读1024个字节,即1KB
//        byte[] buffer = new byte[3];
//        int len1 = fis.read(buffer);  //每次最多读3个字节
//        String s1 = new String(buffer); //解码
//        System.out.println(s1);
//        System.out.println("当次读取的字节数:"+len1);
//
//        //buffer = [abc]
//        //buffer = [66c] //c没有覆盖,因此需要读取多少倒出多少
//        int len2 = fis.read(buffer);
//        //String s2 = new String(buffer);  //66c
//        String s2 = new String(buffer,0,len2); //66
//        System.out.println(s2);
//        System.out.println("当次读取的字节数:"+len2);
//
//        int len3 = fis.read(buffer);
//        System.out.println("当次读取的字节数:"+len3); //没有字节后读取的字节长度会是-1

        //优化
        byte[] buffer = new byte[3];
        int len; //记录每次读取了多少个字节
        while((len = fis.read(buffer)) != -1){
            String s = new String(buffer,0,len);
            System.out.println("当前读取到的字节:"+s+" 当前读取到的字节数:"+len);
        }

        fis.close();
    }
}

4.1.3 一次读取完全部字节

        可以解决字节流读取中文输出乱码的问题,但是如果文件过大,创建的字节数组也会过大,可能引起内存溢出

一次读取完全部字节的两种方式

· 方式一:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节

· 方式二:Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回

public class demo {
    public static void main(String[] args) throws Exception {
        //创建一个文件对象
        File f = new File("demo\\src\\wosun.txt");
        //创建一个字节输入流对象代表字节输入流管道与源文件接通
        InputStream fis = new FileInputStream(f); //多态

        //方式1:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节
//        //length:文件大小
//        long length = f.length();
//        //该方案只适合读相对来说较小的文件(不超过内存容量)
//        byte[] buffer = new byte[(int) length];
//
//        int len = fis.read(buffer); //len:当前读取到的字节数
//        String s = new String(buffer,0,len);
//        System.out.println("当前读取到的字节:"+s+" 当前读取到的字节数:"+len);

        //方式2:Java官方为InputStream提供了read方法,可以直接把文件的全部字节读取到一个字节数组中返回
        byte[] buffer = fis.readAllBytes(); //在jdk9中才出现的
        System.out.println(new String(buffer));

        fis.close();
    }
}

注意:

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

4.2 FileOutputStream(文件字节输出流)

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

构造器说明
public FileOutputStream(File file)创建字节输出流管道与源文件对象接通
public FileOutputStream(String filepath)创建字节输出流管道与源文件路径接通
public FileOutputStream(File file, boolean append)创建字节输出流管道与源文件对象接通,可追加数据
public FileOutputStream(String filepath, boolean append)创建字节输出流管道与源文件路径接通,可追加数据
方法名称说明
public void write(int a)写一个字节出去
public int write(byte[] buffer)写一个字节数组出去
public int write(byte[] buffer, int pos, int len)写一个字节数组的一部分出去
public void close() throws IOException关闭流
public class demo {
    public static void main(String[] args) throws Exception {
        //相对路径
          //以“./”开头,代表当前目录和文件目录在同一个目录里,“./”也可以省略不写!
          //以"../"开头:向上走一级,代表目标文件在当前文件所在的上一级目录;
          //以"../../"开头:向上走两级,代表父级的父级目录,也就是上上级目录,再说明白点,就是上一级目录的上一级目录
          //以"/”开头,代表根目录

        //创建一个字节输出流管道与目标文件接通
          //覆盖管道,会覆盖文件中原有的数据
        //OutputStream os = new FileOutputStream("demo/src/wosun.txt");
          //追加管道,不会覆盖文件中原有的数据
        OutputStream os = new FileOutputStream("demo/src/wosun.txt",true);

        //开始写字节数据出去
        //每次写一个字节
        os.write(97);  //97就是一个字节,代表a
        os.write('b'); //'b'也是一个字节
        //os.write('你'); //乱码,因为write(int a)默认写一个字节,你在系统默认字符集(UTF-8)中占3个字节,因此乱码

        byte[] bytes = "abc你好星期天abc".getBytes();
        os.write(bytes);

        //换行
        os.write("\r\n".getBytes());

        os.write(bytes,3,15); //从3开始,写入15个字节,正好是“你好星期六”

        os.close(); //关闭流
    }
}

4.3 字节流案例:文件复制

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

public class demo {
    public static void main(String[] args) throws Exception {
        //文件复制
        //需要创建一个字节输入流管道与原文件接通
        InputStream is = new FileInputStream("D:/zm/1.jpg");
        //创建一个字节输出流管道与目标位置接通
        OutputStream os = new FileOutputStream("D:/zm/aaa/1.jpg"); //要自己填写文件名
        //创建一个字节数组,负责转移字节数据
        byte[] buffer = new byte[1024];  //一次可以读取1KB
        //从字节输入流中读取字节数据,然后写到字节输出流中,读多少写多少
        //每次读取多个字节read(byte[] buffer)
        int len; //用来记录每次读取了多少字节
        while((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }
        //后创建的流先关闭,先创建的流后关闭
        os.close();
        is.close();
        System.out.println("复制完成");
    }
}


//用try-catch-finally改良后的文件复制
public class demo {
    public static void main(String[] args) {
        InputStream is = null;
        OutputStream os = null;
        try {

            System.out.println(10/0); //出现异常

            //文件复制
            //需要创建一个字节输入流管道与原文件接通
            is = new FileInputStream("D:/zm/1.jpg");
            //创建一个字节输出流管道与目标位置接通
            os = new FileOutputStream("D:/zm/aaa/1.jpg"); //要自己填写文件名

            System.out.println(10/0); //出现异常

            //创建一个字节数组,负责转移字节数据
            byte[] buffer = new byte[1024];  //一次可以读取1KB
            //从字节输入流中读取字节数据,然后写到字节输出流中,读多少写多少
            //每次读取多个字节read(byte[] buffer)
            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();
            }
        }
    }
}

4.4 释放资源的方式

4.4.1 try-catch-finally

public class demo {
    public static void main(String[] args) throws Exception {
        try{
            System.out.println(10/2); //没有异常,也会执行finally中的代码
            // System.out.println(10/0); //出现异常,也会执行finally中的代码
            // return; //跳出方法的执行,也会执行finally中的代码
            // System.exit(0); //虚拟机jvm挂掉,就不会执行finally中的代码
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("======finally执行了一次======");
        }

        System.out.println(chu(10, 2)); //111
    }

    public static int chu(int a,int b){
        try{
            return a/b;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }finally {
            //千万不要在finally里返回数据
            return 111;
        }
    }
}

4.4.2 try-with-resource

public class demo {
    public static void main(String[] args) {
        //文件复制
        try(
                //需要创建一个字节输入流管道与原文件接通
                InputStream is = new FileInputStream("D:/zm/1.jpg");
                //创建一个字节输出流管道与目标位置接通
                OutputStream os = new FileOutputStream("D:/zm/aaa/1.jpg"); //要自己填写文件名

                //注意:这里只能放置资源对象(流对象)
                //什么是资源?
                    // 资源都是会实现AutoCloseable接口,资源都会有一个close方法
                    // 并且资源放到这里(try()里面)后,当它用完之后,会被自动调用其close方法完成资源的释放操作
                
                ) {

            //创建一个字节数组,负责转移字节数据
            byte[] buffer = new byte[1024];  //一次可以读取1KB
            //从字节输入流中读取字节数据,然后写到字节输出流中,读多少写多少
            //每次读取多个字节read(byte[] buffer)
            int len; //用来记录每次读取了多少字节
            while((len = is.read(buffer)) != -1){
                os.write(buffer,0,len);
            }

            System.out.println("复制完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java+Springboot】------ 通过JDBC+GetMapping方法进行数据select查询、多种方式传参、最简单的基本示例!

一、JDBC如何使用、PostGresql数据库 1、在pom.xml 先引用jdbc组件。 <!--jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency> 2、在pom.xml 再引用p…

【GIS前言技术】今年全球唯一一次日全食要来了!

今年全球唯一一次日全食将于北京时间4月9日凌晨上演&#xff0c;全食带扫过北美洲&#xff0c;墨西哥、美国和加拿大的众多城市都能看到这次日全食&#xff0c;发生时间为当地时间4月8日中午到下午&#xff0c;观赏性比较强。 日全食&#xff08;Eclipse&#xff09;是日食的一…

Linux进程状态深度解析:探索进程的生命周期

文章目录 一、引言1、进程的概念与重要性2、Linux系统下进程状态的意义3、进程状态与系统性能的关系 二、Linux下进程状态概述1、Linux进程状态的分类2、进程状态信息的获取方法 三、Linux下进程状态详解1、运行状态&#xff08;Running&#xff09;2、可中断睡眠状态&#xff…

算法打卡day33|动态规划篇01|动态规划理论基础| Leetcode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

目录 动态规划理论 定义 动态规划的解题步骤 算法题 Leetcode 509. 斐波那契数 个人思路 解法 动态规划 Leetcode 70. 爬楼梯 个人思路 解法 动态规划 Leetcode 746. 使用最小花费爬楼梯 个人思路 解法 动态规划 动态规划理论 定义 动态规划(Dynamic Programmi…

yarn集群部署

yarn集群部署案例 我们来基于一个案例讲解yarn集群部署 我们要部署yarn集群&#xff0c;需要分别部署HDFS文件系统及YARN集群 Hadoop HDFS分布式文件系统&#xff0c;我们会启动&#xff1a; NameNode进程作为管理节点DataNode进程作为工作节点SecondaryNamenode作为辅助 同…

乐健体育刷分----AI运动的站姿风车

一.前情提要 1.本文仅作学习参考不得用于其他不当途径&#xff0c;若有问题后果自负 二.操作 1.打开乐健体育 2.点击AI运动&#xff0c;找到站姿风车 3.摄像头对准以下图片&#xff0c;拖动图片或保持不动均可 &#xff08;站姿风车2组及以上效果更佳&#xff09;

在实体类中使用JSONObject对象

有时候我们的业务需求可能字段是json格式&#xff0c;这个时候我们的实体类就对应的也应该是json格式&#xff0c;需要使用到JSONObject这个对象&#xff0c;但是可能会使用不了这个对象&#xff0c;那接下来我将简单介绍如何使用这个对象。 以下为我的实体类中的某个字段&…

面试总结------2024/04/04---项目

1.面试官提问&#xff1a;你说你在项目中使用springsecurity jwt 实现了登录功能&#xff0c;能简单讲一下怎么实现的吗&#xff1f; 2.使用RabbitMQ实现订单超时取消功能 redis实现的劣势 订单状态定义 首先&#xff0c;我们需要定义订单的不同状态。在这个示例中&#xf…

ruoyi-vue-pro 前端vue js直接import导入本地文件使用方法

我的xml文件名称叫w2101.xml 第一步&#xff0c;删除所有依赖&#xff0c;否则配置以后就会启动报错&#xff1a; 第二步配置对应的文件格式&#xff0c;我当前使用的是xml文件 config.module.rule(xml).test(/\.xml$/).use(xml-loader).loader(xml-loader).end();第三步…

3D桌面端可视化引擎HOOPS Visualize如何实现3D应用快速开发?

HOOPS Visualize是一个开发平台&#xff0c;可实现高性能、跨平台3D工程应用程序的快速开发。一些主要功能包括&#xff1a; 高性能、以工程为中心的可视化&#xff0c;使用高度优化的OpenGL或DirectX驱动程序来充分利用可用的图形硬件线程安全的C和C#接口&#xff0c;内部利用…

计算机毕业设计选题之基于SSM的旅游管理系统【源码+PPT+文档+包运行成功+部署讲解】

&#x1f493;项目咨询获取源码联系v&#x1f493;xiaowan1860&#x1f493; &#x1f6a9;如何选题&#xff1f;&#x1f351; 对于项目设计中如何选题、让题目的难度在可控范围&#xff0c;以及如何在选题过程以及整个毕设过程中如何与老师沟通&#xff0c;有疑问不清晰的可…

企业如何选择合适自己的ERP系统?ERP系统应该具有哪些功能和特点?

企业如何选择合适自己的ERP系统&#xff1f;ERP系统应该具有哪些功能和特点&#xff1f; ERP作为一款功能如此众多、对企业如此重要的系统&#xff0c;可能会开源免费吗&#xff1f; 如果有这样一款功能全面又完全开源的ERP&#xff0c;早就爆火了&#xff0c;市面上可能还出…

easyocr

刚刚还想更新之前使用的paddleocr&#xff0c;但是发现他的whl文件网站崩了&#xff0c;估计就是最近的事&#xff0c;因为网上所有主流的讲解paddleocr的都用的同一个网站&#xff0c;没办法我顺便也试试github上有没有其他效果稍好的ocr吧 easyocr EasyOCR传送门 这个下载…

文心一言指令词宝典之自媒体篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint

文章目录 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint257.1 功能描述257.2 语法格式257.3 示例 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint 257.1 功能描…

X年后,ChatGPT会替代底层程序员吗?

能不能替代&#xff0c;真的很难说&#xff0c;因为机器换掉人&#xff0c;这其实是一个伦理问题。 其实说白了&#xff0c;任何行业在未来都会被AI或多或少的冲击到&#xff0c;因为ChatGPT做为一个可以持续提升智能的AI&#xff0c;在某些方面的智能程度超过人类并不是什么难…

分闸合闸、电源监视综合装置 HJZZ-91 DC220V 导轨安装Josef约瑟

系列型号&#xff1a; HJZZ-91分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/1分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/2分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/2A分闸、合闸、电源监视综合装置&#xff1b; HJZZ-92/3分闸、合闸、电源监视综合装置…

内网穿透FRPNPSSPPNgrok

目录 穿透上线 FRP&NPS&SPP&Ngrok Ngrok上线 frp上线 nps上线 spp特殊协议上线 穿透上线 FRP&NPS&SPP&Ngrok 主要目的是&#xff1a;实现在自己内网攻击机&#xff0c;去攻击另一个内网的靶机 让一个内网靶机主动连接我们的内网攻击机 Ngrok上线…

分治思想排序(快速排序、归并排序)

分治&#xff1a;分而治之&#xff0c;即把一个复杂的问题分成两个或更多的相同或相似的子问题&#xff0c;再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解&#xff0c;原问题的解即子问题的解的合并 优点&#xff1a; 降低时间复杂度&#xff1a;分治法可…

vscode教程

个人笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 个人随笔&#xff1a;工作总结随笔_8、以前工作中都接触过哪些类型的测试文档-CSDN博客 目录 一&#xff1a…