JAVA—IO流知识点总结

一、IO流的概念

  是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出

  • IO是InputOutput的简写,也就是输入和输出的含义。
  • IO流是指读写数据时像流水一样从一端流到另外一端,因此得名为"流"。

二、流的分类

Java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

  • 按数据的流向不同分为:输入流和输出流

    --------->输入流:把数据从其他设备上读取到内存中的流。

                  通常以InputStream、Reader结尾

   ---------->输出流:把数据从内存中写到其他设备上的流

                  通常以OutputStream、Write结尾

  • 按操作数据单位的不同分为:字节流和字符流

   --------->字节流:以字节为单位,读写数据的流

                  通常以InputStream、OutputStream结尾

   ---------->字符流:以字符为单位,读写数据的流

                  通常以Reader、Write结尾

  • 根据IO流的角色不同可分为:节点流和处理流

   -------->节点流:直接从数据源或目的地读写数据

  --------->处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

三、流的API

JAVA的IO流共涉及40多个类,实际上非常规则,都是从如下类中派生:

(抽象基类)输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter

四、FileReader/FileWriter使用

执行步骤:

1.创建读取或写出的File类的对象

2.创建输入流或者输出流

3.具体的读入或者写出的过程

     读入:read(char[] cbuffer)

     写出:write(String str) / write(char[] cbuffer,0,len)

4.关闭流资源,避免内存泄漏

注意事项:

1.涉及到了流资源的关闭操作,出现异常的话,需要使用try-catch-finally来处理异常

2.对于输入流,要求file类的对象对应的物理磁盘上的文件必须存在。否则会报FileNotFoundException的异常。

3.对于输出流,file类的对象对应的物理磁盘上的文件可以不存在。

-----》如果文件不存在,输出过程中,会自动创建此文件,并写出数据到此文件中

-----》如果文件存在,使用FileWriter(File file)或FileWriter(File file,false)

           ------>FileWriter(File file,false):输出过程,会创建同名的文件对现有的文件进行覆盖

           ------->FileWriter(File file,true):输出过程,会在现有的文件末尾追加写出的内容

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

public class FileReadWriteExample {
    public static void main(String[] args) {
        String filePath = "path/to/file.txt"; // 文件路径

        // 使用FileReader读取文件内容
        try (FileReader fileReader = new FileReader(filePath)) {
            int character;
            while ((character = fileReader.read()) != -1) {
                // 处理读取的字符
                System.out.print((char) character);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 使用FileWriter写入文件内容
        try (FileWriter fileWriter = new FileWriter(filePath)) {
            String content = "Hello, world!";
            fileWriter.write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的代码示例中,我们首先定义了文件的路径 filePath,你需要将其替换为你要读取或写入的实际文件路径。

然后我们使用FileReader来读取文件内容。在此示例中,我们使用read()方法来一个字符一个字符地读取文件内容,并将其转换为字符类型 char 进行处理。读取的循环会一直执行直到文件的末尾(read()方法返回-1)。

接下来,我们使用FileWriter来写入文件内容。在此示例中,我们使用write()方法将字符串内容写入文件。你可以根据需要写入不同的内容。

五、基础的IO流框架

抽象基类节点流(文件流)缓冲流(处理流一种)
InputStreamFileInputStreamBufferedInputStream
OutputStreamFileOutputStreamBufferedOutputStream
ReaderFileReaderBufferedReader
WriterFileWriterBufferedWriter

缓冲流:缓冲流也称为处理流,对文件或者其他目标频繁的操作,效率低,性能差。缓冲流目的是提高程序读取和写出的性能。缓冲流也分为字节缓冲流(如FileInputStream与FileOutputStream)和字符缓冲流(如FileReader与FileWriter)

基本原理:

是创建流对象时候,会创建一个内置的默认大小的缓冲区数组,通过缓冲区书写.使得性能大大提升。

使用方法:

处理非文本文件的字节流:

BufferedInputStream     read(byte[] buffer)

BufferedOutputStream   write(byte[] buffer,0,len)

处理文本文件的字符流:

BufferedReader    read(char[] cBuffer) / readLine()

BufferedWriter      write(char[] cBuffer,0,len)

六、FileInputStream使用

执行步骤:

1.创建读取或写出的File类的对象

2.创建输入流或者输出流

3.具体的读入或者写出的过程

     读入:read(byte[] buffer)

     写出:write(byte[] buffer,0,len)

4.关闭流资源,避免内存泄漏

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileReadWriteExample {
    public static void main(String[] args) {
        String sourcePath = "path/to/source_file.txt";  // 源文件路径
        String destPath = "path/to/dest_file.txt";      // 目标文件路径

        // 使用FileInputStream读取文件内容
        try (FileInputStream fis = new FileInputStream(sourcePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                // 处理读取的数据
                // 此处示例将读取的数据直接写入目标文件中
                try (FileOutputStream fos = new FileOutputStream(destPath, true)) {
                    fos.write(buffer, 0, bytesRead);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的代码示例中,我们假设有一个源文件和一个目标文件,你需要将 sourcePath 和 destPath 替换为实际的文件路径。源文件将从 sourcePath 读取,然后将读取的内容写入目标文件中。

我们使用 FileInputStream 来读取文件的内容。在示例中,我们使用一个字节数组 buffer 来存储每次读取的数据。通过调用 read() 方法来读取数据,并将读取的字节数保存在 bytesRead 中。如果 read() 方法返回 -1,表示已经读取到文件末尾。

然后,我们使用 FileOutputStream 来将读取的数据写入目标文件中。我们通过调用 write() 方法将读取的数据写入文件中,写入的字节数为 bytesRead

七、对象流的使用

ObjectOutoutStream:将内存中的对象———>磁盘中的文件、通过网络传输的数据。:序列化

ObjectInputStream:磁盘中的文件或通过网络接受的数据———>内存中的对象。:反序列化

  • 序列化是将对象转换为字节流的过程,反序列化是将字节流转换为对象的过程。
  • 序列化和反序列化需要使用相同的序列化算法,否则无法正确地进行反序列化。
  • 常见的序列化算法有JSON、XML、Protobuf、MsgPack等。
  • 序列化和反序列化的性能对系统的影响非常大,需要根据实际情况选择合适的序列化算法。
  • 在redis中,可以使用自定义的序列化算法,也可以使用redis自带的序列化算法。
  • 序列化和反序列化的过程中需要注意对象的版本兼容性问题,避免出现反序列化失败的情况。

序列化示范:

try {
    // 创建一个对象输出流
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.txt"));
    // 创建一个对象
    Person person = new Person("Tom", 18);
    // 将对象序列化到文件中
    out.writeObject(person);
    // 关闭输出流
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}

反序列化示范:

try {
    // 创建一个对象输出流
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.txt"));
    // 创建一个对象
    Person person = new Person("Tom", 18);
    // 将对象序列化到文件中
    out.writeObject(person);
    // 关闭输出流
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}

其中,Person类需要实现Serializable接口,示例代码如下:

public class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

在使用序列化和反序列化时,需要注意以下几点:

  1. 序列化和反序列化的对象必须是可序列化的,即对象必须实现Serializable接口或Externalizable接口。
  2. 序列化和反序列化的对象的类必须存在,否则会抛出ClassNotFoundException异常。
  3. 序列化和反序列化的对象的类的serialVersionUID必须一致,否则会抛出InvalidClassException异常。
  4. 序列化和反序列化的对象的属性必须是基本类型或可序列化的类型,否则会抛出NotSerializableException异常。
  5. 序列化和反序列化的对象的属性如果是transient修饰的,则不会被序列化和反序列化。
  6. 序列化和反序列化的对象的属性如果是static修饰的,则不会被序列化和反序列化。
  7. 序列化和反序列化的对象的属性如果是final修饰的,则在序列化时会被直接写入,反序列化时不会重新赋值。
  8. 序列化和反序列化的对象的属性如果是枚举类型,则在序列化时会写入枚举常量的名称,反序列化时会根据名称获取枚举常量。
  9. 序列化和反序列化的对象的属性如果是集合类型,则需要保证集合中的元素也是可序列化的。

八、关于字符集的理解

字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,就需要进行字符编码,以便计算机能够识别和存储各种文字。

  • 1.ASCII(American Standard Code for Information Interchange,美国信息互换标准编码)是基于罗马字母表的一套电脑编码系统。它是最通用的单字节编码系统,并等同于国际标准ISO 646。
  • 2.GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。双字节表示:两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高字节” ,而称第二字节为“低字节”。
  • 3.Big5字符集共收录13,053个中文字,Big5码使用了双字节储存方法,以两个字节来编码一个字。
  • 4.GB 18030标准采用单字节、双字节和四字节三种方式对字符编码
  • 5.Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”
  • 6.UTF-8是Unicode的其中一个使用方式。 UTF是 Unicode Tranformation Format,即把Unicode转做某种格式的意思。UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字,使得双字节的Unicode能够在现存的处理单字节的系统上正确传输。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值