IO流:字节流和字符流

本文总结整理自 Java零基础教学最新入门视频(1-8 File类与IO流)
参考《Java开发实战经典 第2版》

IO流

I:输入,把硬盘中数据读到内存中使用。
O:输出,把内存中数据写入硬盘中保存。
流:数据。数据又分为字节和字符。
因此IO流分为字符流和字节流
在这里插入图片描述

Java中IO操作,以文件的操作为例,主要的操作步骤如下:
( 1 ) 用File类打开一个文件。
( 2 ) 通过字节流或字符流的子类指定输出的位置。
( 3 ) 进行读/写操作。
( 4 ) 关闭输入/输出流。

字节流

一切的数据归根结底都是字节,无论是文本、图片还是音视频。无论什么样的流对象,底层传输始终是二进制数据。
字节流主要是操 byte类型数据,以byte数组为准,主要操作类就是OutputStream类和InputStream 类 。

  • 字节输出流OutputStream
    OutputStream是整个IO包中字节输出流最大的父类,它实现了Closeable和Flushable接口。
    主要的方法有:
void write(byte b[]) throws IOException;
void write(byte b[], int off, int len) throws IOException;
void flush() throws IOException;
void close() throws IOException;
abstract void write(int b) throws IOException;

jdk1.7后Closeable接口实现AutoCloseable接口,该接口中顶一个一个close方法,可以自动释放资源。避免用户没有手动调用close释放资源导致资源不能再使用。当然还是建议开发者显示地手动调用close。

抽象类不可实例化,必须要通过子类实例化。
当操作的数据对象是文件时,可以使用FileOutputStream类。
写入数据原理:
在这里插入图片描述

public static void main(String[] args) throws InterruptedException, IOException {
    File file = new File("D:\\Willow.txt");
    if (!file.exists()){
        file.createNewFile();
    }
    //写入文件
    OutputStream out1 = new FileOutputStream(file);
    String string = "Hello,Willow!";
    out1.write(string.getBytes());
    out1.close();
    //构造第二个参数代表是否追加
    OutputStream out2 = new FileOutputStream(file,true);
    out2.write("good".getBytes());
    out2.close();
}

换行写时,需要输入换行符。
Windows下:"\r\n"
Linux下:"/n"
Mac下:"/r"

  • 字节输入流InputStream
    InputStream是整个IO包中字节输入流最大的父类,它实现了Closeable接口。
    主要的方法有:
int read(byte b[], int off, int len) throws IOException;
int read(byte b[]) throws IOException;
int available() throws IOException;
void close() throws IOException;
abstract int read() throws IOException;

仍然需要子类实例化。当操作的数据对象是文件时,可以使用FileInputStream类。
数据读取原理和写入原理类似,只是os调用的是读还写方法。
在这里插入图片描述

    public static void main(String[] args) throws InterruptedException, IOException {
        File file = new File("D:\\Willow.txt");
        if (!file.exists()){
            file.createNewFile();
        }
        //读取文件
        InputStream inputStream = new FileInputStream(file);
        byte bytes[] = new byte[128];
        inputStream.read(bytes);
        System.out.println(new String(bytes));
        inputStream.close();
    }

上述代码中先申请一个byte数组去接文件中读取的内容,但是这个大小不知道申请多少合适,大了浪费空间,小了文件内容接不全。因此应先判断文件大小,根据文件大小开辟合适空间。

byte bytes[] = new byte[(int) file.length()];

如果不知道read的内容有多大,那么需要判断是否读取到文件末尾方式。read()方法每次读取一个字节,如果到达文件末尾,read()方法会返回-1。read(byte b[])方法返回读取到的字节长度。

    public static void main(String[] args) throws InterruptedException, IOException {
        File file = new File("D:\\Willow.txt");
        if (!file.exists()){
            file.createNewFile();
        }
        //读取文件
        InputStream inputStream = new FileInputStream(file);
        StringBuffer buffer = new StringBuffer();
        int temp = -1;
        //read每次读取一个字节
        while ((temp = inputStream.read())!=-1){
            buffer.append((char)temp);
        }
        System.out.println(buffer.toString());
        inputStream.close();
    }

图片复制

    public static void main(String[] args) throws InterruptedException, IOException {
        File file = new File("D:\\0.jpg");
        if (!file.exists()){
            return;
        }
        File fileOut = new File("D:\\Willow.jpg");
        if (!fileOut.exists()){
            fileOut.createNewFile();
        }
        //读取文件
        InputStream inputStream = new FileInputStream(file);
        //写入文件
        OutputStream outputStream = new FileOutputStream(fileOut);
        int temp = -1;
        //一个字节一个字节拷贝,如果文件太大,使用read(byte b[])方法读取,再写入。
        while ((temp = inputStream.read())!=-1){
            outputStream.write((char)temp);
        }
        inputStream.close();
        outputStream.close();
    }

字符流

当字节流读取文本时,可能遇到中文,一个中文可能占用多个字节存储,无法正确读取,而字符流以字符为单位,可以正确处理文本文件。
一个字符等于两个字节。Writer是字符输出流,Reader是字符写入流。

  • 字符输出流Writer
    Writer实现接口Appendable、Closeable和Flushable接口。Appendable接口代表内容可以被追加。
    主要的方法有:
void write(String str) throws IOException;
void write(char[] cbuf) throws IOException;
abstract void flush() throws IOException;
abstract void close() throws IOException;

抽象类不可实例化,必须要通过子类实例化。
当操作的数据对象是文件时,可以使用FileWriter类。
注意:write方法只把数据写到内存缓冲区中,并不会直接写到文件中,需要调用flush方法将缓冲区中数据刷到文件中,或者close时会全部刷过去后再释放资源。
追加写入和换行写入同FileOutputStream。

public static void main(String[] args) throws InterruptedException, IOException {
    File file = new File("D:\\Willow.txt");
    if (!file.exists()){
        file.createNewFile();
    }
    Writer writer = new FileWriter(file);
    String string = "Hello,world!";
    writer.write(string);
    writer.close();
    //追加续写,传参true
    Writer writer1 = new FileWriter(file,true);
    writer1.write("你好吗");
    writer1.close();
}
  • 字符输入流Reader

Reader实现接口Readable、Closeable接口。
主要的方法有:

int read(char[] cbuf) throws IOException;
int read() throws IOException;
abstract void close() throws IOException;

抽象类不可实例化,必须要通过子类实例化。
当操作的数据对象是文件时,可以使用FileReader类。

public static void main(String[] args) throws InterruptedException, IOException {
    File file = new File("D:\\Willow.txt");
    if (!file.exists()){
        file.createNewFile();
    }
    Reader reader = new FileReader(file);
    char[] chars = new char[(int) file.length()];
    reader.read(chars);
    System.out.println(chars);
    reader.close();
    
    //循环判断是否读完
    Reader reader1 = new FileReader(file);
    int temp = -1;
    while ((temp = reader1.read()) != -1){
        System.out.print((char) temp);
    }
}

其他

字节流和字符流区别:字符流使用缓冲区,字节流没有使用缓冲区
使用字节流好还是字符流好?字节流更好,因为文件在硬盘存储或传输时都是以字节方式进行,字符只有在内存中才形成,因此开发中字节流使用更广泛
正常写代码时不应往外抛异常,应该捕获异常:

public static void main(String[] args) {
    try {
        File file = new File("D:\\Willow555.txt");
        InputStream inputStream = new FileInputStream(file);
        System.out.println(inputStream.read());
    }catch (IOException e){
        e.printStackTrace();
        System.out.println("error");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值