IO流...

IO流简介

以流的方式进行输入输出的操作就是IO(Input Output)流。流是一个抽象的概念,它是一串连续动态的数据集合,可以将流理解为水管,而数据就是水,水通过水管从一端流到另一端

  1. Input输入流是指的操作,指从外部设备向程序内存中读取数据的过程。
  2. Output 输出流是指的操作,指从程序内存中向外部设备写入数据的过程。

IO流分类

1. 按数据流向分:

输入流:侧重于,数据从数据源读入程序。
输出流:侧重于,数据从程序写出到目的地。

2. 按处理的数据单元分类:

一个字符=两个字节。
一个字节=八个二进制位。
字节流:以 字节 为单位进行读取或者写出数据。
字符流:以 字符为单位进行读取或者写出数据。

比如图片本身就是以二进制存储的,因此采用字节流。
比如文本本身是以字符存储的,因此采用字符流。

3. 按处理对象分类:

节点流:直接处理数据源或者目的地数据的读写。
处理流:不直接连接到数据源或目的地,而是为了提高节点流的效率,对节点流进行处理的流,主要指缓冲流。

IO包中常用的流对象及使用方法

构造方法

FileOutputStream 构造方法

  1. public FileOutputStream(File file)
    创建一个新的 FileOutputStream 实例,用于写入由给定 File 对象表示的文件。
  2. public FileOutputStream(String name)
    创建一个新的 FileOutputStream 实例,用于写入具有给定名称的文件。
  3. public FileOutputStream(File file, boolean append)
    创建一个新的 FileOutputStream 实例,用于写入由给定 File 对象表示的文件。如果 append 参数为 true,则在文件末尾追加数据。
  4. public FileOutputStream(String name, boolean append)
    创建一个新的 FileOutputStream 实例,用于写入具有给定名称的文件。如果 append 参数为 true,则在文件末尾追加数据。

FileInputStream 构造方法

  1. public FileInputStream(File file)
    创建一个新的 FileInputStream 实例,用于从由给定 File 对象表示的文件读取数据。
  2. public FileInputStream(String name)
    创建一个新的 FileInputStream 实例,用于从具有给定名称的文件读取数据。

1. 字节流

字节输出流 OutputStream

OutputStream 是所有输出流的超类,它定义了以下共性成员方法:

  1. public void close(): 关闭此输出流并释放与此流相关联的任何系统资源。
  2. public void flush(): 刷新此输出流并强制任何缓冲的输出字节被写出。
  3. public void write(byte[] b): 将 b.length 字节从指定的字节数组写入此输出流。
  4. public void write(byte[] b, int off, int len): 从指定的字节数组写入 len 字节,从偏移量 off 开始输出到此输出流。
  5. public void write(int b): 将指定的 byte 写入此输出流。

写入数据的原理(内存–>硬盘)java程序–>JvM(java虚拟机)–>0S(操作系统)–Os调用写数据的方法–>把数据写入到文件中

在写入数据的时候会把十进制的整数转换为二进制整数
在打开文件的时候会根据编码表把子节转换为字符表示
getBytes() 方法将字符串中的字符按照默认的字符编码(如UTF-8)转换为字节

步骤

  1. 创建一个Fileoutputstream对象,构造方法中传递写入数据的目的地
  2. 调用Fileoutputstream对象中的方法write,把数据写入到文件中
  3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
 public static void main(String[] args) throws IOException {
        //创建一个Fileoutputstream对象,构造方法中传递写入数据的目的地
        FileOutputStream fos = new FileOutputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
        //调用File0utputstream对象中的方法write,把数据写入到文件中
        // public abstract void write(int b):将指定的字节输出流。
        fos.write(49);
        /* public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
        一次写多个字节:
        如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
        如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)*/
        byte[] bytes = {65, 66, 67, 68, 69, 70};
        //byte []bytes = {-65,-66,-67,-68,69,70};
        fos.write(bytes);
        /* public void write(byte[] b,int off,int len):把字节数组的一部分写入到文件中
        int off:数组的开始索引
        int len:写几个字节*/
        fos.write(bytes, 1, 3);
        /*写入字符的方法:可以使用string类中的方法把字符串,转换为字节数组
        byte[] getBytes()把字符串转换为字节数组*/
        String str = "你好";
        byte[] bytes1 = str.getBytes();
        fos.write(bytes1);
        //关闭资源
        fos.close();
    }

\r 是回车(Carriage Return),会将光标移至行首;
\n 是换行(Line Feed),会将光标移到下一行。
追加写入

public static void main(String[] args) throws IOException {
        // 创建FileOutputStream对象,用于向指定文件写入数据,如果文件不存在,则创建新文件;true表示追加写入
        FileOutputStream fos = new FileOutputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt", true);
        // 定义字符串变量str,用于存储将要写入文件的文本内容
        String str = "hello world";
        // 将字符串str写入文件
        fos.write(str.getBytes());
        // 写入换行符,确保文件内容格式清晰
        fos.write("\r\n".getBytes());
        // 再次将字符串str写入文件,进行重复写入以测试追加功能
        fos.write(str.getBytes());
        // 关闭文件输出流,释放与之关联的系统资源
        fos.close();

    }

字节输入流 InputStream

  1. protected void finalize()
    这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。
  2. public int read(int r)
    这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。
  3. public int read(byte[] r)
    这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。
  4. public int available()
    返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。

原理:java程序---->jvm—>os—>读取数据的方法—>文件

步骤:

  1. 创建FileInputStream 对象构造方法中绑定要读取的数据源
  2. 使用FileInputStream 对象中的read()方法读取数据
  3. 释放资源
public static void main(String[] args) throws IOException {
        // 创建 FileInputStream 对象,用于读取指定文件
        FileInputStream in = new FileInputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
        // 初始化变量 i,用于存储读取的每个字符的 ASCII 值
        int i=0;
        // 循环读取文件内容,直到文件末尾
        // 读取文件内容,一次读取一个字符,并将其 ASCII 值赋给变量 i
        // 将读取的字符转换为对应的字符并输出
        //while ((i=in.read()) !=-1){
        while (i!=-1){
            i = in.read();
            System.out.print((char) i);
        }

        // 关闭文件输入流,释放相关资源
        in.close();
    }

读取多个字节
String类的构造方法
String(byte[] bytes):把字节数组转换为字符串
String(byte[] bytes,int offset,int length)把字节数组的一部分转换为字符串 offset:数组的开始索引 length:转换的字节个数

public static void main(String[] args) throws IOException {
        // 创建 FileInputStream 对象,用于读取指定文件
        FileInputStream in = new FileInputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
        // 定义一个字节数组,用于存储每次读取的文件内容
        byte[] b = new byte[1024];
        // 定义变量用于记录每次实际读取的字节数
        int len = 0;
        // 循环读取文件内容,直到文件末尾
        while ((len = in.read(b)) != -1) {
            // 将读取的内容转换为字符串并打印
            System.out.print(new String(b, 0, len));
        }
        // 关闭文件输入流,释放资源
        in.close();
    }

练习复制

步骤

  1. 创建一个字节输入流对象,构造方法中绑定要读取的数据源
  2. 创建一个字节输出流对象,构造方法中绑定要写入的目的地
  3. 使用字节输入流对象中的方法read读取文件
  4. 使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
  5. 释放资源

复制文件

public static void main(String[] args) throws IOException{
        // 创建 FileInputStream 对象,用于打开并读取源文件
        FileInputStream in = new FileInputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
        // 创建 FileOutputStream 对象,用于打开并写入目标文件
        FileOutputStream fos = new FileOutputStream("D:\\桌面\\新建文件夹\\新建文件夹\\b.txt");
        // 创建字节数组,用于在读取文件时缓冲数据
        byte[] b = new byte[1024];
        // 定义变量用于存储每次实际读取到的字节数
        int len = 0;
        // 循环读取文件,直到文件末尾
        while( (len = in.read(b) ) != -1){
            // 将读取到的数据写入到目标文件中
            fos.write(b, 0, len);
        }
        // 关闭目标文件流,释放资源
        fos.close();
        // 关闭源文件流,释放资源
        in.close();
    }

复制图片

public static void main(String[] args) throws IOException {
        // 创建 FileInputStream 对象,用于打开并读取源文件
        FileInputStream in = new FileInputStream("D:\\桌面\\新建文件夹\\新建文件夹\\a.png");
        // 创建 FileOutputStream 对象,用于打开并写入目标文件
        FileOutputStream fos = new FileOutputStream("D:\\桌面\\新建文件夹\\新建文件夹\\b.png");
        
        // 创建字节数组,用于临时存储读取到的文件数据
        byte[] b = new byte[1024];
        // 定义变量 end 用于接收每次实际读取到的字节数
        int end = 0;
        // 循环读取文件数据,直到文件末尾
        while ((end = in.read(b)) != -1) {
            // 将读取到的数据写入到目标文件中
            fos.write(b, 0, end);
        }
        // 关闭目标文件输出流
        fos.close();
        // 关闭源文件输入流
        in.close();
    }

2. 字符流

字符输入流 Reader

1. 构造方法
  1. public FileReader(File file)
    创建一个新的 FileReader,用于读取由给定 File 对象表示的文件。
  2. public FileReader(String fileName)
    创建一个新的 FileReader,用于读取具有给定名称的文件。
  3. public FileReader(File file, Charset charset)
    创建一个新的 FileReader,用于读取由给定 File 对象表示的文件,并使用指定的字符集。
  4. public FileReader(String fileName, Charset charset)
    创建一个新的 FileReader,用于读取具有给定名称的文件,并使用指定的字符集。
2. 方法
  1. public void close():关闭此流并释放与此流相关联的任何系统资源
  2. public int read():从输入流读取一个字符。
  3. public int read(char[] cbuf):从输入流中读取一些字符,并将它们存储到字符数组 cbuf中。
代码
 public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
       int len=0;
        /* while ((len=fr.read())!=-1){
            System.out.print((char)len);
        }*/
        // 创建一个大小为1024的字符数组,用于存储每次读取的字符数据
        char[] chars = new char[1024];
        // 循环读取文件中的字符,直到文件末尾
        while ((len=fr.read(chars))!=-1){
            // 将读取的字符数组转换为字符串并输出,确保只输出实际读取的部分
            System.out.print(new String(chars,0,len));
        }
        // 关闭文件输入流,释放资源
        fr.close();
    }

字符输出流 Writer

换行符
换行:换行符号
windows:/r/n
Linux:/n
mac:/r

1. 构造方法
  1. public FileWriter(File file)
    创建一个新的 FileWriter,用于写入由给定 File 对象表示的文件。
  2. public FileWriter(String fileName)
    创建一个新的 FileWriter,用于写入具有给定名称的文件。
  3. public FileWriter(File file, boolean append)
    创建一个新的 FileWriter,用于写入由给定 File 对象表示的文件。如果 append 参数为 true,则在文件末尾追加数据。
  4. public FileWriter(String fileName, boolean append)
    创建一个新的 FileWriter,用于写入具有给定名称的文件。如果 append 参数为 true,则在文件末尾追加数据。
  5. public FileWriter(File file, Charset charset)
    创建一个新的 FileWriter,用于写入由给定 File 对象表示的文件,并使用指定的字符集。
  6. public FileWriter(String fileName, Charset charset)
    创建一个新的 FileWriter,用于写入具有给定名称的文件,并使用指定的字符集。
  7. public FileWriter(File file, Charset charset, boolean append)
    创建一个新的 FileWriter,用于写入由给定 File 对象表示的文件,并使用指定的字符集。如果 append 参数为 true,则在文件末尾追加数据。
  8. public FileWriter(String fileName, Charset charset, boolean append)
    创建一个新的 FileWriter,用于写入具有给定名称的文件,并使用指定的字符集。如果 append 参数为 true,则在文件末尾追加数据。
2.方法

void write(int c)写入单个字符
void write(char[]cbuf)写入字符数组。
abstract void write(char[]cbuf,int off,int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
void write(string str)写入字符串。
void write(string str,int off,int len)“写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
void flush()刷新该流的缓冲
void close()关闭此流,但要先刷新它

代码

字符输出流的使用步骤(重点):

  1. 创建Filewriter对象,构造方法中绑定要写入数据的目的地
  2. 使用Filewriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
  3. 使用Filewriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
  4. 释放资源(会先把内存缓冲区中的数据刷新到文件中)
 public static void main(String[] args) throws IOException {
        // 创建一个FileWriter对象,用于向指定文件追加内容
        FileWriter fw = new FileWriter("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt", true);
        // 向文件中写入"hello world"
        fw.write("hello world");
        // 刷新文件写入流,确保内容被写入文件
        fw.flush();
        // 向文件中写入字符数组
        char[] b = {'a', 'b', 'c'};
        fw.write(b, 0, 3);
        fw.flush();
        // 向文件中写入字符串
        fw.write("你好啊", 0, 1);// 输出"你"
        // 关闭文件写入流,释放资源
        fw.close();
    }


关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。
flush:刷新缓冲区,流对象可以继续使用
close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

IO异常的处理

  1. 使用try-catch块捕获异常
    最常见的方式是使用try-catch语句块来捕获并处理异常。

步骤

  1. 提高对象的作用域让finally块也可以使用
  2. 变量定义的时候可以没有值使用时必须有
  3. finally块必定执行但是创建对象失败了,fw的默认值养是null,null是不能调用方法的,会批出NullPointerException,需要增加一个判断,不是null在把资源释放
public static void main(String[] args) {
        FileWriter fw = null;
        try {
            // 创建 FileWriter 对象,用于向指定文件写入数据,如果文件不存在,则创建新文件
            fw = new FileWriter("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt", true);
            // 循环写入文本到文件中
            for (int i = 0; i < 10; i++) {
                fw.write("你好" + "\r\n");
            }
        } catch (IOException e) {
            // 如果发生 IO 异常,则转换为运行时异常抛出
            throw new RuntimeException(e);
        } finally {
            // 确保在任何情况下,关闭文件写入流
            if (fw != null) {
                try {
                    // 关闭 FileWriter 对象,释放资源
                    fw.close();
                } catch (IOException e) {
                    // 处理关闭文件时可能发生的 IO 异常
                    throw new RuntimeException(e);
                }
            }
        }
    }
  1. 使用try-with-resources语句块捕获异常

使用try-with-resources:
将FileWriter对象声明在try语句中,这样在try块结束时,FileWriter会自动关闭。
这样做可以简化代码,并确保即使在发生异常的情况下也能正确关闭资源

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

public class WriteToFileExample {

   public static void main(String[] args) {
        // 定义文件路径
        String str = "D:\\桌面\\新建文件夹\\新建文件夹\\a.txt";
        // 使用try-with-resources语句确保文件写入器在使用后能正确关闭
        try (FileWriter fw = new FileWriter(str,true)){
            // 循环10次,每次写入一行文本
            for (int i = 0; i < 10; i++) {
                fw.write("你好" + "\r\n");
            }
        } catch (IOException e) {
            // 捕获并处理文件操作中的异常
            throw new RuntimeException(e);
        }
    }
}
  1. 使用throws关键字抛出异常
public static void main(String[] args) throws IOException {
        // 创建FileWriter对象,用于向指定文件写入数据
        FileWriter fw = new FileWriter("D:\\桌面\\新建文件夹\\新建文件夹\\a.txt");
        // 创建FileReader对象,用于从指定文件读取数据
        FileReader fr = new FileReader("D:\\桌面\\新建文件夹\\新建文件夹\\b.txt");
        // 使用try-with-resources语句确保文件资源在使用后能被正确关闭
        try (fw; fr){
            // 定义变量len用于存储每次读取的字符
            int len = 0;
            // 循环读取文件内容,直到文件末尾
            while ((len=fr.read()) != -1) {
               // 将读取到的字符写入到另一个文件中
               fw.write(len);
            }
        } catch (IOException e) {
            // 如果在文件操作过程中发生IO异常,则包装为RuntimeException后抛出
            throw new RuntimeException(e);
        }
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值