疯狂java讲义总结-NO15

1.使用序列化机制可以把内存中的java对象转换成二进制字节流,这样就可以把java对象存储到磁盘里,或者在网络上传输java对象,这也是java提供分布式编程的重要基础。
2. 不管是文件还是目录都是使用File来操作的,File能新建、删除、重命名文件和目录,File不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
3. public class FileTest
{
public static void main (String[]args)
throws IOException
{
//以当前路径来创建一个File对象
File file=new File(”.”);
//直接获取文件名,输出一点
System.out.println(file.getName());
//获取相对路径的父路径可能出错,下面代码输出null
System.out.println(file.getParent());
//获取绝对路径
System.out.println(file.getAbsoluteFile());
//获取上一级路径
System.out.println(file.getAbsoluteFile().getParent());
//在当前路径下创建一个临时文件
File tmpFile=File.createTempFile("aaa",”.txt",file);
//指定当JVM退出时删除该文件
tmpFile.deleteOnExit();
//以系统当前时间作为新文件名来创建新文件
File newFile=new File (System.currentTimeMillis()+””);
System.out.println("newFile对象是否存在:"+newFile.exists());
//以指定newFile对象来创建一个文件
newFile.createNewFile();
//以newFile对象来创建一个日录,因为newFile己经存在
//所以下面方法返回false,即无法创建该日录
newFile.mkdir();
//使用1ist()方法列出当前路径下的所有文件和路径
String[] fileList=file.list();
System.out.println(”===当前路径下所有文件和路径如下===’,
for (String fileName:fileList)
{
System.out.println(fileName);
}
//listRoots()静态方法列出所有的磁盘根路径
File[] roots=File.listRoots();
System.out.println(”====系统所有根路径如下=二二=”);
for (File root:roots)
{
System.out.println(root);
}
}
}
4.在File类的list()方法中可以接收一个FilenameFilter参数,通过该参数可以只列出符合条件的文件。(文件过滤器)
5.按照流的流向来分,可以将流分为输入流和输出流:
输入流:只能从中读取数据,而不能向其写入数据。
输出流:只能向其写入数据,而不能从中读取数据。
这里的输入、输出都是从程序所在内存角度来划分的。
6.java的输入流主要由InputStream和Reader作为基类,而输出流则主要由OutputStream和Writer作为基类。他们都是一些抽象基类,无法直接创建实例。
7.字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的是8位的字节,而字符流操作的是16位的字符。字节流主要由 InputStream和OutputStream作为基类,而字符流主要由Reader和Writer作为基类。
8.按照流的角色来分,可以分为节点流和处理流。 可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流,称为节点流,节点流也被称为低级流,处理流则用于对一个已经存在的流进行连接或封装,通过封装后的流来实现数据读/写功能,处理流也被称为高级流。
9. 实际上,Java使用处理流来包装节点流是一种典型的装饰器设计模式,通过使用处理流来包装不同的节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入/输出功能。因此处理流也被称为包装流。
10.java的处理流模型则体现了java输入/输出流设计的灵活性,处理流的功能主要有:
性能的提高:主要以增加缓冲的方式来提高输入/输出的效率。
操作的便捷: 处理流可能提供了一系列便捷的方法来一次输入/输出大批量的内容,而不是输入输出一个或多个“水滴”。
11.每个中文字符占2字节,如果read()方法读取时值读取到了半个中文字符,这将导致乱码。
12. 与JDBC编程一样,程序里打开的文件IO资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件IO资源。Java 7改写了所有的IO资源类,它们都实现了AutoCloseable接口,因此都可通过自动关闭资源的try语句来关闭这些IO流。
13.write(byte[]/char[] buf,int off,int len)将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。
14. 使用Java的IO流执行输出时,不要忘记关闭输出流,关闭输出流除了可以保证流的物理资源被回收之外,可能还可以将输出流缓冲区中的数据flush到物理节点里(因为在执行close()方法之前,自动执行输出流的flush()方法)。
15.在输出字符串内容时,字符串内容的最后是\r\n,这是Windows平台的换行符,通过这种方式就可以让输出内容换行;如果是UNIX/Linux/BSD等平台,则使用\n就作为换行符。
16.处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入/输出方法,让程序员只需关心高级流的操作。
17. 使用处理流时的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入/输出功能,让节点流与底层的I/O设备、文件交互。
18. 实际识别处理流非常简单,只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流就一定是处理流:而所有节点流都是直接以物理IO节点作为构造器参数的。
19. 在使用处理流包装了底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的处理流即可。关闭最上层的处理流时,系统会自动关闭被该处理流包装的节点流。
20. 如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入/输出的内容是二进制内容,则应该考虑使用字节流。
21. 计算机的文件常被分为文本文件和二进制文件两大类—--所有能用记事本打开并看到其中字符内容的文件称为文本文件,反之则称为二进制文件。
22. 增加缓冲功能可以提高输入、输出的效率,增加缓冲功能后需要使用flush()才可以将缓冲区的内容写入实际的物理节点。
23. 与普通的输入/输出流不同的是,RandomAccessFile支持“随机访问”的方式,程序可以直接跳转到文件的任意地方来读写数据。
24.与OutputStream、Writer等输出流不同的是,RandomAccessFile允许自由定位文件记录指针,RandomAccessFile可以不从开始的地方开始输出,因此RandomAccessFile可以向已存在的文件后追加内容。如果程序需要向已存在的文件后追加内容,则应该使用RandomAccessFile 。
25. RandomAccessFile的方法虽然多,但它有一个最大的局限,就是只能读写文件,不能读写其他节点。
26. RandomAccessFile类有两个构造器,其实这两个构造器基本相同,只是指定文件的形式不同而已,一个使用String参数来指定文件名,一个使用File参数来指定文件本身。
27.“r“以只读方式打开指定文件。
“rw“以读写的方式打开指定文件。
“rws“
“rwd“
28. 多线程断点的网络下载工具(如F1ashGet等)就可通过RandomAccessFile类来实现,所有的下载工具在下载开始时都会建立两个文件:一个是与被下载文件大小相同的空文件,一个是记录文件指针的位置文件,下载工具用多条线程启动输入流来读取网络数据,并使用RandomAccessFile将从网络上读取的数据写入前面建立的空文件中,每写一些数据后,记录文件指针的文件就分别记下每个andomAccessFile当前的文件指针位置—--网络断开后,再次开始下载时,每个RandomAccessFile都根据记录文件指针的文件中记录的位置继续向下写数据。
29. 对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,通过网络将这种二进制流传输到另一个网络节点。其他程序一旦获得了这种二进制流(无论是从磁盘中获取的,还是通过网络获取的),都可以将这种二进制流恢复成原来的Java对象。
30.为了让某个类时可序列化的,该类必须实现如下两个接口之一:
(1)Serializable
(2)Externalizable
31. 序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以保存在磁盘土,或通过网络传输,以备以后重新恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
32. 对象的序列化(Serialize)指将一个Java对象写入IO流中,与此对应的是,对象的反序列化( Deserialize)则指从IO流中恢复该Java对象。
33. 反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对时,必须提供该Java对象所属类的class文件,否则将会引发ClassNotFoundException异常。
34. 当反序列化读取Java对象时,并没有看到程序调用该构造器,这表明反序列化机制无须通过构造器来初始化Java对象。
35. 如果使用序列化机制向文件中写入了多个Java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。
36. 当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参数的构造器,要么也是可序列化的—--否则反序列化时将抛出nvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类中定义的成员变量值不会序列化到二进制流中。
37. 由于java序列化机制使然:如果多次序列化同一个Java对象时,只有第一次序列化时才会把该Java对象转换成字节序列并输出,这样可能引起一个潜在的问题—--当程序序列化一个可变对象时,只有第一次使用writeObject()方法输出时才会将该对象转换成字节序列并输出,当程序再次调用writeObject()方法时,程序只是输出前面的序列化编号,即使后面该对象的实例变量值已被改变,改变的实例变量值也不会被输出。
38. 当使用Java序列化机制序列化可变对象时一定要注意,只有第一次调用wirteObject()方法来输出对象时才会将对象转换成字节序列,并写入到ObjectOutputStream;在后面程序中即使该对象的实例变量发生了改变,再次调用writeObject()方法输出该对象时,改变后的实例变量也不会被输出。
39. 当对某个对象进行序列化时,系统会自动把该对象的所有实例变量依次进行序列化,如果某个实例变量引用到另一个对象,则被引用的对象也会被序列化;如果被引用的对象的实例变量也引用了其他对象,则被引用的对象也会被序列化,这种情况被称为递归序列化。
40. 通过在实例变量前面使用transient关键字修饰,可以指定Java序列化时无须理会该实例变量。
41. transient关键字只能用于修饰实例变量,不可修饰Java程序中的其他成分。

 

posted @ 2016-08-11 18:17  ﹍。GG╊棒°  阅读(141)  评论(0)    收藏  举报