1)流的写入读取机制及流的特点
1.低级流是指直接访问源文件的流,高级流是指对已经存在的低级流进行包装,使其在读或写的时候拥有低级流的读写特点,又能拥有高级流读写的便利,比如
BufferedReader已经可以一读读一行了(readLine方法)BufferedWriter开始有newLine(); Writer中继承的可以直接写字符串等等
2)InputStream与OutputStream家族局部继承图。
1,ObjectIutputStream和ObjectOutputStream是对于Object类型的对象进行序列化的流。
*序列化的实质是将对象的完整信息写入到目标位置。反序列化的实质是从目标文件中读取对象的完整信息,然后根据信息克隆出一个新的对象。
*当进行序列化时如果该类没有实现Serializable接口会报错。Serializable接口中没有方法,只是一个标识;
*实现了Serializable接口,JVM会特殊待遇:会给该类添加一个属性, static final long serialVersionUID ;
*不让系统自动生成,自己写一个序列化版本号. static final long serialVersionUID = 123123123L;
*如果不想让该属性参加序列化,需要使用transient关键字修饰,当反序列化时该属性为null。
transient关键字的详细解释
* 注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化
解释:反序列化后类中static型变量的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。 我们查看序列化的文件可以看到,其中没有static 这个属性的 字段。而输出的这个值是因为根据文件信息新建了一个对象,该对象的Static属性是共享的。
4)扩展:我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,
则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。
2.DateIputStream和DateOutputStream是直接对基本数据操作(操作过程包含其值及类型);
代码示例:
import java.io.*;
//循环读取
public class FileInputStreamTest04
{
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("FileInputStreamTest01.java");
//循环读取
byte[] bytes = new byte[1024]; //每次读取1KB
/*
while(true){
int temp = fis.read(bytes);
if(temp==-1) break;
//将byte数组中有效的数据转换成字符串.
System.out.print(new String(bytes,0,temp));
}
*/
//这里的read()返回int 表示此次读取的字节数
//升级循环 ,这里是一次性读取的n(取决于数组容量)个内容读入数组中,在调用String的构造方法截取。
int temp = 0;
while((temp=fis.read(bytes)) != -1){
System.out.print(new String(bytes,0,temp));
}
fis.close();
}
}
补充:
1.FileInputStream中还有两个常用方法-- int available()和skip(),前者是判断剩余文件的字节数,后者是跳过int n个字节读取;
2.FileOutputStream在写出的时候如果目标文件不存在则自动创建。其有两个重要的构造方法:
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。 |
FileOutputStream(String name, boolean append)
创建一个向具有指定
name 的文件中写入数据的输出文件流。
|
看后者的参数可以知道,使用前者时要注意写出文件存在覆盖问题。
3)Reader与Writer家族局部继承图。
1.BufferedReader已经可以一读读一行了(readLine方法);
2.从Writer中继承的可以直接写字符串。
3.BufferedWriter开始有newLine();
注意:printStreatment和printWriter都是打印字符串(包括中文),
但是printStream是自动刷新,而在使用printWriter的时候切记要刷新flush()
代码示例:
/*
使用BufferedReader和BufferedWriter完成复制
*/
import java.io.*;
public class Copy03
{
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new FileReader("Copy03.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("c:/Copy03.java"));
/*
String temp = null;
while((temp=br.readLine())!=null){
bw.write(temp);
bw.newLine();
}*/由于代码原因会比源文件多出一个空格
String temp = null;
int count = 0;
//以下的代码处理了多出空格的问题
while(true){
count++;
//readLine()方法来源于BufferedReader
temp = br.readLine();
if(temp==null){
break;
}
if(count>1){
//newLine()来源于BufferedWriter
bw.newLine();
}
//直接写入字符串来源于Writer
bw.write(temp);
}
bw.flush();
br.close();
bw.close();
}
}