Java学习-常用工具-IO流

Java常用工具-IO流

1. 异常概述

什么是异常?

即非正常情况,通俗地说,异常就是程序出现的错误

异常的分类(Throwable)

  • 异常(Exception)
        合理的应用程序可能需要捕获的问题
        举例:NullPointerException
  • 错误(Error)
        合理的应用程序不应该试图捕获的问题
        举例:StackOverFlowError

2. 异常的处理方式

JVM默认的异常处理方式

在控制台打印错误信息,并终止程序

开发中异常的处理方式

  • try…catch(finally):捕获,自己处理
  • throws:抛出,交给调用者处理

try…catch

在这里插入图片描述
代码演示

/*
    方式一:try catch
        特点:
            处理完异常之后,程序会继续执行
        执行流程:
            先执行try()中的内容,看是否有问题(异常)
                没有:直接执行finally语句中的内容
                有:跳转到catch()语句中开始执行,再执行finally
        方式二:throws
 */
public class Test {
    public static void main(String[] args) {
        //通过try. catch .finally来处理异常
        try {
            //尝试要执行的代码
            int a = 10 / 0;
            System.out.println("a:" + a);
            return;
        } catch (Exception e) {
            //出现问题后的代码(解决方案)
            System.out.println("被除数不能为0");
            return;
        }finally {      //即使try,catch中有return,finally里边的代码也会执行
            System.out.println("看看我执行了吗?");
        }
        //System.out.println("看看我执行了吗?");
    }
}

运行结果
在这里插入图片描述

throws

在这里插入图片描述
代码演示

/*
        异常处理方式二:throws
            抛出异常,交给调用者处理

            特点:
                执行结束后,程序不再继续执行
 */
public class Test {
    public static void main(String[] args) throws Exception{
        //需求:调用show()
        //因为show()方法已经抛出了一个异常,作为调用者(main函数)必须处理这个异常.
        //方案一:接着抛
        //show();

        //方案二:采用try catch处理
        try {
            show();
        }catch (Exception e) {
            System.out.println("代码出问题啦!");
        }
        System.out.println("看看我执行了吗");
    }

    //定义一个方法
    public static void show() throws Exception{
        int a = 10 / 0;
        System.out.println("a:" + a);
    }
}

运行结果
在这里插入图片描述

3. IO流概述

什么是IO流?

I/O,即输入(Input)输出(Output),IO流指的是数据像连绵的流体一样进行传输。

IO流能干什么?

在本地磁盘和网络上操作数据

IO流的分类

  • 按数据流向分:
        输入流
        输出流
  • 按操作方式分:
        字节流:
         InputStream
         OutputStream
        字符流
         Reader
         Writer

IO流体系

  • 字符流:按字符读写数据的IO流
        Reader
         FileReader
         BufferedReader
        Writer
         FileWriter
         BufferedWriter
  • 字节流:按字节读写数据的IO流
        InputStream
         FileInputStream
         BufferedInputStream
        OutputStream
         FileOutputStream
         BufferedOutputStream

4. File类

概念

文件,文件夹,一个File对象代表磁盘上的某个文件或文件夹

  • 构造方法
        File(String pathname)
        File(String parent,String child)
        File(File parent,String child)
  • 成员方法
        createNewFile():创建文件
        mkdir()和mkdirs():创建目录
        isDirectory():判断File对象是否为目录
        isFile():判断File对象是否为文件
        exists():判断File对象是否存在
        getAbsolutePath():获取绝对路径
         绝对路径:以盘符开头的路径
         例如:D:/1.txt
        getPath():获取文件的相对路径
         相对路径:一般是相对于当前项目路径来讲的
         例如:1.txt
        getName():获取文件名
        list():获取指定目录下所有文件(夹)名称数组
        listFiles():获取指定目录下所有文件(夹)File数组

5. 字符流读写文件

字符流读取数据-按单个字符读取

在这里插入图片描述
代码演示

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReaderDemo1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流读取数据
        //1. 创建字符输入流对象
        Reader reader = new FileReader("lib/1.txt");
        //2. 读取数据
        /*int ch1 = reader.read();
        System.out.println(ch1);    //97
        int ch2 = reader.read();
        System.out.println(ch2);    //98
        int ch3 = reader.read();
        System.out.println(ch3);    //99
        int ch4 = reader.read();
        System.out.println(ch4);    //-1*/
        /*
            优化上述的读法,用循环改进
            又因为不知道循环次数,所以用while循环
         */
        //定义变量,用来接收读取到的字符
        int ch;
        /*
            (ch = reader.read()) != -1 做了三件事
                1. 执行了reader.read(),去文件中读取一个字符
                2. 执行ch = reader.read(),将读取到的字符赋值给变量
                3. (ch = reader.read()) != -1,用读取到的字符(内容)和-1进行比较
         */
        while ((ch = reader.read()) != -1) {
            //ch = reader.read();
            System.out.println(ch);
        }
        //3. 释放资源
        reader.close();
    }
}

1.txt里面的内容
abc
运行结果
在这里插入图片描述

字符流读取数据-按字符数组读取

在这里插入图片描述
代码演示

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReaderDemo2 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流读取数据,一次读取一个字符数组
        //1. 创建字符输入流对象
        Reader reader = new FileReader("lib/2.txt");
        //2. 读取数据
        /*char[] chs = new char[3];
        int len1 = reader.read(chs);
        System.out.println(chs);    //abc
        System.out.println(len1);   //3

        int len2 = reader.read(chs);
        System.out.println(chs);    //def
        System.out.println(len2);   //3

        int len3 = reader.read(chs);
        System.out.println(chs);    //gef
        System.out.println(len3);   //1

        int len4 = reader.read(chs);
        System.out.println(chs);    //gef
        System.out.println(len4);   //-1*/
        /*
            优化上述的代码,while循环
         */
        //定义字符数组
        char[] chs = new char[3];
        //定义一个变量,记录读取到的有效字符数
        int len;
        while ((len = reader.read(chs)) != -1) {
            //将读取到的内容,转换成字符串,然后打印
            /*
                chs:表示要操作的数组
                0:表示起始索引
                len:表示要操作的字符的个数
             */
            String s = new String(chs,0,len);   //[g,e,f] len = 1 只读取g 如果不写0,len 那么读取的就是gef
            System.out.println(s);
        }
        //3. 释放资源
        reader.close();
    }
}

2.txt里面的内容
abcdefg
运行结果
在这里插入图片描述

字符流写数据-按单个字符写入

在这里插入图片描述
代码演示

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterDemo {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流,写数据
        //1. 创建字符输出流对象
        Writer writer = new FileWriter("lib/1.txt");
        //2. 写数据
        //一次写一个字符
        writer.write('好');    //原来的文件里面的abc被好覆盖
        //3. 释放资源
        writer.close();
    }
}

运行结果
在这里插入图片描述

字符流写数据-按字符数组写入在这里插入图片描述

代码演示

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterDemo {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流,写数据
        //1. 创建字符输出流对象
        Writer writer = new FileWriter("lib/1.txt");
        //2. 写数据
        //一次写一个指定的字符数组
        char[] chs = {'新','年','快','乐','呀'};
        writer.write(chs,2,3);
        //3. 释放资源
        writer.close();
    }
}

运行结果
在这里插入图片描述

字符流写数据-按字符串写入

在这里插入图片描述
代码演示

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterDemo {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流,写数据
        //1. 创建字符输出流对象
        Writer writer = new FileWriter("lib/1.txt");
        //2. 写数据
        //一次写一个字符串
        writer.write("好好学习,天天向上");
        //3. 释放资源
        writer.close();
    }
}

运行结果
在这里插入图片描述

字符流拷贝文件-按单个字符读写

在这里插入图片描述
代码演示

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流拷贝文件,一次读写一个字符
        //例如:将1.txt文件中的内容复制到2.txt文件中
        /*
            IO流拷贝文件核心6步:
                1. 创建字符输入流对象,关联数据源文件
                2. 创建字符输出流对象,关联目的地文件
                3. 定义变量,记录读取到的内容
                4. 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
                5. 将读取到的数据写入到 目的地文件中
                6. 释放资源
         */
        //1
        //Reader reader = new FileReader("lib/1.txt");
        FileReader fr = new FileReader("lib/1.txt");
        //2
        FileWriter fw = new FileWriter("lib/3.txt");    //细节:如果目的地文件不存在,程序会自动创建
        //3
        int len;
        //4
        while ((len = fr.read()) != -1) {
            //5
            fw.write(len);
        }
        //6
        fr.close();
        fw.close();
    }
}

运行结果
在这里插入图片描述
在这里插入图片描述

字符流拷贝文件-按字符数组读写

在这里插入图片描述
代码演示

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyFile2 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流拷贝文件,一次读写一个字符数组
        //例如:将1.txt文件中的内容复制到2.txt文件中
        /*
            IO流核心6步
                1. 创建字符输入流对象,关联数据源文件
                2. 创建字符输出流对象,关联目的地文件
                3. 创建变量,用来记录读取到的有效字符数
                4. 通过循环进行读取,只要条件满足就一直读,并将读取到的有效字符数赋值给变量
                5. 将读取到的数据写入到目的地文件中
                6. 释放资源
         */
        //1
        FileReader fr = new FileReader("lib/1.txt");
        //2
        FileWriter fw = new FileWriter("lib/2.txt");
        //3
        //定义一个字符数组
        char[] chs = new char[1024];
        //用来记录读取到的有效字符数
        int len;
        //4
        while ((len = fr.read(chs)) != -1) {
            //
            fw.write(chs,0,len);
        }
        //6
        fr.close();
        fw.close();
    }
}

运行结果
在这里插入图片描述

字符缓冲流拷贝文件的标准代码

Demo1

在这里插入图片描述

代码演示

import java.io.*;

/*
    特点:
        字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB
 */
public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符缓冲流将1.txt文件中的内容拷贝到2.txt文件中。
        //1. 创建字符缓冲输入流对象,关联数据源文件
        //1.1 创建普通的字符输入流对象
        FileReader fr = new FileReader("lib/1.txt");
        //1.2 创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(fr);
        //简化上述的代码
        //BufferedReader br2 = new BufferedReader(new FileReader("lib/1.txt"));
        //2. 创建字符缓冲输出流对象,关联目的地文件
        //2.1 创建普通的字符输出流对象
        FileWriter fw = new FileWriter("lib/2.txt");
        //2.2 创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(fw);
        //3. 定义变量,记录读取到的数据
        int len;
        //4. 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = br.read()) != -1) {
            //5. 将读取到的数据写入到目的地文件中
            fw.write(len);
        }
        //6. 释放资源
        br.close();
        bw.close();
    }
}

运行结果
在这里插入图片描述

Demo2

代码演示

/*
    字符缓冲流用法:
        分类:
            BufferedReader:字符缓冲输入流(也叫高效字符输入流)
                成员方法:
                    public String readLine();   一次读取一行数据并返回读取到的内容,读不到就返回null;

            BufferedWriter:字符缓冲输出流(也叫高效字符输出流)
                成员方法:
                    public void newLine();      根据当前操作系统锅给对应的换行符
                                                windows操作系统: \r\n
                                                mac操作系统:     \r
                                                unix操作系统:    \n

        特点:字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB
        注意:字符流只能拷贝纯文本文件
 */
import java.io.*;

public class CopyFile2 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符缓冲流“一次读写一行”的方式,将1.txt文件中的内容拷贝到2.txt文件中
        //1. 创建字符缓冲输入流对象,关联数据源文件
        //FileReader fr = new FileReader("lib/1.txt");
        //BufferedReader br = new BufferedReader(fr);
        //合并版
        BufferedReader br = new BufferedReader(new FileReader("lib/1.txt"));
        //2. 创建字符缓冲输出流对象,关联目的地文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("lib/2.txt"));
        //3. 定义变量,记录读取到的内容
        String str;
        //4. 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((str = br.readLine()) != null) {
            //5. 将读取到的内容写入到目的地文件中
            bw.write(str);
            //千万注意一个小细节,你特别容易忽略
            //千万别忘记换行
            //bw.write("\r\n");
            bw.newLine();
        }
        //6. 释放资源
        br.close();
        bw.close();
    }
}

运行结果
在这里插入图片描述

6. 字节流读写文件

字节流拷贝文件 - 按单个字节读写

在这里插入图片描述
代码演示

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过普通的字节流,一次读写一个字节的方式,将a.jpg复制到b.jpg中
        //1. 创建字节输入流,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        //2. 创建字节输出流,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/b.jpg");
        //3. 定义变量,用来记录读取到的内容
        int len;
        //4. 循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = fis.read()) != -1) {
            //5. 将读取到的内容写入到目的地文件中
            fos.write(len);
        }
        //6. 释放资源
        fis.close();
        fos.close();
    }
}

运行结果
在这里插入图片描述
在这里插入图片描述

字节流拷贝文件 - 按字节数组读写

在这里插入图片描述
代码演示

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile2 {
    public static void main(String[] args) throws IOException {
        //需求:通过普通字节流一次读写一个字节数组的方式,将a.jpg复制到c.jpg中
        //1. 创建字节输入流,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        //2. 创建字节输出流,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/c.jpg");
        //3. 定义变量,用来接收读取到的内容
        byte[] bys = new byte[1024];
        //用来记录读取到的有效字节数
        int len;
        //4. 循环读取,只要条件满足就一直读,并将读取到的内容(有效的字节数)赋值给变量
        while ((len = fis.read()) != -1) {
            //5. 将读取到的数据写入到目的地文件中
            fos.write(bys,0,len);
        }
        //6. 释放资源
        fis.close();
        fos.close();
    }
}

运行结果
在这里插入图片描述

字节缓冲流拷贝文件的标准代码

在这里插入图片描述
代码演示

import java.io.*;

/*
    特点:
        字节缓冲流有自己的缓冲区,大小为8192个字节,也就是8KB
    总计:
        拷贝纯文本文件使用字符流,拷贝其他(图片、音频、视频等)使用字节流
 */
public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字节缓冲流,将a.jpg复制到d.jpg中
        //1. 创建字节输入流对象,关联数据源文件
        //创建普通的字节输入流
        //FileInputStream fis = new FileInputStream("lib/a.jpg");
        //创建高效的字节输入流
        //BufferedInputStream bis = new BufferedInputStream(fis);
        //合并版
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lib/a.jpg"));
        //2. 创建字节输出流对象,关联目的地文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/d.jpg"));
        //3. 定义变量,用来记录读取到的内容
        int len;
        //4. 循环读取,只要条件满足就一直读,然后读取到的内容赋值给变量
        while ((len = bis.read()) != -1) {
            //5. 将读取到的内容写入到目的地文件中
            bos.write(len);
        }
        //6. 释放资源
        bis.close();
        bos.close();
    }
}

运行结果
在这里插入图片描述

案例:模拟文件上传功能

在这里插入图片描述
代码演示

import java.io.*;
import java.util.Scanner;

public class UpdateFile {
    public static void main(String[] args) throws IOException {
        //需求:模拟用户上传头像的功能,假设所有的用户头像都应上传到:项目下的lib文件夹中
        //1. 定义一个方法,用来获取要上传的用户头像的路径:    getPath();
        File path = getPath();
        System.out.println(path);   //C:\Users\hp\Desktop\1\psc.jpg
        //2. 定义一个方法,用来判断要上传的用户头像,在lib文件夹中是否存在
        boolean flag = isExists(path.getName());
        //3. 如果存在,提示:该用户头像已经存在,上传失败
        if (flag) {
            System.out.println("该用户头像已经存在,上传失败");
        } else {
            //4. 如果不存在,就上传该用户头像,并提示上传成功
            //System.out.println("我马上要上传了,代码等下写");
            //数据源文件                 目的地文件
            //e:/picture/psc.jpg   ->   lib/psc.jpg
            uploadFile(path);
        }
    }

    //1.定义一个方法,用来获取要上传的用户头像的路径:getPath();

    /**
     * 用来获取要上传的用户头像的路径
     * @return  具体要上传的用户头像的路径
     */
    public static File getPath() {
        //1. 提示用户录入要上传的用户头像路径,并接收
        Scanner sc = new Scanner(System.in);
        //7. 因为不知道用户多少次能录入正确,所以用while(ture)改进
        while (true) {
            System.out.println("请录入您要上传的用户头像的路径:");
            String path = sc.nextLine();

            //2. 判断该路径的后缀名是否是: .jpg .png .bmp
            //3. 如果不是,就提示:您录入的不是图片,请重新录入
            if (!path.endsWith(".jpg") && !path.endsWith(".png") && !path.endsWith(".bmp")) {
                System.out.println("您录入的不是图片,请重新录入");
                //细节,千万注意,别忘了写
                continue;
            }

            //4. 如果是,程序接着执行,判断该路径是否存在,并且是否是文件
            File file = new File(path);
            if (file.exists() && file.isFile()) {
                //6. 如果是,说明就是我们想要的数据(图片,文件),直接返回
                return file;
            } else {
                //5. 如果不是,就提示:您录入的路径不合法,请重新录入
                System.out.println("您录入的路径不合法,请重新录入");
            }
        }
    }

    //2. 定义一个方法,用来判断要上传的用户头像,在lib文件夹中是否存在
    public static boolean isExists(String path) {
        //1. 将lib文件夹封装成File对象
        File file = new File("lib");
        //2. 获取lib文件夹中所有的文件(夹)的名称数组
        String[] names = file.list();
        //3. 遍历第二步获取到的数组,用获取到的数据依次和path进行比较
        for (String name : names) {
            if (name.equals(path)) {
                //4. 如果一致,说明该用户头像已经存在了,就返回true
                return true;
            }
        }
        //5. 如果不一致,说明该用户头像不存在,就返回false
        return false;
    }

    //4. 定义方法,用来上传具体的用户头像

    /**
     * 用来上传具体的用户头像
     * @param path  数据源文件路径
     */
    public static void uploadFile(File path) throws IOException {
        //1. 创建字节输入流,关联数据源文件
        //FileInputStream类中的构造方法
        // public FileInputStream(File file)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));   //path: e:/picture/psc.jpg
        //2. 创建字节输出流,关联目的地文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/" + path.getName()));    // lib/psc.jpg
        //3. 定义变量,记录读取到的数据
        int len;
        //4. 循环读取,只要条件满足就一直读,并将读取到的数据赋值给变量
        while ((len = bis.read()) != -1) {
            //5. 将读取到的数据写入到目的地文件中
            bos.write(len);
        }
        //6. 释放资源
        bis.close();
        bos.close();

        System.out.println("上传成功");
    }
}

运行结果
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值