(7)Java笔记7之IO

1、File类能新建、删除和重命名文件和目录,但是File不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。

2、输入流:只能从中读取数据,而不能向其写出数据。
   输出流:只能向其写出数据,而不能从中读取数据。

3、输入、输出都是从程序运行所在内存的角度来划分的。

4、Java的输入流主要由InputStream和Reader作为基类,而输出流则主要由OutputStream和Writer作为基类。

5、字节流和字符流的区别在于字节流和字符流所操作的数据单元不同:字节流操作的最小数据单元是8位的字节,而字符流操作的最小数据单元是16位的字符。

6、节点流(低级流)可以向一个特定的IO设备(如磁盘、网络)读/写数据的流,当使用节点流来进行输入/输出的时候,程序直接连接到实际的数据源,和实际的输入/输出节点连接。

7、处理流(高级流)用于对一个已存在的流进行连接或者封装,通过封装后的流来实现数据读/写功能。程序不会直接连接到实际的数据源,没有和实际的输入输出节点连接。

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

9、InputStream/Readers是抽象类,本身并不能创建实例来执行输入,但是它们的方法是所有输入流都可使用的方法。

10、InputStream/Readers判断读取到数据的最后:直到read(char[] cbuf)或者read(byte[] b)方法返回-1时表明到了输入流的结束点。

11、处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入/输出方法,让程序员只需关心高级流的操作。

12、识别处理流:只需流的构造器参数不是一个物理节点,而是已经存在的流,那么这种口就一定是处理流;而所有节点流都是直接以物理IO节点作为构造器参数

13、PrintStream的输出功能强大,System.out的类型就是PrintStream,通常需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。

14、当使用了处理流来包装底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的处理流即可。关闭最上层的处理流时,系统会自动关闭被该处理流包装的节点。

15、2个转换流均用于将字节流转换成字符流,InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流。

16、RandomAccessFile是Java输入/输出流体系中功能最多丰富的文件内容访问类,它提供了众多方法来访问文件内容,既可以读取文件内容,也可以向文件输出数据,与一般不同之处在于它支持“随机访问”,程序可以跳到文件的任意地方来读写数据。

17、对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象,对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久保存在磁盘中,通过网络将这种二进制流传输到另一个网络节点。其他程序一旦获得这种二进制流,兜里可以将这种二进制流恢复成原来的Java对象。

18、对象的序列化(Serialize)指将一个Java对象写入IO流中,对象的反序列化(Deserialize)则指IO流中回复该Java对象。

19、要使某个对象支持序列化,必须让它的类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:Serializable、Externalizable。

20、使用Serializable来实现序列化非常简单,主要让目标类实现Serializable接口即可,无须实现任何方法。

21、序列化一个对象需要两步:①创建一个ObjectOutputStream,该输出流是一个处理流,必须建立在其他节点流的基础之上,如:
ObjectOutputStream oos=new ObjectOutStream(new FileOutputStream("object.txt"));
②调用ObjectOutputStream对象的writeObject方法输出可序列化对象
oos.write(per);

22、反序列化需要两步:①创建一个ObjectInputStream,这个输入流是一个处理流,必须建立在其他节点流的基础之上,ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.txt"));
②调用ObjectInputStream对象的readObject方法读取流中的对象,该方法返回一个Object类型的Java对象,如果程序知道该Java对象的类型,可以将该对象强制类型转换成其真实的类型。
Person p=new (Person)ois.readObject();

23、反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供该Java对象所属类的class文件,否则将引发ClassNotFoundException异常。

24、反序列化机制无须通过构造器来初始化Java对象。

25、如果我们向文件中使用序列化机制写入了多个Java对象,使用反序列化机制恢复对象时必须按照实际写入的顺序读取。

26、注意:如果某个类的属性类型不是基本类型,而是一个引用类,那么这个引用类必须是可序列化的,否则拥有该类型属性类是不可序列化的。

27、Java序列化机制采用了一种特殊的序列化算法:
①所有保存在磁盘中的对象都有一个序列化编号,
②当序列化一个对象的时候,程序先检查该对象是否已经被序列化过了,只有当该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列并输出。
③如果某个对象时已经序列化过的,程序将直接只是输出一个序列化编号,而不是再次重新序列化该对象。

28、对于同一个对象,只有在第一次调用writeObject方法来输出对象时才会将对象转换成字节序列,并写到ObjectOutStream,但是对于可变对象,当调用了一次writeObject()后,再次调用writeObject方法输出该对象的时候,改变后的属性不会被输出。

29、通常在属性前面加上transient关键字,可以指定Java序列化时无需理会该属性值;transient关键字只能用于修饰属性,不可修饰Java程序中其他成分。


30、实现自定义序列化方法,实际上就是重写writeObject和readObject方法

31、当序列化流不完整的时候,readObjectNoData方法可正确地初始化反序列化的对象。如接收方使用的反序列化类的版本不同于接收方,或者接受者版本扩展的类不是发送者版本扩展的类时,或者序列化流被篡改,系统都调用readObjectNoData方法来初始化反序列化对象。

32、WriteObject方法存储属性的顺序应该和readObject方法中恢复属性的顺序一致,否则将不能正常恢复该Java对象。

33、系统在序列化的时候会先调用两个方法:writeRplace和writeObject,系统总是先调用被序列化对象的writeReplace方法,如果该方法返回另一个对象,系统将再次调用另一个对象的writeReplace方法...直到该方法不再返回另一个对象为止,程序将调用该对象的writeObject方法来保存该对象的状态。

34、对象序列化有以下几点注意:
①对象的类名、属性(包括基本类型、数组、对其他对象的引用)都会被序列化;方法、static属性(即静态属性)、transient属性(也被称为瞬态属性)都不会被序列化。
②实现了Serializable接口的类如果想要让某个属性不被序列化,可在该属性前面加transient修饰符,而不是加static关键字。虽然static关键字也可以达到这个效果,但static关键字不能这样用。
③反序列化对象时必须有序列化对象的class文件
④当通过文件、网络来读取序列化后对象时,必须按实际写入的顺序读取。

35、反序列化Java对象时必须提供的该对象的class文件,但是随着项目的升级,系统的class文件也会升级,Java为了保证两个class文件的兼容性,提供了private static final的serialVersionUID属性值,该属性值用于标识该Java类的序列化版本,即当一个类升级后,只要它的serialVersionUID属性保持不变,序列化机制也会把他们当成一个序列化版本,具体数值自己定义。

36、如果对类的修改确实会导致该类反序列化失败时,我们应该为该类重新分配一个serialVersionUID属性值。

37、对类的修改会不会导致该类实例的发序列化失败情况:
①如果修改类的时候仅仅修改了方法,则反序列化完全不受任何影响,类定义无须修改serialVersionUID属性值。
②如果修饰类时仅仅修改了静态属性或瞬态属性,则反序列化完全不受任何影响,类定义无须修改serialVersionUID属性值。
③如果修改类时修饰了非静态、飞瞬态属性,则可能导致序列化版本不兼容。

38、Java新IO采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了,比传统的输入/输出要快得多。

39、如果说传统的输入/输出系统是面向流的处理,而新IO则是面向块的处理。

40、Buffer就像一个数组,它是一个抽象类,其最常用的子类是ByteBuffer,它可以在底层字节数组上进行get/set操作,除了ByteBuffer外,对应其他基本数据类型(boolean除外)都有相应的Buffer类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。

41、只有ByteBuffer才提供了allocateDirect方法,所以只能在ByteBuffer级别上创建直接Buffer,直接Buffer创建成本比普通Buffer高,但是可以使运行时环境直接在该Buffer上进行较快的本机I/O操作。

42、Channel可直接将制定文件的部分或者全部直接映射成Buffer。但是程序不能直接访问Channel中的数据,读取和写入都不行,只能通过Buffer进行交互。

43、编码:将明文的字符串序列转换成计算机理解的字节序列(二进制文件、普通人看不懂)
    解码:把字节序列转换成普通人能看懂的明文字符串称为解码

44、Java的编码采用UNICODE字符集,但是很多操作并不适用UNICODE字符集。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值