Java IO流

  • Java IO流
    • IO 流的分类
      • 按照流的方向
        • 输入流
        • 输出流
      • 按照数据单位的不同
        • 字节流
        • 字符流
      • 根据功能不同
        • 节点流
        • 处理流
    • IO 流的架构
      • 四个基本抽象类
        • InputStream 字节输入流
        • OutputStream 字节输入流
        • Reader 字符输入流
        • Writer 字符输出流
        • 总结
      • IO 流特性
      • IO 流常用对象
        • File
        • InputStream
          • FileInputStream
          • ByteArrayInputStream
          • PipedInputStream
          • FilterInputStream
          • BufferedInputStream
          • DataInputStream
          • ObjectInputStream
        • OutputStream
        • Reader
          • InputStreamReader
          • BufferedReader
          • FileReader
          • PipedReader
          • FilterReader
          • CharArrayReader
          • StringReader
        • Writer
      • 字符流和字节流的应用场景
      • 字符流和字节流的区别(重点)
      • IO 流方法
        • 字节流常用方法
        • 字符流常用方法
      • IO 流使用实例
        • FileInputStream、FileOutputStream(字节流)
        • BufferedInputStream、BufferedOutputStream(缓冲字节流)
        • 字符流便捷类
        • BufferedReader、BufferedWriter(字符缓冲流)
      • 序列化与反序列化
        • 什么是序列化?
        • 为什么要进行序列化?
        • 什么是反序列化?
        • 序列化的实现 Serializable
          • 如何将一个对象序列化?
          • 反序列化
          • transient关键字
          • 实际实现例子

Java IO流

IO 流的分类

按照流的方向

输入和输出都是相对于我们程序来说

输入流

从别的地方(本地文件、网络上的资源等)获取资源 输入 到我们程序中

输出流

从我们程序中 输出 到别的地方(本地文件),例如:将一个字符串输出到文件中保存,就是需要用到输出流

按照数据单位的不同

首先对单位有个认识: 1 字符 = 2 字节; 1 字节 = 8 位(bit),1 中文汉字 对应 1 字符、或者 2 字节

字节流

每次读取 / 写出一个字节,当出现中文,使用字节流就会出现乱码的情况

字符流

每次读取 / 写出两个字节,当出现中文,使用字符流不会出现乱码的情况

根据功能不同

节点流

直接操作数据读写的流类

从 / 向一个特定的地方(节点)读写数据。 例如 FileInputStream、FileOutputStream

处理流

是对一个已经存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,功能更加丰富

IO 流的架构

四个基本抽象类

Java 所有的流都是继承这四个抽象类

为什么是抽象类不是接口? 因为Java IO流的设计模式采用的是装饰者模式,后面深挖!

类型 输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

InputStream 字节输入流

  • ByteArrayInputStream 节点流
  • PipedInputStream 节点流
  • FilterInputStream
    • BufferedInputStream 处理流
    • DataInputStream 处理流
  • FileInputStream 节点流
  • ObjectInputStream 节点流

OutputStream 字节输入流

  • ByteArrayOutputStream 节点流
  • PipedOutputStream 节点流
  • FilterOutStream
    • BufferedOutputStream 处理流
    • DateOutputStream 处理流
    • PrintStream
  • FileOutputStream 节点流
  • ObjectOutputStream 节点流

Reader 字符输入流

  • CharArrayReader
  • PipedReader
  • FilterReader
  • BufferedReader
  • InputStreamReader
    • FileReader

Writer 字符输出流

  • CharArryWriter
  • PipedWriter
  • FilterWriter
  • BufferedWriter
  • OutputStreamWriter
    • FilteWriter
  • PrintWriter

总结

一、对于以上四个抽象类的各种继承子类,如何选择?

  1. 首先确定是要输入流还是输出流,如果要读取文件到程序中使用,那么就选择输入流,反之,要将程序的数据输出到文件,那么就选择输出流
  2. 其次选择是字节流还是字符流,如果需要操作的数据中包含有中文,那么肯定是使用字符流更加好,反之则选择字节流
  3. 根据 1、2 点就可以选出合适的节点流了,比如 FileInputStream 文件输入流,如果想要在这个基础上增加功能,那么可以从处理流中找到一个合适的,例如 BufferedInputStream

二、字符流的由来

Java 中字符采用的是 Unicode 标准,一个字符是16位的,也就是一个字符对应两个字节。为此,Java引入了处理字符的流。因为数据编码的不同,而又了对字符进行高效操作的流对象。字符流的本质就是基于字节流读取时,去查了指定的码表。

IO 流特性

  1. 先进先出, 最先写入输出流的数据最先被输入流读取到
  2. 顺序存取,可以一个接着一个地往流中写入一串字节,读出的时候也是按照写入顺序来读取一串字节,不能随机访问中间的数据
  3. 只读或者只写,每个流都只能是输入流或者输出流的一种,不能同时具备这两个功能,输入流只能进行读操作,输出流只能进行写操作。如果既要写入数据又要读取数据,那么就分别提供两个流(输入流和输出流)

IO 流常用对象

常用的对象是五个类一个接口

五个类: InputStream,OutputStream、Reader、Writer、File

接口: Serializable(序列化接口

File

  1. File 类是用来操作文件的类,但是不能操作文件内的数据。可以通过对象的思想来操作文件和文件夹。

  2. File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

  3. 构造方法

    方法名 说明
    File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
    File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
    File(String parent, String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
    File(URI uri) 通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
  4. 常用的成员方法

    方法 说明
    createNewFile() 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件
    delete() 删除此抽象路径名表示的文件或者目录
    exists() 判断此抽象路径名表示的文件或者目录是否存在
    getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。
    getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。
    length() 返回由此抽象路径名表示的文件的长度。
    mkdir() 创建此抽象路径名指定的目录。
  5. File类使用实例

    public class FileTest {public static void main(String[] args) throws IOException {File file = new File("C:/Mu/fileTest.txt");// 判断文件是否存在if (!file.exists()) {// 不存在则创建file.createNewFile();}System.out.println("文件的绝对路径:" + file.getAbsolutePath());System.out.println("文件的大小:" + file.length());// 刪除文件file.delete();}
    }
    

InputStream

InputStream 和 OutputStream 都是抽象类,是字节流的基类,所有具体的字节流实现类都是分别继承了这两个类。

InputStream常见的实现子类

FileInputStream

文件输入流,非常常用到的一个类,他通常用来对文件进行读写操作

ByteArrayInputStream

字节数组输入流,从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去。

PipedInputStream

管道字节输入流,能够实现多线程间的管道通信

FilterInputStream

装饰者类,具体的装饰者继承该类,这些类都是处理类,作用是对节点类进行功能增强,实现特殊功能

BufferedInputStream

缓冲字节输入流,是继承了FilterInputStream的处理类,内部有一个缓冲区缓冲区用来存放字节,每次都是将缓存区存满之后在进行发送,而不是一个字节一个字节进行发送,这样的效率更高

DataInputStream

数据输入流,是处理类,同样是继承了FilterInputStream,作用是“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。

ObjectInputStream

对象输入流,用来提供对基本数据或对象的持久存储,也就是说,能够直接传输对象,通过用在反序列化中,他是一种处理流。构造器的参数是一个InputStream的实例对象

OutputStream

OutputStream的常用继承子类和InputStream的常用继承子类相似。

作用相反,我们需要注意这个PrintSteam

Reader

字符流的两个抽象基类:Reader和Writer

Reader的主要实现子类

截图中划掉的部分是因为,这部分有错

InputStreamReader

从字节流到字符流的桥梁。(InputStreamReader构造器入参是FileInputStream的实例对象),它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式给定,或者可以接受平台的默认字符集。

BufferedReader

从字符输入流中读取文本,设置一个缓冲区来提高效率。BufferedReader是对InputStreamReader的封装,前者构造器的入参就是后者的一个实例对象。

FileReader

用于读取字符文件的便利类,new FileReader(File file)等同于new InputStreamReader(new FileInputStream(file, true),"UTF-8"),但FileReader不能指定字符编码和默认字节缓冲区大小。

PipedReader

管道字符输入流。实现多线程间的管道通信

FilterReader

FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。

CharArrayReader

Char数组中读取数据的介质流。

StringReader

String中读取数据的介质流。

Writer

与Reader的相似,但是同样Writer有子类PrintWriter

字符流和字节流的应用场景

  1. 字节流一般用来处理图像,视频,以及PPT,Word类型的文件
  2. 字符流一般用来处理纯文本类型的文件,例如txt文件
  3. 字节流也可以处理纯文本文件,但是字符流不能处理图像视频等非文本类型的文件

字符流和字节流的区别(重点)

  1. 读写单位不同

    字节流以字节为单位进行读、写

    字符流以字符为单位进行读、写,因为是根据码表映射字节,所以有可能一个字符对应多个字节

  2. 处理对象不同

    字节流处理的对象可以是视频、图片、ppt、文本文件等等

    字符流只能处理纯文本类型的文件

  3. 有无缓冲区(详情可以到 http://blog.csdn.net/qq_25184739/article/details/51203733 查看)

    • 字节流是没有缓冲区的,字节流是直接对文件进行处理,如果在输出字符串到文件的时候,如果最后没有调用close方法进行关闭流,那么对应的文件也是有输出的
    • 字符流是自带缓冲区的,如果输出字符串到文件的时候,最后没有调用close方法,那么输出的数据可能有一部分是在缓冲区中,我们可以调用flush方法强制将缓冲流的数据输出到文件

IO 流方法

字节流常用方法

字节输入流InputStream主要方法:

  • read() :从此输入流中读取一个数据字节。
  • read(byte[] b) :从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
  • read(byte[] b, int off, int len) :从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
  • close():关闭此输入流并释放与该流关联的所有系统资源。

字节输出流OutputStream主要方法:

  • write(byte[] b) :将 b.length 个字节从指定 byte 数组写入此文件输出流中。
  • write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
  • write(int b) :将指定字节写入此文件输出流。
  • close() :关闭此输入流并释放与该流关联的所有系统资源。

字符流常用方法

字符输入流Reader主要方法:

  • read():读取单个字符。
  • read(char[] cbuf) :将字符读入数组。
  • read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
  • read(CharBuffer target) :试图将字符读入指定的字符缓冲区。
  • flush() :刷新该流的缓冲。
  • close() :关闭此流,但要先刷新它。

字符输出流Writer主要方法:

  • write(char[] cbuf) :写入字符数组。
  • write(char[] cbuf, int off, int len) :写入字符数组的某一部分。
  • write(int c) :写入单个字符。
  • write(String str) :写入字符串。
  • write(String str, int off, int len) :写入字符串的某一部分。
  • flush() :刷新该流的缓冲。
  • close() :关闭此流,但要先刷新它。

另外,字符缓冲流还有两个独特的方法:

  • BufferedWriternewLine()写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
  • BufferedReaderreadLine() :读取一个文本行。

IO 流使用实例

FileInputStream、FileOutputStream(字节流)

字节流的方式效率较低,不建议使用

public class IOTest {public static void main(String[] args) throws IOException {File file = new File("D:/test.txt");  write(file);System.out.println(read(file));}public static void write(File file) throws IOException {// 第二个参数是追加的意思,不会覆盖之前的数据,默认是falseOutputStream os = new FileOutputStream(file, true);// 要写入的字符串String string = "松下问童子,言师采药去。只在此山中,云深不知处。";// 写入文件os.write(string.getBytes());// 关闭流os.close();}public static String read(File file) throws IOException {InputStream in = new FileInputStream(file);// 一次性取多少个字节byte[] bytes = new byte[1024];// 用来接收读取的字节数组StringBuilder sb = new StringBuilder();// 读取到的字节数组长度,为-1时表示没有数据int length = 0;// 循环取数据while ((length = in.read(bytes)) != -1) {// 将读取的内容转换成字符串sb.append(new String(bytes, 0, length));}// 关闭流in.close();return sb.toString();}
}

BufferedInputStream、BufferedOutputStream(缓冲字节流)

缓冲字节流是为高效率而设计的,真正的读写操作还是靠FileOutputStreamFileInputStream,所以其构造方法入参是这两个类的对象也就不奇怪了。

public class IOTest {public static void write(File file) throws IOException {// 缓冲字节流,提高了效率BufferedOutputStream bis = new BufferedOutputStream(new FileOutputStream(file, true));// 要写入的字符串String string = "松下问童子,言师采药去。只在此山中,云深不知处。";// 写入文件bis.write(string.getBytes());// 关闭流bis.close();}public static String read(File file) throws IOException {BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));// 一次性取多少个字节byte[] bytes = new byte[1024];// 用来接收读取的字节数组StringBuilder sb = new StringBuilder();// 读取到的字节数组长度,为-1时表示没有数据int length = 0;// 循环取数据while ((length = fis.read(bytes)) != -1) {// 将读取的内容转换成字符串sb.append(new String(bytes, 0, length));}// 关闭流fis.close();return sb.toString();}
}

InputStreamReader、OutputStreamWriter(字符流)

字符流适用于文本文件的读写OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象

public class IOTest {public static void write(File file) throws IOException {// OutputStreamWriter可以显示指定字符集,否则使用默认字符集OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");// 要写入的字符串String string = "松下问童子,言师采药去。只在此山中,云深不知处。";osw.write(string);osw.close();}public static String read(File file) throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");// 字符数组:一次读取多少个字符char[] chars = new char[1024];// 每次读取的字符数组先append到StringBuilder中StringBuilder sb = new StringBuilder();// 读取到的字符数组长度,为-1时表示没有数据int length;// 循环取数据while ((length = isr.read(chars)) != -1) {// 将读取的内容转换成字符串sb.append(chars, 0, length);}// 关闭流isr.close();return sb.toString()}
}

字符流便捷类

Java提供了FileWriterFileReader简化字符流的读写,new FileWriter等同于new OutputStreamWriter(new FileOutputStream(file, true))

public class IOTest {public static void write(File file) throws IOException {FileWriter fw = new FileWriter(file, true);// 要写入的字符串String string = "松下问童子,言师采药去。只在此山中,云深不知处。";fw.write(string);fw.close();}public static String read(File file) throws IOException {FileReader fr = new FileReader(file);// 一次性取多少个字节char[] chars = new char[1024];// 用来接收读取的字节数组StringBuilder sb = new StringBuilder();// 读取到的字节数组长度,为-1时表示没有数据int length;// 循环取数据while ((length = fr.read(chars)) != -1) {// 将读取的内容转换成字符串sb.append(chars, 0, length);}// 关闭流fr.close();return sb.toString();}
}

BufferedReader、BufferedWriter(字符缓冲流)

public class IOTest {public static void write(File file) throws IOException {// BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new// FileOutputStream(file, true), "UTF-8"));// FileWriter可以大幅度简化代码BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));// 要写入的字符串String string = "松下问童子,言师采药去。只在此山中,云深不知处。";bw.write(string);bw.close();}public static String read(File file) throws IOException {BufferedReader br = new BufferedReader(new FileReader(file));// 用来接收读取的字节数组StringBuilder sb = new StringBuilder();// 按行读数据String line;// 循环取数据while ((line = br.readLine()) != null) {// 将读取的内容转换成字符串sb.append(line);}// 关闭流br.close();return sb.toString();}
}

序列化与反序列化

什么是序列化?

序列化就是将一个 Java 对象编程二进制内容,二进制内容本质上就是一个byte[]数组。

为什么要进行序列化?

因为序列化之后可以把 byte[] 数组保存到文件中,或者把 byte[] 通过网络传输到远程,就相当于把 Java 对象存储到文件或者通过网络传输出去了。

什么是反序列化?

就是将一个二进制内容(即byte[] 数组)变成Java对象,通过反序列化,就可以将保存在文件中的byte[] 数组变回 Java对象,或者从网络中读取byte[] 数组并且把他变回Java对象

序列化的实现 Serializable

需要被序列化的类实现 Serializable 接口,这个接口没有任何的抽象方法。因为他的作用仅仅是为了标注该对象是可以被序列化的

如何将一个对象序列化?

通过一个输出流 ObjectOutputStream 对象的 writeObject(Object obj) 方法就可以将obj对象的状态(内容)写出。

反序列化

如果要将obj对象的内容保存输入到程序中,我们可以通过输入流 ObjectInputStream 对象的readObject() 方法,该方法将返回反序列化得到的内容

transient关键字

transient 关键字的作用就是,如果类中某个属性不想被序列化,那么就使用该关键字,对象的该属性就不会被序列化,反之也无法反序列化恢复

实际实现例子
  1. 定义一个Person类,实现Serializable接口,表示该类的对象可以实例化

    package Test;import java.io.Serializable;public class Person implements Serializable {private int age;private transient String name;public Person(int age, String name) {this.age = age;this.name = name;}public Person() {}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +'}';}
    }
    
  2. 定义ObjectInputStream 对象和 ObjectOutputStream 对象

    public static void main(String[] args) throws IOException, ClassNotFoundException {String path = "D:\\java\\LeetCode\\src\\Test\\test.txt";ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File(path)));ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File(path)));Person p = new Person(18,"小明");// 序列化poos.writeObject(p);System.out.println("序列化成功");// 反序列化Object o = ois.readObject();System.out.println(o);System.out.println("反序列化成功");// 关闭资源oos.close();ois.close();
    }
    
  3. 程序结果

    可以看到结果中,name并没有被复原,这是因为我们对于name属性使用了transient关键字

    序列化成功
    Person{age=18, name='null'}
    反序列化成功Process finished with exit code 0
  4. 查看test.txt文件

    生成了一些东西,不过这里乱码了

    本文大部分内容来自:

    • https://blog.csdn.net/mu_wind/article/details/108674284
    • https://blog.csdn.net/sinat_37064286/article/details/86537354

【Java】IO流 (超详细!!)相关推荐

  1. Java——IO流超详细总结

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 在初学Java时,I ...

  2. 一篇文让你了解JAVA IO(超详细 基础篇)

    JAVA IO java io可以让我们用标准的读写操作来完成对不同设备的读写数据工作. java将IO按照方向划分为输入与输出,参照点是我们写的程序. 输入:用来读取数据的,是从外界到程序的方向,用 ...

  3. Java基础17:Java IO流总结

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a724888/article/details/80201802 这位大侠,这是我的公众号:程序员江湖 ...

  4. JAVA 正则表达式 (超详细,转)

    转 JAVA 正则表达式 (超详细,转) 2015年03月25日 10:27:57 阅读数:1514 在Sun的Java JDK 1.40版本中,Java自带了支持正则表达式的包,本文就抛砖引玉地介绍 ...

  5. java io流详解_一文带你看懂JAVA IO流,史上最全面的IO教学啦

    一.IO流是什么 惯例引用百科的回答流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操作 ...

  6. javaio流_一文带你看懂JAVA IO流,史上最全面的IO教学啦

    一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...

  7. 一文带你看懂JAVA IO流,史上最全面的IO教学啦(附送JAVA IO脑图

    一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...

  8. java IO流进阶 模拟上传头像系统详解

    目录 一.前言: 二.思路: PS:直接看代码中的注释也可以. ①分析: ②总结: 三.代码: ①准备工作: ②代码演示: ③运行效果: 四.撒❀: 一.前言: 这篇文章是对之前java IO流基础 ...

  9. JAVA~~IO流和文件

    ​​​​​​​​ Io流的分类 有多种分类方式: 一种方式是按照流的方向进行分类: 以内存作为参照物, 往内存中去,叫做输入(Input).或者叫做读(Read). 从内存中出来,叫做输出(Outpu ...

  10. Java IO流经典练习题详解

    Java IO流经典练习题 转载于:https://blog.csdn.net/wenzhi20102321/article/details/52582705 博主对转载的原代码进行了调试,改了一些小 ...

最新文章

  1. php 去除实体,php – 如何在学说中正确关闭实体管理器
  2. C++包扩展_利用 MATLAB Coder 将M代码生成C/C++代码
  3. 从一个实例看编程水平的步步提高
  4. WebAPI基本封装
  5. 构造方法、toString、Object类、String类
  6. USGS网站中STRM DEM数据批量下载
  7. 硬件设计论坛_疫情让硬件教育迎百年巨变 EDA365 电子论坛成为主角
  8. 高等数学(第七版)同济大学 总习题八 个人解答
  9. 雷蛇键盘灯光配置文件_三模连接一步到位,游戏宅女必备的雷蛇电竞外设套装...
  10. 美团财报数据初步分析
  11. 第三方登陆之微博登录
  12. 毕业论文尾注和参考文献
  13. java实现光盘摆渡_一种光盘摆渡机的制作方法
  14. 我的世界java版上网的mod_我的世界Minecraft Mod(模组)安装指南
  15. 系统渗透与防护——网络安全
  16. Classical Algorithm--Mobius反演
  17. 重大要素改变中的机会选择包括_智慧树青年教师课堂教学比赛微课4答案
  18. python demo.py_pythonDemo.py
  19. 成都中学生培训计算机,成都中学生编程培训
  20. 今日学习在线编程题:古人的剩余定理

热门文章

  1. 刷题小程序【程序猿面试宝典】开发(二)| 页面创建、页面配置、全局配置
  2. 终于知道 Java agent 怎么重写字节码了
  3. babylon 画线_【温故知新】——BABYLON.js学习之路·前辈经验(一)
  4. 监狱工作信息化建设的实践与思考
  5. 2021计算机保研记录总结(已上岸计算所)
  6. [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集
  7. 上海体育馆分布api 上海体育馆查询
  8. 嵌入式开发的架构设计
  9. 土木工程计算机软件应用考试,土木工程计算机应用技术(12年4月)试题及答案
  10. bzoj 2803 [POI2012]prefixuffix hsh+性质