java IO --- IO流

简介: java IO --- IO流

IO其实意味着:数据不停地搬入搬出缓冲区而已(使用了缓冲区)。


什么是Java序列化和反序列化,如何实现?


  • 把Java对象转换为字节序列的过程称为对象的序列化,也就是将对象写入到IO流中。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
    ps:要对一个对象序列化,这个对象就需要实现Serializable接口,如果这个对象中有一个变量是另一个对象的引用,则引用的对象也要实现Serializable接口,这个过程是递归的。Serializable接口中没有定义任何方法,只是作为一个标记来指示实现该接口的类可以进行序列化。


实现序列化:


  • 步骤一:创建一个ObjectOutputStream输出流;
  • 步骤二:调用ObjectOutputStream对象的 writeObject 方法输出可序列化对象。


image.png

序列化只能保存对象的非静态成员变量,而不能保存任何成员方法和静态成员变量,并且保存的只是变量的值,变量的修饰符对序列化没有影响。


有一些对象类不具有可持久化性,因为其数据的特性决定了它会经常变化,其状态只是瞬时的,这样的对象是无法保存去状态的,如Thread对象或流对象。对于这样的成员变量,必须用 transient 关键字标明,否则编译器将报错。任何用 transient 关键字标明的成员变量,都不会被序列化。


另外,序列化可能涉及将对象存放到磁盘上或在网络上发送数据,这时会产生安全问题。对于一些需要保密的数据(如用户密码等),不应保存在永久介质中,为了保证安全,应在这些变量前加上 transient 关键字。


反序列化就是从 IO 流中恢复对象。反序列化实现:


  • 步骤一:创建 ObjectInputStream 输入流
  • 步骤二:调用ObjectInputStream对象的readObject()得到序列化的对象。


image.png

控制台只输出了Person的信息,没有输出构造方法中的内容,说明反序列化的对象是由 JVM 自己生成的,不通过构造方法生成。


Java 中 IO 流分为几种?


  • 按照流的流向分,可以分为输入流和输出流
  • 按照操作单元划分,可以划分为字节流和字符流
  • 按照流的角色划分节点流和处理流(包装流)


Java IO 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的


  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。


按照操作方式分类结构图:


image.png

按照角色划分:

image.png

既然有了字节流,为什么还要有字符流?区别?


问题本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?

因为字符流是由 Java 虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。


总结:性能和使用更加方便两方面阐述。


如何选择?


  • 大多数情况下使用字节流会更好,因为大多数时候 IO 操作都是直接操作磁盘文件,所以这些流在传输时都是以字节的方式进行的
  • 为了提高性能,针对读写对象的不同,字节流可以采用带缓冲区的BufferedInputStream和BufferedOutputStream,字符流可以采用带缓冲区的BufferedReader和BufferedWriter。


java.io 包下有哪些流?


字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。


字符流和字节流都有对应的缓冲流,字节流也可以包装为字符流,缓冲流带有一个 8KB 的缓冲数组,可以提高流的读写效率。除了缓冲流外还有过滤流 FilterReader、字符数组流 CharArrayReader、字节数组流 ByteArrayInputStream、文件流 FileInputStream 等。


ps:BufferedReader属于处理流中的缓冲流,可以将读取的内容存在内存里面,有readLine()方法,它,用来读取一行


什么是节点流,什么是处理流,它们各有什么用处,处理流的创建有什么特征?


  • 节点流:   直接与数据源相连,用于输入或者输出,常见涉及操作:文件操作、管道操作与数组操作。
  • 处理流:在节点流的基础上对之进行加工,进行一些功能的扩展,常见操作:缓冲操作、对象序列化操作、转化操作、打印控制与基本数据类型操作
  • 处理流的构造器必须要 传入节点流的子类


什么是缓冲区?有什么作用?


  • 缓冲区就是一段特殊的内存区域,很多情况下当程序需要频繁地操作一个资源(如文件或数据库)则性能会很低,所以为了提升性能就可以将一部分数据暂时读写到缓存区,以后直接从此区域中读写数据即可,这样就显著提升了性。
  • 针对读写对象的不同,字节流可以采用带缓冲区的BufferedInputStream和BufferedOutputStream,字符流可以采用带缓冲区的BufferedReader和BufferedWriter。


流一般需要不需要关闭,如果关闭的话在用什么方法,一般要在那个代码块里面关闭比较好,处理流是怎么关闭的,如果有多个流互相调用传入是怎么关闭的?


  • 流一旦打开就必须关闭,使用close方法
  • 放入finally语句块中(finally 语句一定会执行)
  • 调用的处理流就关闭处理流
  • 多个流互相调用只关闭最外层的流


文件操作使用的流


Filter Stream是一种IO流主要作用是用来对存在的流增加一些额外的功能,像给目标文件增加源文件中不存在的行数,或者增加拷贝的性能。


ps:FileInputStream和FileOutputStream是什么?


这是在拷贝文件操作的时候,经常用到的两个类。


  • 在处理小文件的时候,它们性能表现还不错(针对字符文件,FileReader/FileWriter)。
  • 在大文件的时候,最好使用BufferedInputStream (或 BufferedReader) 和 BufferedOutputStream (或 BufferedWriter)


说说管道流(Piped Stream)


  • 有四种管道流, PipedInputStream, PipedOutputStream, PipedReader 和 PipedWriter.
  • 在多个线程或进程中传递数据的时候管道流非常有用。


键盘获取输入的两种方式?


注意:这里的输入(和输出)针对的是内存,类似反序列化将对象流还原为对象的,创建输入流,调用readObject(),写入内存。

// Scanner:用来包装System.in流,很方便地将输入的String字符串转换成需要的数据类型。
Scanner input = new Scanner(System.in);
String s  = input.nextLine();
input.close()
// BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();


System.out.println()是什么?


PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream.


println是PrintStream的一个方法。out是一个静态PrintStream类型的成员变量,System是一个java.lang包中的类,用于和底层的操作系统进行交互。

相关文章
|
1月前
|
存储 Java 数据处理
|
1月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
3月前
|
存储 Java 数据安全/隐私保护
从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
|
3月前
|
存储 移动开发 Java
从零开始学习 Java:简单易懂的入门指南之IO字节流(三十)
从零开始学习 Java:简单易懂的入门指南之IO字节流(三十)
|
3月前
|
存储 算法 Java
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
从零开始学习 Java:简单易懂的入门指南之IO序列化、打印流、压缩流(三十三)
|
18天前
|
存储 Java
探索 Java IO 流的多种实现方式
【4月更文挑战第4天】Java IO 流是处理输入输出的关键组件,包括文件流(FileInputStream/FileOutputStream)、字符流(FileReader/FileWriter)、缓冲区流(BufferedInputStream/BufferedOutputStream)、转换流(InputStreamReader/OutputStreamWriter)、数据流(DataInputStream/DataOutputStream)、对象流(ObjectInputStream/ObjectOutputStream)、随机访问文件流(RandomAccessFile)和管道流。
|
30天前
|
Java 关系型数据库 MySQL
Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
【2月更文挑战第33天】Flink1.18.1和CDC2.4.1 本地没问题 提交任务到服务器 报错java.lang.NoClassDefFoundError: Could not initialize class io.debezium.connector.mysql.MySqlConnectorConfig
49 2
|
1月前
|
Java
|
2月前
|
Java 数据处理
如何玩转Java IO?
【2月更文挑战第7天】
219 0
如何玩转Java IO?
|
2月前
|
缓存 分布式计算 Java
Java基础深化和提高-------IO流
Java基础深化和提高-------IO流
108 0