Provides for system input and output through data streams, serialization and the file system.

IO流

Java - IO - 图1
Java - IO - 图2

缓存、文件、字符串、管道、字节数组、字符数组、过滤、Object对象

bit、字节、字符

字符集、字符编码

字符集(character set)是一个系统支持的所有抽象字符的集合。字符(character)就是各种文字和符号,包括国家文字、标点符号、图形符号、数字等。 常见的编码字符集有: Unicode:也叫统一字符集,它包含了几乎世界上所有的已经发现且需要使用的字符(如中文、英文、德文等)。 ASCII:早期的计算机系统只能处理英文,所以ASCII成为了计算机的缺省字符集,包含了英文所需要的所有字符。 GB2312:中文字符集,包含ASCII字符集。ASCII部分用单字节表示,剩余部分用双字节表示。 GBK:GB2312的扩展,完整包含了GB2312的所有内容。 GB18030:GBK字符集的超集,常叫大汉字字符集,也叫CJK(Chinese,Japanese,Korea)字符集,包含了中、日、韩三国语言中的所有字符。

字符编码(character encoding),是编码字符集的字符和实际的存储值之间的转换关系。 常见的编码方式有: UTF-8(Unicode字符集的编码方式) UTF-16(Unicode字符集的编码方式) UTF-32(Unicode字符集的编码方式) ASCII(ASCII字符集的编码方式)

Java字符串由char序列组成,char数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元,大多数的常用Unicode字符使用一个代码单元就可以表示,而增补字符需要一对代码单元表示。我们所熟知的String类型的length方法,它返回的是UTF-16编码表示的给定字符串的代码单元的数量,如果想要得到代码点的数量,可以调用codePointCount()方法,charAt方法返回位于指定位置的代码单元,codePointAt方法则返回指定位置的代码点。 原文链接: https://blog.csdn.net/nlznlz/article/details/80950596

字节流、字符流

字节流继承inputStream和OutputStream 字符流继承自InputSteamReader和OutputStreamWriter 都实现了Closeable, Flushable, Appendable这些接口 输入输出流是相对于内存而言的

区别

字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据,不能用于处理图像视频等非文本类型的文件。

转换流

NIO

NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。 https://tech.meituan.com/2016/11/04/nio.html 对于NIO,它是非阻塞式,核心类: 1.Buffer为所有的原始类型提供 (Buffer)缓存支持。 2.Charset字符集编码解码解决方案 3.Channel一个新的原始 I/O抽象,用于读写Buffer类型,通道可以认为是一种连接,可以是到特定设备,程序或者是网络的连接

https://ifeve.com/overview/
https://blog.csdn.net/luoshenfu001/article/details/5812041

节点流、处理流

节点流:从或向一个特定的地方(节点)读写数据。如FileInputStream。

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

装饰者模式

序列化、反序列化

将保存在内存中的对象数据转化为二进制数据流进行传输,任何对象都可以序列化 实现方法:实现java.io.Serializable接口 把一个Java对象写入到硬盘或者传输到网路上面的其它计算机,这时我们就需要自己去通过java把相应的对象写成转换成字节流。ObjectOutputStream(OutputStream oS) 在使用tomcat开发JavaEE相关项目的时候,我们关闭tomcat后,相应的session中的对象就存储在了硬盘上,如果我们想要在tomcat重启的时候能够从tomcat上面读取对应session中的内容,那么保存在session中的内容就必须实现相关的序列化操作,还有jdbc加载驱动用的就是反序列化,将字符串变为对象。ObjectInputStream(inputStream iS) 采用类实现Serializable接口的序列化很简单,Java自动会将非transient修饰属性序列化到指定文件中去。

序列化版本号

反序列化必须拥有 class 文件,但随着项目的升级,class文件也会升级 序列化版本号可自由指定,如果不指定,JVM会根据类信息自己计算一个版本号,这样随着class的升级,就无法正确反序列化;不指定版本号另一个明显隐患是,不利于jvm间的移植,可能class文件没有更改,但不同jvm可能计算的规则不一样,这样也会导致无法反序列化。

transient关键字

一个类某些属性不需要序列化的,可用transient关键字修饰

如果只想将部分属性进行序列化,可以采用如下几种方法:

  1. 使用transient关键字
  2. 添加writeObject和readObject方法
  3. 使用Externalizable实现

Serializable与Externalizable

  1. Serializable 是标识接口,实现该接口,无需重写任何方法;

Externalizable 接口继承于Serializable,实现该接口,需要重写readExternal和writeExternal方法

  1. Serializable提供了两种方式进行对象的序列化,
    • 采用默认序列化方式,将非transatient和非static的属性进行序列化
    • 编写readObject和writeObject完成部分属性的序列化

Externalizable 接口的序列化,需要重写writeExternal和readExternal方法,并且在方法中编写相关的逻辑完成序列化和反序列化

  1. Externalizable接口的实现方式一定要有默认的无参构造函数

Serializable接口实现,其采用反射机制完成内容恢复,没有一定要有无参构造函数的限制

  1. 采用Externalizable无需产生序列化ID(serialVersionUID),而Serializable接口则需要
  2. 相比较Serializable, Externalizable序列化、反序列更加快速,占用相比较小的内存

在项目中,大部分的类还是推荐使用Serializable, 有些类可以使用Externalizable接口,如:

  • 完全控制序列的流程和逻辑
  • 需要大量的序列化和反序列化操作,而你比较关注资源和性能~ 当然,这种情况下,我们一般还会考虑第三方序列化/反序列化工具,如protobuf等进行序列化和反序列化操作~

    File

    常用方法

    文件分片与文件断点续传

    大文件内容查询与排序

FastDFS

FastDFS + nignx 搭建分布式文件服务器

FastDFS + nignx + SpringCloud 实现文件分片与断点续传

参考
https://blog.csdn.net/chengyuqiang/article/details/79183748
https://blog.csdn.net/sinat_37064286/article/details/86537354
https://www.cnblogs.com/whgk/p/5326568.html
https://my.oschina.net/wangmengjun/blog/1588096