javaio流比较完整的总结

本文全面总结了Java中的IO流,包括File类的使用、各种IO流的分类与操作,如FileReader/Writer、FileInputStream/OutputStream、缓冲流、转换流等,还介绍了标准输入输出流和数据流的基础概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

javaio流总结

File类介绍

1.File类的理解:

  1. file类的一个对象,代表了一个文件或者文件夹
  2. file类声明在java.io包下
  3. file类涉及到文件或者目录的创建,删除,重命名,查看等方法,并未涉及到写入或者读取文件内容的操作,如果需要写入或者读取需要通过io流来完成
  4. 后续file类的对象常作为参数传递到流的构造器中,指明读取或写入的终点

2.File类的实例化

  1. 常用的构造器

    File(String filePath)

    File(String parentPath,String childPath)

    File(File parentFile,String childPath)

  2. 路径的分类

    相对路径:相较于某个路径下,知名的路径

    绝对路径:包含盘符在内的文件或者文件夹路径

  3. 路径分隔符

    windows和dos系统默认使用"\"来表示

    unix和url使用"/"来表示

3.File类中的一些常用方法

public String getAbsolutePath()//获取绝对路径

public String getPath()//获取路径

public String getName()//获取名称

public string getParent()//获取上层文件目录路径,若无返回null

public long length()//获取文件长度(即:字节数),不能获取目录的长度

public long lastModified()//获取最后一次修改的时间,毫秒值

public String[] list()//获取指定目录下的所有文件或者文件目录的名称数组

public boolean renameTo(File dest)//把文件重命名为指定的文件路径

public boolean isDirectory()//判断是否是文件夹

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

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

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

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

public boolean isHidden()//判断是否隐藏

public boolean createNewFile()//创建文件

public boolean mkdirs()//创建目录

public boolean delete()//删除文件或者目录,如果是删除目录,那么目录下不能有文件或者文件夹

IO流介绍

io流是什么:i代表input输入,o代表output输出

输入输出流的意思:Java程序进行数据传输的管道,这个流就是管道的意思

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

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

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

我们应该处在程序中来判断这是输入还是输出,不应该从内存的位置来看

io流的分类:

  • 按操作数据单位不同分为:字节流(8bit)(非文本的数据都主要用字节流来处理)和字符流(16bit)(文本数据主要用字符流来处理)
  • 按数据流的流向不同可以分为:输入流和输出流
  • 按流的角色不同分为:节点流和处理流

下面来看具体的一个图

主要解释一下节点流和处理流

节点流就相当于直接用一根管道把数据和程序连接起来,而处理流就是在这个管道的上面再加上一个管道,可以加速数据的传输,处理流可以多次叠加

流的分流

java的Io流共涉及到40多个类,实际上非常规则都是,都是从下面这四个基类派生的,这些子类名称都是父类名称作为后缀的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ma27rhF4-1604632941624)(C:\Users\24239\Desktop\数据库截图\屏幕截图 2020-11-05 092026.png)]

下面来看下io流的一个体系
io流体系

在这上面中处了访问文件的四个流是节点流之外,它以下的所有流都是处理流,其中蓝色表示的流是主要用到的流

当我们看到一个流时,应该马上就能知道它是出于什么流,我们主要通过流的后面部分来判断这是一个什么流。

FileReader流和FileWriter流的操作

我们可以通过FileReader来读取文件,通过FileWriter来写入文件,结合两种可以进行文件的复制,但是不能用来处理图片,下面通过代码来看下

public class FileReaderWriterTest {
    private FileReader filereader;
    //单元测试Test,这个也是可以运行的,和Main方法中的相对路径的不同
    //单元测试中的相对路径是基于Module的
    //Main方法中的相对路径是基于Project的
    @Test
    //throws没有try catch finally 好用
    public void fileReaderTest01()  {
        //为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally
        try {
            //这个相对路径是较于当前Module中的(io流)
            //1、实例化File对象,指明我们要操作的文件
            //读入的文件一定要存在,不然会出现错误
            File file = new File("hello.txt");
            //2、提供具体的流,流的实例化
            filereader = new FileReader(file);
            //3、数据的读入
            //read():返回读入的一个字符,如果达到末尾,返回-1
            //字符char是可以自动转换成为int的
            //方式一
        /*int data = filereader.read();//data返回的是-1表示文件已经读完
        while (data != -1) {
            System.out.print((char) data);
            data = filereader.read();
        }*/
            //方式二,语法上的修改
            int data1;
            while ((data1 = filereader.read()) != -1){
                System.out.print((char)data1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、流的关闭操作
            try {
                filereader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //对read()操作升级,使用read的重载方法
    @Test
    public void FileReaderTest02(){
        FileReader f1 = null;
        try {
            //File类的实例化
            File file = new File("hello.txt");
            //FileReader流的实例化
            f1 = new FileReader(file);
            //读取的操作
            //read(char[] cbuf):返回每次读入cbuf数组中的字符个数,达到文件末尾返回-1
            char[] cbuffer = new char[1024];
            int data ;
            while ((data = f1.read(cbuffer)) != -1){
                //方式一
//                for (int i = 0; i < cbuffer.length; i++) {
//                    System.out.print(cbuffer[i]);
//                }这样写是有问题的,当最后读取的字符不够五个时,依然是输出五个字符,因为它是采用填充式的
//                ,不够的字符依然采用上一次没有被覆盖的字符
                //正确的写法
                for (int i = 0; i < data; i++) {
                    System.out.print(cbuffer[i]);
                }
                //方式二
//                String str = new String(cbuffer);
//                System.out.println(str);
//                这种错误和方式一中的错误是一样的,都会多输出
                //正确方式
                //这个构造器就是输出你输入进来的字符个数,
                /*String str = new String(cbuffer,0,data);
                System.out.println(str);*/
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(f1 != null){
                try {
                    //资源的关闭
                    f1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //从内存中写出数据到硬盘文件中
    /*
    * 说明
    * 输出操作,对应的File可以不存在,如果不存在,在输出地过程中会自动地创建
    *               如果存在,想要接着写,就要在创建FileWriter流的时候,进行说明
    *               fw = new FileWriter(file,true);表示接着写
    *               fw = new FileWriter(file);表示写入的内容会把原来的内容给覆盖住
    *               fw = new FileWriter(file,false);表示写入的内容会把原来的内容给覆盖住
    * */
    @Test
    public void fileWriterTest(){
        FileWriter fw = null;
        try {
            //提供File类的对象,指明写出到的文件
            //写出时文件不存在时,会自动地帮我们创建,
            File file = new File("hello1.txt");
            //提供FileWriter流的实例化,用于数据的写出
            fw = new FileWriter(file,true);
            //写入操作
            fw.write("I have a dream!\n");//可以写入字符串或者字符数组
            fw.write("You need to a dream!\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭
            if (fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //文件的复制功能的实现
    @Test
    public void FileWriterFileReaderTest(){
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1、创建File类对象,指明读入和写出的文件
            File file1 = new File("hello1.txt");
            File file2 = new File("hello.txt");
            //2、创建输入流和输出流的对象
            fr = new FileReader(file1);
            fw = new FileWriter(file2);
            //3、数据的读入和写出操作
            char[] cbuf = new char[5];
            int data1 ;//记录每次读入到cbuf数组中的字符个数
            while ((data1 = fr.read(cbuf)) != -1){
//                for (int i = 0; i < data1; i++) {
//                    fw.write(cbuf[i]);
//                }
                //也可以直接就下面这样写
                fw.write(cbuf,0,data1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            /*if(fr != null || fw != null){
                try {
                    //4、关闭流资源
                    fr.close();
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }//这是我写的
            }*/
            //谁先关,谁后关没有关系,有两种方式来释放
            //第一种,两个都会执行
            try {
                if (fr != null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fw != null){
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            //第二种
            /*try {
                if (fr != null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fw != null){
                        fw.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }*/
        }
    }
}

FileInputStream流和FileOutputStream流的操作

如果我们需要对图片、视频等字节资源进行操作我们就要使用FileInputStream和FileOutputStream来操作,下面来看代码

//测试FileInputStream和FileOutputStream的使用
public class FileInputOutputStreamTest {

    //测试图片的复制
    @Test
    public void FileInputOutputStreamTest()  {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //File类的创建
            File file1 = new File("流的分类.png");//被复制的图片
            File file2 = new File("流的分类2.png");//复制后的图片
            //创建流的实例
            fis = new FileInputStream(file1);
            fos = new FileOutputStream(file2);
            //复制的过程
            byte[] buffer = new byte[1024];
            int data ;
            while ((data = fis.read(buffer)) != -1){
                fos.write(buffer,0,data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭
            try {
                if (fis != null) {
                    fis.close();
                }

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

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


    }
}

我们可以写一个复制的方法来实现对非文本的复制

//指定路径下文件的复制方法
    public void copyFile(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //File类的创建
            File file1 = new File(srcPath);
            File file2 = new File(destPath);
            //创建流的实例
            fis = new FileInputStream(file1);
            fos = new FileOutputStream(file2);
            //复制的过程
            byte[] buffer = new byte[1024];
            int data ;
            while ((data = fis.read(buffer)) != -1){
                fos.write(buffer,0,data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭
            try {
                if (fis != null) {
                    fis.close();
                }

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

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

    }

    @Test
    public void testCopy(){
        long start = System.currentTimeMillis();
        copyFile("鄙视链.png","鄙视链2.png");
        long end = System.currentTimeMillis();
        long result = end - start;//复制一张图片需要的时间(毫秒)
        System.out.println(result);
    }

其实上面的方法也可以用来复制文本,但是不能在控制台输出,有可能会乱码,

字节流也可以用来文本,就是不能在控制台输出,但是字符流不能用来复制非文本

缓冲流操作

缓冲流由于有了一个缓冲区,所以速度要file类的快

    //实现非文本文件的复制
    @Test
    public void BufferedStreamTest()  {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //可以简写一二两步
            //BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("鄙视链.png")));

            //1、创建File对象
            File srcfile = new File("鄙视链.png");
            File destfile = new File("鄙视链3.png");
            //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 data;
            while((data = bis.read(buffer)) != -1){
                bos.write(buffer,0,data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //资源的关闭
            //要求:先关闭外层的流,在关闭内层的流
            //关闭四个流
            try {
                if (bos != null) {
                    bos.close();
                }

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

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
//说明,再关闭外层流的时候,内层流也会进行自动的关闭,我们可以省略内层流的关闭
//        fos.close();
//        fis.close();

    }
    public void copyFileWithBuffered(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1、创建File对象
            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 data;
            while((data = bis.read(buffer)) != -1){
                bos.write(buffer,0,data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //资源的关闭
            //要求:先关闭外层的流,在关闭内层的流
            //关闭四个流
            try {
                if (bos != null) {
                    bos.close();
                }

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

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
//说明,再关闭外层流的时候,内层流也会进行自动的关闭,我们可以省略内层流的关闭
//        fos.close();
//        fis.close();

    }
    @Test
    public void testBuffered(){
        long start = System.currentTimeMillis();
        String srcPath = "C:\\Users\\24239\\Videos\\录像\\整合好应用.mp4";
        String destPath = "C:\\Users\\24239\\Videos\\录像\\整合好应用01.mp4";
        copyFileWithBuffered(srcPath,destPath);
        long end = System.currentTimeMillis();
        long result = end - start;
        System.out.println("复制的时间是:"+result+"毫秒");//24毫秒

    }

//使用BufferedReader和BufferedWriter实现文本文件的复制
    @Test
    public void BufferedReaderBufferedWriterTest()  {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //1、创建File对象
            File file1 = new File("hello.txt");
            File file2 = new File("hello2.txt");
            //2、创建流对象
            //2、1创建FileWriter和FileReader对象
            FileReader fr = new FileReader(file1);
            FileWriter fw = new FileWriter(file2);
            //2、2创建BufferedWriter和BufferedReader对象
            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);
            //3、复制操作,有两种方式
            //方式一,使用Char[]数组
            /*char[] buffer = new char[1024];
            int data ;
            while((data = br.read(buffer)) != -1){
                bw.write(buffer,0,data);
            }*/
            //方式二,使用String
            String data;
            while ((data = br.readLine()) != null){//一次读取一行
                //换行的两种方式
                //方法一
                bw.write(data +"\n");//data中不包含换行
                //方式二
                /*bw.write(data);
                bw.newLine();*/
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流资源,只需关闭外层即可,内层会自动地关闭,我们可以省略
            try {
                if (br != null) {
                    br.close();
                }

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

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
//        关闭流资源
//        br.close();
//        bw.close();

    }

下面来看下我们在上面中使用到的不同的构造方法
不同的构造方法

转换流操作

转换流实现了字符流和字节流之间的转换

Java中提供了两个转换流

  • InputStreamReader:将InputStream转换为Reader
  • OutputStreamWriter:将OutputStream转换为Writer

字节流中的数据都是字符时,转换为字符流操作更加高效

很多时候我们使用转换流来处理文件乱码问题。实现编码和解码功能

转换流的过程

下面就来看下这两个流的使用

//测试转换流
//转换流,属于字符流:
// InputStreamReader:将一个字节的输入流转换为字符的输入流
// outputStreamWriter:将一个字符的输出流转化为字节的输出流
//作用:提供字节流和字符流之间的转换
//解码:字节,字节数组->字符串,字符数组
//编码:字符串,字符数组->字节,字节数组

import org.junit.Test;

import java.io.*;

//字符集
public class InputStreamReaderTest {
    @Test
    public void test1()  {
        InputStreamReader isr2 = null;
        try {
            //1、创建File对象
            FileInputStream fis = new FileInputStream("hello.txt");
            //使用系统默认的字符集,默认的是utf-8
            //InputStreamReader isr1 = new InputStreamReader(fis);
            //参数2,指明了字符集,具体使用什么字符集,取决于文件hello.txt保存时使用的字符集
            isr2 = new InputStreamReader(fis,"UTF-8");
            char[] cbuf = new char[1024];
            int data ;
            while ((data = isr2.read(cbuf)) != -1){
                //输出到控制台
                String str = new String(cbuf,0,data);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (isr2 != null) {
                    //还是只要关闭最外层的流即可
                    isr2.close();
                }

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

    }
    //综合使用InputStreamReader 和 outputStreamWriter
    @Test
    public void test2()  {
        InputStreamReader isr = null;
        OutputStreamWriter osw = null;
        try {
            //创建File对象
            File file1 = new File("hello.txt");
            File file2 = new File("hello_gbk.txt");//这个文件在idea中打开中文会出现乱码的现象

            //创建流对象
            FileInputStream fis = new FileInputStream(file1);
            FileOutputStream fos = new FileOutputStream(file2);
            //指明字符集
            isr = new InputStreamReader(fis,"utf-8");
            osw = new OutputStreamWriter(fos,"gbk");
            //读写的过程
            char[] cbuf = new char[1024];
            int len ;
            while ((len = isr.read(cbuf)) != -1){
                osw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //资源的关闭
            try {
                if (isr != null){
                    isr.close();
                }

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

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


    }
    
}

标准输入,输出流(了解)

标准输入输出流

import org.junit.Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//其它流的使用
//标准的输入,输出流
//打印流
//数据流
public class OtherStreamTest {
    /*标准的输入,输出流
    System.in:标准的输入流,默认从键盘输入
    System.out:标准的输出流,默认从控制台输出*/

    //练习
    //从键盘输入字符串,要求将读取到的整行字符串转成大写输出,然后继续进行输入操作,
    //直至输入"e"或者"exit"时,退出程序

    //方法一:使用scanner实现,调用next()返回一个字符串
    //方法二:使用System.in实现,,System.in-->转换流-->BufferedReader的readLine()
    @Test
    public void test1(){
        BufferedReader br = null;
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            br = new BufferedReader(isr);
            while (true){
                System.out.println("请输入字符串:");
                String str = br.readLine();
                if ("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str)){
                    System.out.println("程序结束");
                    break;
                }
                String upCase = str.toUpperCase();
                System.out.println(upCase);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }

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



    }
}

打印流(了解)

打印流

数据流(了解)

数据流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值