Java编程思想之I/O系统

  1. File类指文件路径,既可以代表一个文件,也可以代表一个目录下的一组文件总称。list()和list(new FilenameFilter())分别返回此File对象包含的全部列表和受限列表的字符串素组。从外界传给匿名内部类中的参数必须是final修饰的。
  2. File类不仅只代表存在的文件或目录,也可以用来创建新的目录或尚不存在的整个目录路径。可以参看文件的大小,最后修改日期,读/写,检查某个File对象是一个目录还是文件,并可以删除,重命名(移动)文件,mkdirs()用来创建目录路径。
  3. 流代表任何有能力产生数据的数据源对象或有能力接受数据的接收端对象。与输入有关的所有类都是从InputStream继承,而与输出有关的所有类都是从OutputStream继承。
  4. Java编程思想之I/O系统

  5. Java编程思想之I/O系统

  6. Java编程思想之I/O系统

  7. Java编程思想之I/O系统

  8. InputStream和OutputStream提供面向8位字节流的I/O功能,而Reader和Writer提供兼容Unicode与面向字符的I/O功能。

  9. 适配器类:InputStreamReader把InputStream转换成Reader;OuputStreamWriter把OuputStream转换成Writer。

  10. Java编程思想之I/O系统

  11. Java编程思想之I/O系统
  12. RandomAcessFile适用于由大小已知的记录组成的文件,可以使用seek()将记录从一处转移到另一处,然后读取或修改记录。此类不是InputStream和OutputStream继承层次的,除了实现了DataInput和DataOutput接口。只有此类支持搜寻方法,并且只适用于文件。
  13. I/O流典型使用:
    1. 缓冲输入文件:具有readLine()的BufferedReader和FileReader组成。
    2. 从内存输入:具有read()的StringReader和BufferInputFile.read()组成。
    3. 格式化的内存输入:具有readByte()的DataInputStream,ByteArrayInputStream和BufferInputFile.read().getBytes()组成。
    4. 基本的文件输出:具有println()的PrintWriter, BufferedWriter和FileWriter组成。必须为PrintWrite对象显示调用close(),以舒心清空缓冲区内容,保证输出内容完整性。PrintWriter中添加了一个辅助构造器,使得不必每次使用时,都去执行所有的装饰工作。
    5. 存储和恢复数据:DataInputStream,InputStream和DataOutputStream,OutputStream,保证数据读写跨平台的准确性。用UTF-8编码来保证字符串读写。保证数据读得正确,必须知道流中数据项所在的确切位置。
    6. 读写随机访问文件:RandomAcessFile。
    7. 管道流:用于多进程任务之间的通信。
  14. Java.util.Scanner类只用于读取文件,主要用于创建扫描器。
  15. 读取二进制文件,使用BufferInputStream和FileInputStream。
  16. System.out, System.err都是PrintStream对象,而System.in却是未包装的InputStream,因此可以立刻使用System.out, System.err,但是在读取System.in之前要进行包装。
  17. 通常把System.in通过InputStreamReader包装成BufferReader来读取键盘输入。
  18. 标准I/O流可以进行重定向输入和输出,重定向操作的是字节流,而不是字符流,只能用InputStream和OutputStream。
  19. 基础控制,在Java内部操作其他操作系统的程序,并要控制这些程序的输入和输出。
  20. java.nio.*包提高了速度,来源于所用的结构更接近操作系统执行I/O的方式:通道和缓冲器。通道封装了数据,用户不与通道交互,而与缓冲器交互,并把缓冲器送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据。
  21. 唯一与通道交互的缓冲器是ByteBuffer,可以存储未加工的字节。只可以读取原始字节或者基本类型数据,不能读取输出对象。
  22. FileInputSteam,FileOutputStream和既读又写的RandomAccessFile可以产生FileChannel。通道是一种相当基础的东西:可以向他传送用于读写的ByteBuffer,并且可以锁定文件的某些区域用于独占式访问。
  23. 将字节存放于ByteBuffer的两种方法:1. 使用put方法,2. 使用wrap()方法将一寸照的字节数组包装到ByteBuffer中。一旦如此,就不再复制底层的数组,而是将数组作为所产生ByteBuffer的存储器。
  24. 对于只读访问,必须显示调用静态的allocate()方法或更快的allocateDirect()方法来分配ByteBuffer。
  25. 缓冲器上的flip()用于做好让别人读取字节的准备。特殊方法transferTo()和transferFrom()允许将一个通道与另一个通道相连。
  26. ByteBuffer具有asCharBuffer()函数,在进行编码或解码的前提下,可返回包含缓冲器中所有字符的字符串。
  27. ByteBuffer具有可以从其所容纳的字节中产生不同基本类型值的方法。想ByteBuffer插入基本类型的最简单方法是:利用asCharBuffer()等获得该缓冲器的试图,然后调用视图的put()方法。注意:使用ShortBuffer的put()方法需要进行类型转换。
  28. 视图缓冲器可以通过某个特定的基本数据类型的视窗查看其底层的ByteBuffer。对视图的修改都会映射成为对ByteBuffer中数据的修改。视图允许从ByteBuffer一次一个地或成批地读取基本类型值。
  29. ByteBuffer通过一个被包装的字节数组产生,然后通过不同的基本类型的视图缓冲器显示出来。
  30. 字节存放顺序:高位优先和低位有限。
  31. ByteBuffer是将数据移进移出通道的唯一方式,并且只能创建一个独立的基本类型缓冲器,或使用as方法从ByteBuffer中获得。
  32. Buffer缓冲器由数据和可以高效访问即操纵这些数据的四个索引组成,这四个索引是:标记,位置,界限和容量。
  33. 内存映射文件允许创建和修改那些因为太大而不能放入内存的文件。有了内存映射文件,可以假定这个文件都放在内存中,而且可以完全把它当成非常大的数组访问。映射缓冲器可以映射某个大文件的较小部分,其它部分被交换出去。
  34. 文件加锁机制允许同步访问某个作为共享资源的文件,通过FileChannel调用tryLock()或lock(), 就可以获得文件的FileLock,区别在于阻不阻塞。通过FileLock.release()来释放锁。也可用相应重载函数进行文件部分上锁。对独占锁和共享锁的支持由底层的操作系统提供。可以对映射文件部分上锁,只能是通道上的锁可以获得。
  35. Java压缩类库是按字节方式而不是字符方式处理的,支持读写压缩格式的数据流。
  36. 用GZIP进行简单压缩,用Zip进行多文件保存。
  37. JAR文件格式,可以将一组文件压缩到单个压缩文件中,支持跨平台使用。JAR文件有一组压缩文件构成,同时还有一张描述所有这些文件的“文件清单”Manifest(可以自行创建,也可以由JAR程序自动生成)。JDK自带的jar程序可以根据我们的选择自动压缩文件。
  38. Java对象序列化将实现了Serializable接口的对象转换成一个字节序列,并能在以后将这个字节序列完全恢复成原来的对象。这一过程可以通过网络进行,对象可以生成于程序调用之间。
  39. Serializable接口是一个标记接口,不包括任何方法。
  40. 要序列化一个对象,首先创建某些OutputStream对象,然后将其封装到一个ObjectOutputStream对象内。只需调用writeObject()即可将对象序列化,并将其发送给OutputStream。
  41. 要反向序列化一个对象,首先创建某些InputStream对象,然后将其封装到一个ObjectInputStream对象内。只需调用readObject()即可将对象反序列化。
  42. 对象***不仅保存了对象的全景图,而且能追踪对象内所包含的所有引用,并保存这些对象;接着又能对对象内包含的每个这样的引用进行追踪;以此类推,此称为对象网。
  43. 注意在对一个Serializable对象进行还原的过程中,没有调用任何构造器,包括默认构造器,整个对象都是通过从InputStream中取得数据恢复而来的。
  44. 打开文件和读取序列化对象需要Java虚拟机存在对象所属的类的class文件,否则会抛出ClassNotFoundException异常。
  45. 通过实现Externalizable接口,代替实现Serializable接口,来控制***过程。通过会在序列化和反序列化还原过程被自动调用的writeExternal()(只对函数内进行序列化)和readExternal()来实现。当反向序列化时,必须保证对象的类具有public的默认构造器,因为所有的默认构造器会被调用。必须在readExternal()初始化成员和在writeExternal()写入数据,才能恢复成员状态,否则状态为默认值。
  46. 可以用transient关键字在Serializable对象逐个字段关闭序列化。但反序列化对象时,transient对象被置为默认值。
  47. 只要我们在实现Serializable接口,并添加writeObject()和readObject()方法,方法特征签名要准确,则会使用它们而不是默认的序列化机制。
  48. 在调用ObjectOutputStream. writeObject()时,会检查所传递的Serializable对象,看看是否实现了自己的writeObject()。如果实现了,则跳过正常的序列化过程,并调用它的writeObject()。readObject()的情形与此相同。
  49. 在对象的writeObject()和readObject()内部可以分别第一个调用defaultWriteObject()和defaultReadObject()来执行默认序列化和反序列化。
  50. 对象序列化实现了深度复制,深度复制意味着复制整个对象网。同一缓冲区的2个相同反序列对象具有相同内存地址,但跟原对象不一样。不同缓冲区的2个相同反序列对象具有不同的内存地址。
  51. Class是Serializable的,如果将statci置于基类,只会产生一个static字段,因为static字段不能在派生类中复制。static字段没被序列化。必须显式在serializeStaticState()和de serializeStaticState()中保存和读取static字段,才能被序列化。
  52. 因为序列化把private数据保存下来,如果关系安全问题,那么应将其标记为transient。
  53. 对象序列化只限于Java使用,而一种数据持久化方法是将数据转换成XML格式,支持跨平台和语言使用。使用XOM包可以实现这个功能。
  54. Preferences API可以自动存储和读取基本类型和字符串信息,并且每个字符串的存储长度不能超过8K。Preferences是一个键-值组合,存储在一个节点层次结构中,通常以类名来命名单一节点,然后将信息存储于其中。可以用useNodeForPackage()(用户偏好)和system NodeForPackage()(通用的安装配置)来创建节点。节点信息存储地方随操作系统不同而不同,在windows中使用了注册表来存储节点信息。