Java高级之File类、节点流、缓冲流、转换流、标准I/O流、打印流、数据流

第13章 IO流

文章目录

一、File类的使用

  1. File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
  2. FiLe类声明在java.io包下
  3. File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用Io流来完成。
  4. 后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的"终点"

1.1、如何创建File类的实例

java 复制代码
File(String filePath)
File(String parentPath, String childPath)
File(String parentFile, String childPath)
  1. 相对路径:相较于某个路径下,指明的路径。

  2. 绝对路径:包含盘符在内的文件或文件目录的路径

  3. 路径分隔符:

    windows: \\

    unix: /

说明:

IDEA中:如果开发使用JUnit中的单元测试方式测试,相对路径即为当前Module下。如果使用main()测试,相对路径即为当前的Project下。

Eclipse中:不管使用单元测试方法还是使用main()测试,相对路径即为当前的Project下。

1.2、常用方法

1.2.1、File类的获取功能

java 复制代码
public String getAbsolutePath():获取绝对路径
public String getPath() :获取路径
public String getName() :获取名称
public String getParent():获取上层文件目录路径。若无,返回null
public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified() :获取最后一次的修改时间,毫秒值
public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
java 复制代码
@Test
public void test2(){
    File file1 = new File("hello.txt");
    File file2 = new File("D:\\JAVA NOTES\\核心基础笔记\\Java高级编程\\hi.txt");
    System.out.println(file1.getAbsoluteFile());
    System.out.println(file1.getPath());
    System.out.println(file1.getName());
    System.out.println(file1.getParent());
    System.out.println(file1.length());
    System.out.println(new Date(file1.lastModified()));


    System.out.println("----------------------");
    System.out.println(file2.getAbsoluteFile());
    System.out.println(file2.getPath());
    System.out.println(file2.getName());
    System.out.println(file2.getParent());
    System.out.println(file2.length());
    System.out.println(file2.lastModified());
}

@Test
public void test3(){
    File file = new File("F:\\ProjectsLocation\\IdeaProjects\\Indomitable\\src");
    String[] list = file.list();
    for (String s:list){
        System.out.println(s);
    }

    File[] listFiles = file.listFiles();
    for (File f:listFiles){
        System.out.println(f);
    }
}

1.2.2、File类的重命名功能

java 复制代码
/**
 * public boolean renameTo(File dest):把文件重命名为指定的文件路径
 * 比如: file1.renameTo(file2)为例:
 *      要想保证返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在。
 */
@Test
public void test4(){
    File file1 = new File("hello.txt");
    File file2 = new File("he.txt");

    boolean rename = file1.renameTo(file2);
    System.out.println(rename);
}

1.2.3、File类的判断功能

java 复制代码
public boolean isDirectory():判断是否是文件目录 

public boolean isFile() :判断是否是文件 

public boolean exists() :判断是否存在 

public boolean canRead() :判断是否可读 

public boolean canWrite() :判断是否可写 

public boolean isHidden() :判断是否隐藏
java 复制代码
@Test
public void test5(){
    File file1 = new File("F:\\ProjectsLocation\\IdeaProjects\\Indomitable\\src");

    System.out.println(file1.isDirectory());
    System.out.println(file1.isFile());
    System.out.println(file1.exists());
    System.out.println(file1.canRead());
    System.out.println(file1.canWrite());
    System.out.println(file1.isHidden());

    System.out.println("***************");

    File file2 = new File("hello.txt");

    System.out.println(file2.isDirectory());
    System.out.println(file2.isFile());
    System.out.println(file2.exists());
    System.out.println(file2.canRead());
    System.out.println(file2.canWrite());
    System.out.println(file2.isHidden());
}

1.2.4、File类的创建功能

java 复制代码
public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false

public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。
如果此文件目录的上层目录不存在,也不创建。

public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目
路径下。
java 复制代码
@Test
public void test7(){
    //文件目录的创建
    File file1 = new File("D:\\Java\\1.尚硅谷全套JAVA教程--基础阶段(73.36GB)\\尚硅谷宋红康Java核心基础_好评如潮\\Java基础全套视频教程\\day25_泛型与File\\20230527");

    boolean mkdir = file1.mkdir();
    if (mkdir){
        System.out.println("创建成功1");
    }

    File file2 = new File("D:\\Java\\1.尚硅谷全套JAVA教程--基础阶段(73.36GB)\\尚硅谷宋红康Java核心基础_好评如潮\\Java基础全套视频教程\\day25_泛型与File\\20230528");
    boolean mkdirs = file2.mkdirs();//级联创建
    if (mkdirs){
        System.out.println("创建成功2");
    }
}

1.2.5、File类的删除功能

java 复制代码
public boolean delete():删除文件或者文件夹
删除注意事项:
Java中的删除不走回收站。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

二、IO流原理及流的分类

2.1、Java IO原理

  1. I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于 处理设备之间的数据传输。如读/写文件,网络通讯等。
  2. Java程序中,对于数据的输入/输出操作以"流(stream)" 的 方式进行。
  3. java.io包下提供了各种"流"类和接口,用以获取不同种类的 数据,并通过标准的方法输入或输出数据。

输入input:读取外部数据(磁 盘、光盘等存储设备的数据)到 程序(内存)中。

输出output:将程序(内存) 数据输出到磁盘、光盘等存储设备中。

2.2、流的分类/体系结构

  • 按操作数据单位 不同分为:字节流(8 bit),字符流(16 bit)
  • 按数据流的流向 不同分为:输入流,输出流
  • 按流的角色 的不同分为:节点流,处理流

流的分类理解示意图:

三、节点流(或文件流)

bash 复制代码
* 抽象基类             节点流(或文件流)           缓冲流(处理流的一种)
InputStream          FileInputStream (read(byte[] buffer))       BufferedInputStream (read(byte[] buffer,0,len))
 * OutputStream         FileOutPutStream (write(byte[] buffer,0,len))     BufferedOutputStream (write(byte[] buffer))
 * Reader               FileReader (read(char[] cbuf))              BufferedReader (read(char[] cbuf))
 * Writer               FileWriter (write(char[] cbuf,0,len))             BufferedWriter (write(char[] cbuf,0,len))

本章步骤:

java 复制代码
1.实例化File类的对象,指明要操作的文件
2.提供具体的流
3.数据的读入
4.流的关闭操作

3.1、读入数据 FileReader

java 复制代码
    @Test
    public void test1(){
        FileReader fr = null;
        try {
            //1.实例化File类的对象,指明要操作的文件
            File file = new File("hello.txt ");//相较于当前Module
            //2.提供具体的流
            fr = new FileReader(file);
            //3.数据的读入
            //read():返回读入的一个字符。如果达到文件末尾,返回 -1
            //方式一
//        int data = fr.read();
//        while (data != -1){
//            System.out.print((char)data);
//            data = fr.read();
//        }

            //方式二:语法上针对方式一的修改
            int data;
            while ((data = fr.read()) != -1){
                System.out.print((char)data);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //4.流的关闭操作
            try {
                //可能会有空指针异常
                if (fr != null){
                    fr.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

对 read()操作升级:使用read 的重载方法

java 复制代码
@Test
    public void test2() throws IOException {
        FileReader fr = null;
        try {
            //1.File类的实例化
            File file = new File("hello.txt ");//相较于当前Module
            //2.FileReader流的实例化
            fr = new FileReader(file);
            //3.读入的操作
            char[] cbuf = new char[5];
            int len;
            while ((len = fr.read(cbuf)) != -1){
//                //方式一
//                for (int i=0;i<len; i++){
//                    System.out.print(cbuf[i]);
//                }

                //方式二
                String s = new String(cbuf, 0, len);
                System.out.print(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //4.资源的关闭
                if (fr != null){
                    fr.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

3.2、写出数据 FileWriter

从内存中写出数据的到硬盘文件的操作

说明:

  1. 输出操作,对应的File可以不存在,并不会报异常

  2. File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件

    ​ File对应的硬盘中的文件如果存在:

    ​ ① 如果流使用的构造器是 FileWriter(file, false) / FileWriter(file):对原有文件的覆盖

    ​ ② 如果流使用的构造器是 FileWriter(file, true):不会对原有文件覆盖,而是在原有文件基础上追加内容

java 复制代码
/**
     * 从内存中写出数据的到硬盘文件的操作
     * 说明:
     * 1.输出操作,对应的File可以不存在,并不会报异常
     * 2.File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件
     *   File对应的硬盘中的文件如果存在:
     *      如果流使用的构造器是 FileWriter(file, false) / FileWriter(file):对原有文件的覆盖
     *      如果流使用的构造器是 FileWriter(file, true):不会对原有文件覆盖,而是在原有文件基础上追加内容
     */
@Test
public void  testFileWriter() throws IOException {
    //1.提供File类的对象,指明写出搭配的文件
    File file = new File("hello1.txt");

    //2.提供FileWriter的对象,用于数据的写出
    FileWriter fw = new FileWriter(file, true);

    //3.写出的操作
    fw.write("I hava a little dream!\n");
    fw.write("You need to hava a dream!\n");

    //4.流资源的关闭
    fw.close();
}

3.3、使用FileReader 和 FileWriter 实现文本文件的复制

步骤:

java 复制代码
1.创建File类的对象,指明读入和写出的文件
2.提供输入流和输出流的对象
3.数据的读入和写出操作
4.关闭流资源
java 复制代码
@Test
public void testFileReaderFileWriter(){
    FileWriter fw = null;
    FileReader fr = null;
    try {
        //1.创建File类的对象,指明读入和写出的文件
        File srcFile = new File("hello.txt");
        File destFile = new File("hello2.txt");

        //2.提供输入流和输出流的对象
        fr = new FileReader(srcFile);
        fw = new FileWriter(destFile);

        //3.数据的读入和写出操作
        char[] cbuf = new char[5];
        int len;//记录每次读入到cbuf数组中的字符个数
        while ((len = fr.read(cbuf)) != -1){
            //每次写出 len个字符
            fw.write(cbuf, 0, len);
        }

    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        //4.关闭流资源
        try {

            if (fw != null) {
                fw.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if (fr != null){
                fr.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.4、FileInputStream

总结:

  • 1.对于文本文件(.txt, .java, .c, .cpp), 使用字符流处理
  • 2.对于非文本文件(.jpg, .mp3, .mp4, .avi, .doc, .ppt, ...),使用字节流处理
java 复制代码
/**
 * 使用字节流 FileInputStream 处理文本文件,可能出现乱码
 */
@Test
public void test1() throws IOException {
    FileInputStream fis = null;
    try {
        //1.造文件
        File file = new File("hello.txt");
        //2.造流
        fis = new FileInputStream(file);

        //3.读数据
        byte[] buffer = new byte[5];
        int len;//记录每次读取的字节的个数
        while ((len = fis.read(buffer)) != -1){
            String str = new String(buffer, 0, len);
            System.out.print(str);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //4.关闭流
        try {
            if (fis != null){
                fis.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.5、使用FileInputStream和FileOutputStream实现对图片的复制操作

java 复制代码
/**
 * 使用FileInputStream和FileOutputStream实现对图片的复制操作
 */
@Test
public void testFileInputOutputStream(){
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        //1.造文件
        File srcFile = new File("头像.jpg");
        File destFile = new File("头像2.jpg");
        //2.造流
        fis = new FileInputStream(srcFile);
        fos = new FileOutputStream(destFile);

        //3.复制
        byte[] buffer = new byte[5];
        int len;//记录每次读入的长度
        while ((len = fis.read(buffer)) != -1){
            fos.write(buffer, 0, len);
        }
        System.out.println("复制成功!");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //4.关闭流
        try {
            if (fis != null){
                fis.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if (fos != null){
                fos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

四、处理流之一---缓冲流

java 复制代码
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

作用:提供流的读取、写入的速度

提高读写速度的原因:内部提供了一个缓冲区

4.1、使用BufferedInputStream和BufferedOutputStream实现对图片的复制操作

java 复制代码
/**
     * 实现非文本文件的复制
     */
    @Test
    public void BufferedStreamTest(){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.造文件
            File srcFile = new File("头像.jpg");
            File destFile = new File("头像3.jpg");

            //2.造流
            //2.1 造节点流
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节:读取、写入
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭流:要求:先关闭外层的流,再关闭内层的流
            //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可哟自动省略。
            if (bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            if (bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

//        fis.close();
//        fos.close();
    }

4.2、实现文件的复制

步骤:

java 复制代码
1.造文件
2.造流
	2.1 造节点流
	2.2 造缓冲流
3.复制的细节:读取、写入
4.关闭流:要求:先关闭外层的流,再关闭内层的流
    说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可哟自动省略。
java 复制代码
	/**
     * 实现文件复制的方法
     */
    public void copyFileWithBuffered(String srcPath, String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.造文件

            File srcFile = new File(srcPath);
            File destFile = new File(destPath);

            //2.造流
            //2.1 造节点流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节:读取、写入
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);

                //bos.flush();//刷新缓冲过去
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.关闭流:要求:先关闭外层的流,再关闭内层的流
            //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可哟自动省略。
            if (bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            if (bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

//        fis.close();
//        fos.close();
    }

五、处理流之二---转换流

1、转换流:属于字符流

InputStreamReader: 将一个字节的输入流转换为字符的输入流--->解码

OutputStreamReader: 将一个字符的输入流转换为字节的输出流--->编码

2、作用:提供字节流与字符流之间的转换

3、解码 :字节、字节数组 ---> 字符数组、字符串

​ 编码 :字符数组、字符串 ---> 字节、字节数组

5.1、InputStreamReader的使用

java 复制代码
/**
     * 此时处理异常的话,仍应该使用try-catch-finally
     * InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
     */
    @Test
    public void test1() throws IOException {
        FileInputStream fis = new FileInputStream("dbcp.txt");
        //参数2 指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
        InputStreamReader isr = new InputStreamReader(fis, "utf-8");
//        InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集:UTF-8

        char[] cbuf = new char[20];
        int len;
        while ((len = isr.read(cbuf)) != -1){
            String str = new String(cbuf, 0, len);
            System.out.print(str);
        }

        isr.close();
    }

5.2、综合使用 InputStreamReader 和 OutputStreamWriter

java 复制代码
/**
 * 综合使用 InputStreamReader 和 OutputStreamWriter
 */
@Test
public void test2() throws Exception{
    //1. 造文件、造流
    File file1 = new File("dbcp.txt");
    File file2 = new File("dbcp_gbk.txt");

    FileInputStream fis = new FileInputStream(file1);
    FileOutputStream fos = new FileOutputStream(file2);

    InputStreamReader isr = new InputStreamReader(fis, "utf-8");
    OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");

    //2.读入和写出的过程
    char[] cbuf = new char[20];
    int len;
    while ((len = isr.read(cbuf)) != -1){
        osw.write(cbuf, 0, len);
    }

    //3.关闭资源
    fis.close();
    fos.close();
}

5.3、多种字符集编码

编码表的由来

计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识 别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表。 这就是编码表。

常见的编码表

  1. ASCII:美国标准信息交换码。
    • 用一个字节的7位可以表示。
  2. ISO8859-1 :拉丁码表。欧洲码表。
    • 用一个字节的8位表示。
  3. GB2312:中国的中文编码表。最多两个字节编码所有字符
  4. GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
  5. Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
  6. UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。

六、标准输入、输出流

6.1、练习题

java 复制代码
/**
 * 练习:
 * 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续
 * 进行输入操作,直至当输入"e"或者"exit"时,退出程序。
 */
public static void main(String[] args) {
    BufferedReader br = null;
    try {
        InputStreamReader isr = new InputStreamReader(System.in);
        br = new BufferedReader(isr);
        String data;
        while (true){
            System.out.println("请输入字符串: ");
            data = br.readLine();
            if ("e".equalsIgnoreCase(data)|| "exit".equalsIgnoreCase(data)){
                System.out.println("程序结束");
                break;
            }

            String upperCase = data.toUpperCase();
            System.out.println(upperCase);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        if (br !=  null){
            try {
                br.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

七、打印流

八、数据流

相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔9 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社10 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海10 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨11 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区13 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai14 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说14 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json