2019独角兽企业重金招聘Python工程师标准>>>

tip 0, 读到文件(或流)结尾的标志

java.io.InputStream 中有个关键方法:

int read(),

它从流中读取一个字节,并将该字节返回; 如果到达流末尾,则返回 -1 .

那么问题是, 如果流中正好有一个字节的值是 -1 (即该字节的二进制是 11111111, 十六进制 FF),那么怎样和碰到流的结尾时的返回值区分呢?

答案在这个方法的返回值类型int上。 虽然每次读取并返回一个字节,但返回值类型并不是byte , 而是int。 byte长度一个字节,而int 是 4个字节, 当读取一个字节 XY 时, 返回的值是 00 00 00 XY ,这个值永远不会为负数 ;当遇到流的结尾时, 返回的值是 FF FF FF FF, 即 -1

tip 1,关于路径:

All the classes in java.io interpret relative path names as starting from the user’s working directory. You can get

this directory by a call to System.getProperty("user.dir").

tip 2,关于InputStreamReader  和 InputStreamWriter 的编码问题:

When saving text strings, you need to consider the character encoding. In the UTF-16 encoding, the string "1234" is encoded as 00 31 00 32 00 33 00 34 (in hex). However, many programs expect that text files are encoded in a different encoding.

In ISO 8859-1, the encoding most commonly used in the United States and Western Europe, the string would be written as 31 32 33 34, without the zero bytes.

OutputStreamWriter 把 Unicode 字符转换为字节流(按系统默认编码或指定的编码)写入,InputStreamReader 将字节流(按系统默认编码或指定的编码)转化为Unicode字符:

The OutputStreamWriter class turns a stream of Unicode code units into a stream of bytes, using a chosen character encoding. Conversely, the InputStreamReader class turns an input stream that contains bytes (specifying characters in some character encoding) into a reader that emits Unicode code units.

For example, here is how you make an input reader that reads keystrokes from the console and converts them to Unicode:

InputStreamReader in = new InputStreamReader(System.in);

This input stream reader assumes the default character encoding used by the host system, such as the ISO 8859-1 encoding in Western Europe. You can choose a different encoding by specifying it in the constructor for the InputStreamReader, for example:

InputStreamReader in = new InputStreamReader(new FileInputStream("kremlin.dat"), "ISO8859_5");

tip 3, 关于对象序列化

序列化对象时,序列号的作用不光是校验,还可以处理对象之间的引用关系。如果序列化时没提供序列号,ObjetOutputStream会默认生成一个

对象序列化有严谨的顺序与格式。序列化时,ObjectOutputStream内部按序列化顺序为每个对象赋予一个隐式的序列号,一般来讲,如果类型为A的对象a内部有一个类型为 B 的成员变量b, 那么对象b的序号要比a的序列号要小,也就是说b序列化更早(同样的,反序列化也更早);假设b是被0个序列化,其隐式的序列号为0, 那么在序列化a时,a的对象数据内部存储b对象时会使用一个序列号为0的引用。

ObjectInputStream在反序列化时同样的顺序,也会按反序列化顺序为每个对象维护一个序列号,这样就可以解决a引用b的问题。

序列化的数据文件除了头数据(魔数,版本等)外,核心数据有两种:类描述符 和 对象数据。

一个序列化对象的格式是 :首先是类描述符,后面紧跟对象数据;

类描述符存储了类的结构,包括类型、类结构的指纹(类名、成员变量、方法签名等数据的一个哈希值),成员个数以及每个成员的描述;

对象数据按类描述中成员变量的顺序存储了各个成员变量的值;如果成员变量是基本类型或String类型,对象数据会直接存储它的值;如果是其他的对象类型,如果这个对象之前没序列化过,则按“类描述符 数据对象”的格式存储,如果已经序列化过,则存储一个指向该对象的序列号(判断一个对象是否序列化过,是由ObjectOutputStream通过维护对象的序列号来实现的);

对象存储格式:73  类描述符  对象数据

数组对象存储格式:75  类描述符  4字节长的数组项的数量  数组项(对象或基本类型的数据)

类描述符:72 两字节长的类名长度 类名  8字节长的指纹  1字节长的序列化方式标志  两字节长的成员变量个数  成员变量描述符(数量与成员变量个数对应)  78(结束标记)   超类类型(没有的话,写70)

引用:71  4字节长的序列号

字符串对象存储格式:74  两字节字符串长度  所有字符

采用外部存储方式的对象:  77  对象数据

注:对于实现了Externalizable接口的类,其对象序列化时会采用“外部存储方式”,序列化的数据以及反序列时数据的处理都是类实现的接口方法控制的。

版本管理:类描述符中的指纹是反序列化时用来校验最新的类定义与当前序列化数据是否一致,比如要从一个序列化文件中反序列化出一个类型为C的对象, 那么会对C的类结构(类名、成员、方法签名)进行哈希,然后与文件中类描述符中的指纹对比,如果不一致会反序列化失败。为了兼容可以在类定义中显示的声明这个指纹:public static final long serialVersionUID = ..., 这个值可以jdk的工具 serialver生成。这样在反序列化时,如果新的类定义中少了某些成员,那序列化的对象数据中相应的域会被掉弃;如果新的类定义中多了某些成员,这些成员会被置为默认值(null, 0, false等)。

序列化的定制:默认的序列化机制忽略transient 和  static域, 我们可以通过实现 private void readObject(ObjectInputStream in) 和 private void writeObject(ObjectOutputStream out) 来定制序列化、反序列化过程,写入自己要存储的数据,甚至不必和类定义的成员变量对应;另外一种方法就是实现外部存储方式:实现 Externalizable 接口,折中方式完全有类对象自己控制,接口方法也需要先有对象才能调用(这种反序列方式类似于给对象初始化成员值),而前一种方式的readObject 和 writeObject 则是由序列化机制调用的,我们不能显示调用。

read () 方法读一个字节,但是返回int:

write(int)写一个字节,该字节是int 参数的低8位, 高24位被忽略:

Reader Writer被设计来读写文本文件,设计到字符集与编码问题:

DataInput 和 DataOutput 用来规范读写二进制文件,文件内容可以方便的转化为基本类型或对象数据:

转载于:https://my.oschina.net/u/255456/blog/367549

java.io 相关tips相关推荐

  1. java io运用_Java IO相关使用

    date: 2020-06-14 14:42:22 updated: 2020-08-21 17:35:45 Java IO相关使用 1. 文件 创建 File 对象的三种方式 一个路径名:File( ...

  2. Java基础相关6(IO)

    java基础相关6 File类 File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径) 使用File可以做到: 访问其表示的文件或目录的属性信息,例如:名字,大 ...

  3. java io教学文件_通过代码实例跟我学Java语言程序设计及应用技术——Java文件IO技术及应用相关的教学示例(第3部分)...

    1.1Java文件IO技术及应用相关的教学示例(第3部分) 1.1.1文本字符流IO操作 1.字符流Reader/Writer类 提供的对字符流处理的类,它们为抽象类.其子类 (1)InputStre ...

  4. java.io.IOException: offset 0相关问题研究

    近日,碰到一个问题java.io.IOException: offset < 0,就是打开压缩包(里面文件也是压缩包),打开速度慢,而且打开显示里面的压缩包文件大小为负数,为-1.16G.废话不 ...

  5. JAVA面试相关基础知识

    1.面向对象的特征有哪些方面  1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽 ...

  6. linux rm 提示io异常,Hadoop异常 java.io.IOException: Job status not available

    Hadoop集群上跑mapreduce,在job任务执行完成退出时报 java.io.IOException: Job status not available异常.Job client请求job状态 ...

  7. Java IO基础原理你该知道这些

    Java IO 也称为IO流,IO = 流,它的核心就是对文件的操作,对于 字节 .字符类型的输入和输出流. IO是指对数据流的输入和输出,也称为IO流,IO流主要分为两大类,字节流和字符流.字节流可 ...

  8. 一。深入了解JDK1.8 从Package java.io开始

    Package java.io 通过数据流,序列化和文件系统提供系统输入和输出. See: 描述 接口摘要 接口 描述 Closeable A Closeable是可以关闭的数据的源或目的地. Dat ...

  9. 1.6 万字长文带你读懂 Java IO

    Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 N ...

最新文章

  1. 输入示例,自动生成代码:TensorFlow官方工具TF-Coder已开源
  2. 程序员,你就是三明治!
  3. asp.net 中chartlet 统计图表的的使用
  4. Spark SQL and DataFrame for Spark 1.3
  5. rds 数据导入mysql_将数据导入到 Amazon RDS 数据库实例
  6. 【LeetCode笔记】剑指 Offer 33. 二叉树的后序遍历序列(Java、递归、栈)
  7. JS基础入门篇(二十)—事件对象以及案例(二)
  8. 《HTML5游戏编程核心技术与实战》——2.3 图像API
  9. php数据库随机选择,php – 在MySQL数据库中选择两个随机行
  10. Centos 7.X 安装 supervisord
  11. 基于Java visualvm的可视化监控的使用
  12. Tapestry5.3使用总结
  13. 基于自动编码器特征抽取的分类实战
  14. Google Guice依赖注入框架使用
  15. 华为路由器怎么看是不是公网_如何查看华为路由器默认ip地址
  16. RabbitMQ配置SSL
  17. layim之绑定未读消息数量
  18. 洛谷 P3387 【模板】缩点(scc 缩点)
  19. JavaScript常见设计模式
  20. Argox(立象)打印机

热门文章

  1. 7-2 整除分块 (15 分)
  2. 力扣114. 二叉树展开为链表(C++,解释一下别人的思路)
  3. ps怎么对比原图快捷键_PS裁剪几大构图法
  4. QT-helloworld-Qt设计师编写
  5. [Contest]2017 ACM/ICPC Asia Regional Shenyang Online(01 03 07 09 10 11待补)
  6. 字典树从第i个构造HDU2846
  7. 《构建之法》第8,9,10章
  8. 原生js实现ajax
  9. 遵循Java EE标准规范的开源GIS服务平台之三:数据发布与访问
  10. iPhone应用程序编程指南(图形和描画)