IO流【Java】

IO流

1.认识IO流

I:input,称为输入流,将字节或者字符从硬盘/网络中读取到内存中
O:output,称为输出流,把字节或者字符从Java程序中写入到网络或者硬盘中

  • 作用:读写文件数据

    IO流分类:
  • 流的方向:输入和输出流
  • 按流的内容:字节流和字符流

那么主要分类有:字节输入流、字符输入流、字节输出流、字符输出流
在这里插入图片描述

2.字节流

1) 字节输入流

  • FileInputStream

文件字节输入流读取文件数据的步骤:

  • 1.创建文件字节输入流管道与文件接通:InputStream fs = new FileInputStream(filePath);
  • 2.开始读取文件中的字节并输出:
    • 每次读取一个字节:int b; while((b = fs.read()) != -1) { String str = new String((char) b));}
    • 读取指定长度的字节数组:byte[] b = new byte(10); int len; while((len = fs.read(b)) != -1) { String str = new String(b, 0, len)}; //将读取到的字节数组转成字符串输出,读取多少倒出多少
    • 读取所有字节: byte[] bytes = fs.readAllBytes(); String str = new String(bytes); 适用于存在汉字读取,当文件内容过大时,可能导致内存溢出
package com.itheima.demo.demo1.filestream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class fileInputStream {
    public static void main(String[] args) throws Exception {
        //目标:从文件中读取字节
        //1.与文件建立管道
        InputStream is = new FileInputStream("C:\\Users\\zlb\\IdeaProjects\\untitled\\src\\com\\itheima\\demo\\demo1\\filestream\\inputStream.txt");

        //2.从文件中开始读取数据
        //a. 读取单个字节
        int b;
        while ((b = is.read()) != -1) {
            System.out.print((char) b);
        }
        System.out.println("======================================");
        //b.读取字节数组
        InputStream is1 = new FileInputStream("C:\\Users\\zlb\\IdeaProjects\\untitled\\src\\com\\itheima\\demo\\demo1\\filestream\\inputStream.txt");
        byte[] buffer = new byte[3];
        //定义一个len表示读取到的字节长度
        int len;
        while ((len = is1.read(buffer)) != -1) {
            //从0开始倒出来,读取到多长的字节倒多长
            System.out.print(new String(buffer, 0, len));
        }
        System.out.println("=========================================");

        InputStream is2 = new FileInputStream("C:\\Users\\zlb\\IdeaProjects\\untitled\\src\\com\\itheima\\demo\\demo1\\filestream\\inputStream.txt");
        byte[] bytes = is2.readAllBytes();
        System.out.println(new String(bytes));
    }
}

2) 字节输出流

  • FileOuputStream

字节输出流将字节写入到文件中的步骤

  • 创建字节输出流,指定写出文件路径,第二个参数填true则代表是追加管道,不会覆盖原本内容
  • 开始将字节写出到文件
    • 只写一个字节
    • 写一个字节数组
    • 写字节数组中的一部分出去
  • 关闭输出流管道: os.close(),写完之后关闭,即时释放资源,减少性能占用
package com.itheima.demo.demo1.filestream;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class fileOutputStream {
    public static void main(String[] args) throws Exception {
        //目标: 将字节写入到文件中
        //1、创建字节输出流,指定文件名建立输出管道
//        OutputStream os = new FileOutputStream("untitled/src/output.txt");  //覆盖管道
        OutputStream os = new FileOutputStream("output.txt",true); //追加管道
        //2、将字节写道文件中
        //a.写入一个字节
        os.write(97);
        os.write('b');
        os.write("\r\n".getBytes()); //换行
        //b.写入一个字节数组
        byte[] bytes = "hello world".getBytes();
        os.write(bytes);
        os.write("\r\n".getBytes());
        //c.写入一个字节数组中的一部分
        os.write(bytes, 0, 3);
        //3.关闭管道
        os.close();
    }
}

3) 文件复制

  • 任何文件的底层都是字节,字节流做复制,就是将源文件的字节一个不漏的读取并写入到新文件中,主要复制之后的文件格式一致就一定能复制成功
package com.itheima.demo.demo1.filestream;

import java.io.*;
import java.sql.SQLOutput;

public class fileCopy {
    public static void main(String[] args) {
        try {
            copyFile("C:\\Users\\zlb\\Pictures\\family.jpg", "qiya.jpg");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }
    public static void copyFile(String src, String dest) throws Exception {
        InputStream is = new FileInputStream(src);
        OutputStream os = new FileOutputStream(dest);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = is.read(buf)) != -1) {
            is.read(buf, 0, len);
            os.write(buf, 0, len);
        }
        //关闭流
        os.close();
        is.close();
        System.out.println("复制成功!");
    }
}

4) 资源释放

情形:普通关闭流只是在操作完之后,直接进行关闭,但是如果代码在中间过程出现异常,就会直接跳出,而没有执行流的关闭,导致资源浪费
关闭方式

  • try-catch-finally: 太臃肿,不美观

package com.itheima.demo.demo1.filestream;

import java.io.*;
import java.sql.SQLOutput;

public class fileCopy {
    public static void main(String[] args) {
       copyFile("C:\\Users\\zlb\\Pictures\\family.jpg", "qiya.jpg");



    }
    public static void copyFile(String src, String dest){
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(src);
            os = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                is.read(buf, 0, len);
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
            System.out.println("复制成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } 
        }
    }
}
  • try-with-resource: 从JDK7开始添加了新功能:try可以自动调用()中资源的close()方法
    在这里插入图片描述
package com.itheima.demo.demo1.filestream;

import java.io.*;
import java.sql.SQLOutput;

public class fileCopy {
    public static void main(String[] args) {
       copyFile("C:\\Users\\zlb\\Pictures\\family.jpg", "qiya.jpg");



    }
    public static void copyFile(String src, String dest){
        try (
                InputStream is = new FileInputStream(src);
                OutputStream os = new FileOutputStream(dest);
                )
        {
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                is.read(buf, 0, len);
                os.write(buf, 0, len);
            }
            is.close();
            os.close();
            System.out.println("复制成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.字符流

1) 文件字符输入流

  • FileReader

从文件中读取字符到内存的程序中
步骤:

  • 创建FileReader对象与源文件建立管道
  • 每次可以读取一个字符或者读取一个字符数组
package com.itheima.demo.demo1.filestream;

import java.io.*;

public class FIleReader {
    public static void main(String[] args) throws IOException {
        try (
                Reader is = new FileReader("fileReader.txt")
        ) {
            char[] buf = new char[1024];
            int len;
            while ((len = is.read(buf)) != -1) {
                System.out.print(new String(buf, 0, len));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2) 文件字符输出流

  • FileWriter

以内存为基准,把内存中的数据以字符的形式写出到文件中

package com.itheima.demo.demo1.filestream;

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

public class FIleWriter {
    public static void main(String[] args) {
        try (
                //1.创建FileWriter对象,与源文件创建管道
                Writer fw = new FileWriter("fileWriter.txt", true)
        ) {
            //2.写入
            //a.写入一个字符
            fw.write('啊');
            fw.write('\n');
            //b.写入字符串
            fw.write("hello");
            fw.write('\n');
            //c.写入字符串的一部分
            fw.write("world",2, 2);
            fw.write('\n');
            //d.写入字符数组
            char[] chars = "hello".toCharArray();
            fw.write(chars);
            fw.write('\n');
            //e.写入字符数组中的一部分
            fw.write(chars,2,chars.length-2);
            fw.write('\n');
            //3.刷新,将字符缓冲区中的字符刷新到文件中,这里可以不需要,因为关流前会执行刷新
            fw.flush();
            //4.关流,将流关闭,这里也不需要,使用了try-with-resource
            fw.close(); 
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4.缓冲流

缓冲流是为了提高原本流的性能。
在这里插入图片描述

1) 缓冲字节流

  • 缓冲字节输入流:BufferedInputStream
  • 缓冲字节输出流:BufferedOutputStream

为什么可以提升性能:自带8KB缓冲池,一次性读取8KB的字节到内存中,然后在内存中从缓冲字节输入流中读取字节数组长度的字节到缓冲字节输出流中,当读取够8KB时,缓冲字节输出流会统一将8KB的字节输出到文件中。这样减少了内存与磁盘(IO操作效率低)之间的IO操作次数,大大提升IO效率
在这里插入图片描述


package com.itheima.demo.demo1.filestream;

import java.io.*;
import java.sql.SQLOutput;

public class fileCopy {
    public static void main(String[] args) {
       copyFile("C:\\Users\\zlb\\Pictures\\family.jpg", "qiya.jpg");



    }
    public static void copyFile(String src, String dest){
        try (
        		//1.创建字节输入流,源源文件接通
                InputStream is = new FileInputStream(src);
                //2.创建缓冲字节输入流,包装低级的字节输入流
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream(dest);
                OutputStream bos = new BufferedOutputStream(os);
                )
        {
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                bis.read(buf, 0, len);
                bos.write(buf, 0, len);
            }
            bis.close();
            bos.close();
            System.out.println("复制成功!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2) 缓冲字符流

  • 缓冲字符输入流:BufferedReader
    • 新增功能: 读取一行:readLine(),每次读取一行,没有数据可读时则返回null
  • 缓冲字符输出流:BufferedWriter
    • 新增功能:换行:newLine()

5.性能分析

在这里插入图片描述

在这里插入图片描述
字节数组的长度并不是越大越好,适用在一定大小。

6.其他流

1) 字符输入转换流

解决不同编码格式下,字符流读取文本内容乱码的问题

  • InputStreamReader
    在这里插入图片描述
package com.itheima.demo.demo1.filestream;

import java.io.*;

public class InputStreamReader {


    public static void main(String[] args) {
        //目标:使用字符输入转换流解决不同编码格式读取乱码的问题
        //从GBK编码格式下的文件读取数据到UTF-8编码格式的代码中
        try (
                //先提取文件的元素字节流:此时读取的是GBK格式下的字节
                InputStream is = new FileInputStream("C:\\Users\\zlb\\IdeaProjects\\untitled\\fileReader.txt");
                //指定字符集把原始字节流转换成字符输入流
                Reader isr = new java.io.InputStreamReader(is,"GBK");
                //创建缓冲输入流包装低级的字符输入流
                BufferedReader br = new BufferedReader(isr);
        ) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }

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

2) 打印流

  • PrintStram:字节打印流
  • PrintWriter:字符打印流
    二者作用基本一致:能实现打印什么东西出去就是什么东西

package com.itheima.demo.demo1.filestream;

import java.io.PrintStream;

public class printStream {
    public static void main(String[] args) {
        try (
                PrintStream ps = new PrintStream("C:\\Users\\zlb\\IdeaProjects\\untitled\\src\\com\\itheima\\demo\\demo1\\filestream\\inputStream.txt")
        ) {
            ps.println("Hello World");
            ps.println(97);
            ps.println('1');
            ps.println(99.24);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

3) 特殊数据流

允许把数据和其类型一并写出去

  • DataOnputStream
package com.itheima.demo.demo1.filestream;

import java.io.*;

public class dataOutputStream {
    public static void main(String[] args) {
        try (
                OutputStream os = new FileOutputStream("output.txt");
                OutputStream bos = new BufferedOutputStream(os);
                DataOutputStream dos = new DataOutputStream(bos)
        ) {
            dos.writeUTF("Hello World");
            dos.writeBoolean(true);
            dos.writeByte(23);
            dos.writeDouble(1.0);
            dos.writeInt(23);
            dos.writeFloat(3.0f);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • DataInputStream
package com.itheima.demo.demo1.filestream;

import java.io.*;

public class dataOutputStream {
    public static void main(String[] args) {
        try (
                InputStream is = new FileInputStream("output.txt");
                InputStream bis = new BufferedInputStream(is);
                DataInputStream dis = new DataInputStream(bis);

        ) {
            System.out.println(dis.readUTF());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readByte());
            System.out.println(dis.readDouble());
            System.out.println(dis.readInt());
            System.out.println(dis.readFloat());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


7.IO框架

框架:是一个预先写好的代码库或者一组工具,旨在简化和加速开发过程

  • 框架形式:一般是把类或者接口编译成class形式,再压缩成一个.jar结尾的文件发行

IO框架:封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等
commons-io框架
使用教程:

  • commons-io官网,下载对应的zip文件
  • 解压之后复制到项目中新建的lib文件夹内
  • 在这里插入图片描述
  • 与项目产生联系:
  • 在这里插入图片描述

常用的API


实战小案例
在这里插入图片描述
在这里插入图片描述
*注:上述内容均是学习黑马程序员IO流过程中的学习笔记,图片是课上PPT直接截图的,仅作为学习交流使用,不作为商业用途,如有侵权,联系删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值