java IO流


一、介绍

  • I/OInput/Output的缩写
  • 输入input:读取外部数据(磁盘、光盘等存储设备数据)到程序(内存)中
  • 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中

二、分类

1、按数据流的方向

  1. 输入流
  2. 输出流

2、按处理数据单位

  1. 字节流
    • 即一次只读取一个字节,可以用来处理一切文件,但是一般用来处理:二进制文件、图片、音频、视频
  2. 字符流
    • 一次读取一个字符,一般用来处理:文本类型文件;不能处理图像视频等非文本文件

3、按功能

  1. 节点流
    • 直接操作数据读写的流类,如:FileInputStream
  2. 处理流
    • 不直接连接到数据源,而是连接已存在的流,通过对数据的处理提供更强大的功能,如:BufferedInputStream

三、基类

1、字节流

  1. InputStream
  • 是所有字节输入流的父类,抽象类
  • 实现类:FileInputStreamBufferedInputStreamObjectInputStream
  1. OutputStream
  • 是所有字节输出流的父类,抽象类
  • 实现类:FileOutputStreamBufferedOutputStreamObjectOutputStream

1、字符流

  1. Reader
  • 是所有字符输入流的父类,抽象类
  • 实现类:InputStreamReaderFileReaderBufferedReader
  1. Writer
  • 是所有字符输出流的父类,抽象类
  • 实现类:OutputStreamWriterFileWriterBufferedWriterPrintWriter

四、具体实现

1、FileInputStream

  • 字节输入流
  • extends InputStream
final String inputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/inputFile.txt";

FileInputStream fis1=null;
FileInputStream fis2=null;
try{
    //1、FileInputStream(String name)  //通过文件的路径名构建
    fis1=new FileInputStream(inputPathname);

    //2、FileInputStream(File file)  //通过File构建
    fis2=new FileInputStream(new File(inputPathname));

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        if(fis1!=null){
            fis1.close();
        }
        if(fis2!=null){
            fis2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

2、FileOutputStream

  • 字节输出流
  • extends OutputStream
final String inputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/inputFile.txt";
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

FileInputStream fis1=null;

FileOutputStream fos1=null;
FileOutputStream fos2=null;
FileOutputStream fos3=null;
FileOutputStream fos4=null;
try{
    //1、FileOutputStream(String name)  //通过文件的路径名构建,append缺省=false
    fos1=new FileOutputStream(outputPathname);

    //2、FileOutputStream(String name, boolean append)  //通过文件的路径名构建,append:false-覆盖模式;true-追加模式
    fos2=new FileOutputStream(outputPathname,true);

    //3、FileOutputStream(File file)  //通过File构建,append缺省=false
    fos3=new FileOutputStream(new File(inputPathname));

    //4、FileOutputStream(File file, boolean append)  //通过File构建,append:false-覆盖模式;true-追加模式
    fos4=new FileOutputStream(new File(inputPathname),true);

    //demo
    fis1=new FileInputStream(inputPathname);
    //起缓冲作用的字节数组
    byte[] buffer=new byte[1024];
    int len;//接收实际读取的字节长度
    //一次读取1024个字节,并装入buffer字节数组,返回实际读取到的字节长度,当无内容时返回-1
    while((len=fis1.read(buffer))!=-1){
        //将buffer数组中从0开始,长度为len的数据写出
        fos2.write(buffer,0,len);
    }
}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(fis1!=null){
            fis1.close();
        }

        //out
        if(fos1!=null){
            fos1.close();
        }
        if(fos2!=null){
            fos2.close();
        }
        if(fos3!=null){
            fos3.close();
        }
        if(fos4!=null){
            fos4.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

3、BufferedInputStream

  • 缓冲字节输入流
  • extends FilterInputStream
  • 为了提高读效率而设计
final String inputPathname = "file/inputFile.txt";

BufferedInputStream bis1=null;
BufferedInputStream bis2=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(inputPathname);
    
    //1、BufferedInputStream(InputStream in)  //通过字节输入流构建;缓冲数组的大小缺省DEFAULT_BUFFER_SIZE=8192
    bis1 = new BufferedInputStream(ips);

    //2、BufferedInputStream(InputStream in, int size) //通过字节输入流构建;size:指定缓冲数组的大小
    bis2 = new BufferedInputStream(ips, 1024);

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(bis1!=null){
            //会自动关闭包装的流
            bis1.close();
        }
        if(bis2!=null){
            //会自动关闭包装的流
            bis2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

4、BufferedOutputStream

  • 缓冲字节输出流
  • extends FilterOutputStream
  • 为了提高写效率而设计
final String inputPathname = "file/inputFile.txt";
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

BufferedInputStream bis1=null;

BufferedOutputStream bos1=null;
BufferedOutputStream bos2=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(inputPathname);
            
    //1、BufferedOutputStream(OutputStream out)  //通过字节输出流构建;缓冲数组的大小缺省=8192
    bos1 = new BufferedOutputStream(ips);

    //2、BufferedOutputStream(OutputStream out, int size)  //通过字节输出流构建;指定缓冲数组的大小
    bos2 = new BufferedOutputStream(ips, 1024);

    //demo
    bis1=new BufferedInputStream(ips);
    //起缓冲作用的字节数组
    byte[] buffer=new byte[1024];
    int len;//接收实际读取的字节长度
    //一次读取1024个字节,并装入buffer字节数组,返回实际读取到的字节长度,当无内容时返回-1
    while((len = bis1.read(buffer)) != -1){
        //将buffer数组中从0开始,长度为len的数据写出
        bos1.write(buffer,0,len);
    }

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(bis1!=null){
            //会自动关闭包装的流
            bis1.close();
        }
        //out
        if(bos1!=null){
            //会自动关闭包装的流、自动调用flush
            bos1.close();
        }
        if(bos2!=null){
            //会自动关闭包装的流、自动调用flush
            bos2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

5、ObjectInputStream

  • 字节输入流(对象反序列化流)
  • extends InputStream
  • 对象的反序列化:对象输入流在读取了一组字节后按照其表示的结构将其还原为对象的过程
final String objectFileName = "file/objectFile.txt";

ObjectInputStream ois=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(objectFileName);
            
    //1、ObjectInputStream(InputStream in)
    ois = new ObjectInputStream(new BufferedInputStream(ips));

    //demo
    //从文件读取对象
    User user = (User)ois.readObject();
    System.err.println(user.toString());

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(ois!=null){
            //会自动关闭包装的流
            ois.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

6、ObjectOutputStream

  • 字节输出流(对象序列化流)
  • extends OutputStream
  • 对象序列化:对象流按照 对象 的结构将其转换为一组字节这个过程
  • 数据持久化:然后这组字节再经过io写入文件中,将数据写入文件(硬盘上)的这个过程
  • 序列化的对象的注意事项:
    1. 实现序列化接口:implements Serializable,否则会抛出异常NotSerializableException
    2. 添加序列化版本号属性:private static final long serialVersionUID = 1L;
    3. 不必需set、get方法
    4. 当对象的属性被transient修饰后,再进行对象序列化时,该属性的值就会被忽略,这意味着反序列化时得不到该属性的值;忽略不必要的属性,可以做到对象序列化时的"瘦身"效果,减少资源开销
final String objectFileName = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/objectFile.txt";

ObjectOutputStream oos=null;
try{
    //1、ObjectOutputStream(OutputStream out)  通过字节输出流构建
    oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(objectFileName)));

    //demo
    //构建对象
    User outUser = new User("kimi",18);
    //将对象转换成字节后写出到文件
    oos.writeObject(outUser);

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //out
        if(oos!=null){
            //会自动关闭包装的流
            oos.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

7、InputStreamReader

  • 字符输入流
  • extends Reader
  • 转换流,用于连接字节输入流,将字节输入流转换成字符输入流
final String inputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/inputFile.txt";

//1、InputStreamReader(InputStream in)   //通过字节输入流构建;使用系统默认的字符集
InputStreamReader isr1=new InputStreamReader(new FileInputStream(inputPathname));

//2、InputStreamReader(InputStream in, String charsetName)   //通过字节输入流构建;charsetName:指定转换的编码格式
InputStreamReader isr2=new InputStreamReader(new FileInputStream(inputPathname),StandardCharsets.UTF_8);

//3、InputStreamReader(InputStream in, Charset cs)  //通过字节输入流构建;cs:指定转换的编码格式
InputStreamReader isr3=new InputStreamReader(new FileInputStream(inputPathname),Charset.forName(StandardCharsets.UTF_8));

//获取该流使用的编码格式
String charsetName=isr1.getEncoding();

8、OutputStreamWriter

  • 字符输出流
  • extends Writer
  • 转换流,用于连接字节输出流,将字节输出流转换成字符输出流
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

//1、OutputStreamWriter(OutputStream out)  //通过字节输出流构建;使用系统默认的字符集
OutputStreamWriter osw1=new OutputStreamWriter(new FileOutputStream(outputPathname));

//2、OutputStreamWriter(OutputStream out, String charsetName)  //通过字节输出流构建;charsetName:指定转换的编码格式
OutputStreamWriter osw2=new OutputStreamWriter(new FileOutputStream(outputPathname),StandardCharsets.UTF_8);

//3、OutputStreamWriter(OutputStream out, Charset cs)  //通过字节输出流构建;cs:指定转换的编码格式
OutputStreamWriter osw3=new OutputStreamWriter(new FileOutputStream(outputPathname),Charset.forName(StandardCharsets.UTF_8));

//获取该流使用的编码格式
String charsetName=osw1.getEncoding();

9、FileReader

  • 字符输入流
  • extends InputStreamReader
  • FileInputStream + InputStreamReader
  • 无法设置编码格式
final String inputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/inputFile.txt";

FileReader fr1=null;
FileReader fr2=null;
try{
    //1、FileReader(String fileName)  //通过文件的路径名构建
    //内部:new InputStreamReader(new FileInputStream(String name))
    fr1=new FileReader(inputPathname);

    //2、FileReader(File file)  //通过File构建
    //内部:new InputStreamReader(new FileInputStream(File file))
    fr2=new FileReader(new File(inputPathname));

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(fr1!=null){
            //会自动关闭包装的流
            fr1.close();
        }
        if(fr2!=null){
            //会自动关闭包装的流
            fr2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

10、FileWriter

  • 字符输出流
  • extends OutputStreamWriter
  • FileOutputStream + OutputStreamWriter
  • 无法设置编码格式
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

FileWriter fw1=null;
FileWriter fw2=null;
FileWriter fw3=null;
FileWriter fw4=null;
try{
    //1、FileWriter(String fileName)  //通过文件的路径名构建;append缺省=false
    //内部:new OutputStreamWriter(new FileOutputStream(String name))
    fw1=new FileWriter(outputPathname);

    //2、FileWriter(String fileName, boolean append)  //通过文件的路径名构建;append:false-覆盖模式;true-追加模式
    //内部:new OutputStreamWriter(new FileOutputStream(String name, boolean append))
    fw2=new FileWriter(outputPathname,true);

    //3、FileWriter(File file)  //通过File构建;append缺省=false
    //内部:new OutputStreamWriter(new FileOutputStream(File file))
    fw3=new FileWriter(new File(outputPathname));

    //4、FileWriter(File file, boolean append)  //通过File构建;append:false-覆盖模式;true-追加模式
    //内部:new OutputStreamWriter(new FileOutputStream(File file, boolean append))
    fw4=new FileWriter(new File(outputPathname),true);

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //out
        if(fw1!=null){
            //会自动关闭包装的流
            fw1.close();
        }
        if(fw2!=null){
            //会自动关闭包装的流
            fw2.close();
        }
        if(fw3!=null){
            //会自动关闭包装的流
            fw3.close();
        }
        if(fw4!=null){
            //会自动关闭包装的流
            fw4.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

11、BufferedReader

  • 缓冲字符输入流
  • extends Reader
final String inputPathname = "file/inputFile.txt";

BufferedReader br1=null;
BufferedReader br2=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(inputPathname);
            
    //1、BufferedReader(Reader in)  //通过字符输入流构建;缓冲数组的大小缺省defaultCharBufferSize=8192
    br1 = new BufferedReader(new InputStreamReader(ips, StandardCharsets.UTF_8));

    //2、BufferedReader(Reader in, int size)  //通过字符输入流构建;size:指定缓冲数组的大小
    br2 = new BufferedReader(new InputStreamReader(ips, StandardCharsets.UTF_8), 1024);

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(br1!=null){
            //会自动关闭包装的流
            br1.close();
        }
        if(br2!=null){
            //会自动关闭包装的流
            br2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

12、BufferedWriter

  • 缓冲字符输出流
  • extends Writer
final String inputPathname = "file/inputFile.txt";
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

BufferedReader br1=null;

BufferedWriter bw1=null;
BufferedWriter bw2=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(inputPathname);
            
    //1、BufferedWriter(Writer out)  //通过字符输出流构建;缓冲数组的大小缺省defaultCharBufferSize=8192
    bw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputPathname), StandardCharsets.UTF_8));

    //2、BufferedWriter(Writer out, int size)  //通过字符输出流构建;size:指定缓冲数组的大小
    bw2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputPathname), StandardCharsets.UTF_8), 1024);

    //demo
    br1 = new BufferedReader(new InputStreamReader(ips, StandardCharsets.UTF_8));
    String lineStr;//接收读到的每行字符
    //一次读取一行,返回实际读取到的每行字符(不会读末尾的换行符),当无内容时返回null
    while((lineStr=br1.readLine())!=null){
        //将读到的每行字符写出
        bw1.write(lineStr);
        //由于不会读换行符,所以需要手动换行
        bw1.newLine();
    }

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(br1!=null){
            //会自动关闭包装的流
            br1.close();
        }
        //out
        if(bw1!=null){
            //会自动关闭包装的流、自动调用flush
            bw1.close();
        }
        if(bw2!=null){
            //会自动关闭包装的流、自动调用flush
            bw2.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}

13、PrintWriter

  • 字符输出流
  • extends Writer
  • 具有自动行刷新功能
  • 内部是BufferedWriter构建的还会默认具有缓冲功能
final String inputPathname = "file/inputFile.txt";
final String outputPathname = "D:/IDEA/Projects/myproject/io-demo/src/main/resources/file/outputFile.txt";

BufferedReader br=null;

PrintWriter pw1=null;
PrintWriter pw2=null;
PrintWriter pw3=null;
PrintWriter pw4=null;
PrintWriter pw5=null;
PrintWriter pw6=null;
PrintWriter pw7=null;
PrintWriter pw8=null;
try{
    // 读取resource下的文件获取流
    InputStream ips = getClass().getClassLoader().getResourceAsStream(inputPathname);
            
    //1、PrintWriter(String fileName) 通过文件的路径名构建;autoFlush缺省=false
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(new FileOutputStream(String name))
    pw1 = new PrintWriter(outputPathname);

    //2、PrintWriter(String fileName,String charsetName) 通过文件的路径名构建;charsetName:编码格式;autoFlush缺省=false
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(String name)),Charset cs)
    pw2 = new PrintWriter(outputPathname, StandardCharsets.UTF_8.name());

    //3、PrintWriter(File file) 通过File构建;autoFlush缺省=false
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(new FileOutputStream(File file))
    pw3 = new PrintWriter(new File(outputPathname));

    //4、PrintWriter(File file, String charsetName) 通过File构建;charsetName:编码格式;autoFlush缺省=false
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(new FileOutputStream(File file),Charset cs)
    pw4 = new PrintWriter(new File(outputPathname), StandardCharsets.UTF_8.name());

    //5、PrintWriter(OutputStream out) 通过字节输出流构建;autoFlush缺省=false
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(OutputStream out))
    pw5 = new PrintWriter(new FileOutputStream(outputPathname));

    //6、PrintWriter(OutputStream out,boolean autoFlush) 通过字节输出流构建;autoFlush:true-自动行刷新
    //默认具有缓冲功能
    //内部:new BufferedWriter(new OutputStreamWriter(OutputStream out))
    pw6 = new PrintWriter(new FileOutputStream(outputPathname),true);

    //7、PrintWriter(Writer out) 通过字符输出流构建;autoFlush缺省=false
    pw7 = new PrintWriter(new BufferedWriter(new FileWriter(outputPathname)));

    //8、PrintWriter(Writer out,boolean autoFlush) 通过字符输出流构建;autoFlush:true-自动行刷新
    pw8 = new PrintWriter(new BufferedWriter(new FileWriter(outputPathname)),true);


    //demo
    br = new BufferedReader(new InputStreamReader(ips, StandardCharsets.UTF_8));
    //输出文件不存在则创建
    File outputFile = new File(outputPathname);
    if(!outputFile.exists()){
        outputFile.createNewFile();
    }
    pw4 = new PrintWriter(outputFile, StandardCharsets.UTF_8.name());

    String lineStr;//接收读到的每行字符
    //一次读取一行,返回实际读取到的每行字符(不会读换行符),当无内容时返回null
    while((lineStr = br.readLine()) != null){
        //将读到的每行字符写出+换行符写出+flush
        pw4.println(lineStr);
    }

}catch(Exception e){
    e.printStackTrace();
}finally{
    try{
        //in
        if(br!=null){
            //会自动关闭包装的流
            br.close();
        }
        //out
        if(pw1!=null){
            //会自动关闭包装的流、自动调用flush
            pw1.close();
        }
        if(pw2!=null){
            //会自动关闭包装的流、自动调用flush
            pw2.close();
        }
        if(pw3!=null){
            //会自动关闭包装的流、自动调用flush
            pw3.close();
        }
        if(pw4!=null){
            //会自动关闭包装的流、自动调用flush
            pw4.close();
        }
        if(pw5!=null){
            //会自动关闭包装的流、自动调用flush
            pw5.close();
        }
        if(pw6!=null){
            //会自动关闭包装的流、自动调用flush
            pw6.close();
        }
        if(pw7!=null){
            //会自动关闭包装的流
            pw7.close();
        }
        if(pw8!=null){
            //会自动关闭包装的流
            pw8.close();
        }
    }catch(Exception ex){
        ex.printStackTrace();
    }
}
  • write()print()的区别?
    • write()print()效果是一样的,底层都是调用了write(),只是入参数据类型不一样;print()提供了更丰富的入参类型就是帮我们转换了数据类型再调用write()
  • print()println()的区别?
    • println()就是在print()的基础上会 多写出一个换行符、多调用一次flush(),即println()=自动换行 + 自动行刷新

五、注意事项

  • java的IO流使用了装饰模式,关闭最外层的流,会自动调用被包装的流的close(),所以当多个流连接时只需要关闭最外层流即可
  • 带有缓冲功能的输出流在调用close()时会自动调用flush(),来清空一次缓冲区,保证缓冲区内的数据写出文件,如BufferedOutputStream
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            flush();
        }
    }
    
    • 输入流是没有flush()方法的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kimi-001

只想在有限的时间分享更多的知识

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值