----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1.ObjectInputStream ObjectOutputStream 对象存在于堆内存中,堆内存回收后,对象就不存在了。通过流的方式可以将对象存放在磁盘上,就做对象的持久化存储,也叫序列化或对象的可串行性。
通过实现Serializable接口实现序列化:
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致InvalidClassException
。可序列化类可以通过声明名为"serialVersionUID"
的字段(该字段必须是静态 (static)、最终 (final) 的 long
型字段)显式声明其自己的 serialVersionUID。
反序列化用在 writeObject 和 readObject 方法。类对象可能发生改变,改变前实现的持久化数据可能就无法被再次正确读入,如果没有显示的声明serialVersionUID运行时会出现错误。 local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = -681721207272073045 通过报的异常可以发现是序列号不一致导致的,如果显示初始化了,就会通过验证,只是会出现null值。
transient修饰成员属性表示该属性不进行序列化,这样的成员属性不能通过readObject和writeObject操作。
代码如下:
public static void main(String[] args) throws Exception {
Person person=new Person("wangwu",13);
Person person1=new Person("zhangsan",13);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("demo.txt"));
objectOutputStream.writeObject(person);
objectOutputStream.writeObject(person1);
objectOutputStream.flush();
objectOutputStream.close();
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("demo.txt"));
Object object;
while((object=objectInputStream.readObject()) !=null){//运行时会报EOFException异常,通过设置一个多余的结束Person,更改条件可解决。
System.out.println(((Person)object).getName());
}
}
public class Person implements Serializable {
private static final long serialVersionUID = 1L;//对Person类进行序列化
2.PipedInputStream和PipedOutputStream 结合多线程使用,因为单线程可能造成死锁,管道流可以对接到一起。
read方法是阻塞式方法,线程就处于等待。connect方法实现管道输入流和输出流的连接。代码如下:
class Read implements Runnable{
private PipedInputStream in;
public Read(PipedInputStream in) {
this.in = in;
}
@Override
public void run() {
try {
byte[] buf=new byte[1024];
int len =in.read(buf);
String s=new String(buf,0,len);
System.out.println(s);
//pipedInputStream.close();
} catch (Exception e) {
System.out.println("管道读取流失败");
}
}
}
class Write implements Runnable{
private PipedOutputStream out;
public Write(PipedOutputStream out) {
this.out = out;
}
@Override
public void run() {
try {
out.write("你好".getBytes());
out.close();
} catch (Exception e) {
System.out.println("管道输出流失败");
}
}
}
3.RandomAccessFile
该类不算是io体系中的子类,而是直接继承与Object类,但是它io包中的一员,因为具有读写功能。随机存取文件的行为类似存储在文件系统中的一个大型字节数组。
该文件指针可以通过 getFilePointer
方法读取,并通过 seek
方法设置。该类只能操作文件,而且操作文件还有模式。可以实现多线程数据的分段写入。
mode 参数指定用以打开文件的访问模式。允许的值及其含意为:
值
含意
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException
。"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 "rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到基础存储设备。 "rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到基础存储设备。
如果操作模式为r的话,如果文件不存在,会报异常。如果模式为‘rw’的话,不会报异常,如果不存在则自动创建,如果存在不会覆盖。
write()方法只能写最低八位。
代码示例:
public static void readFile() throws IOException{
RandomAccessFile raf=new RandomAccessFile("ran.txt", "r");
byte[] buf=new byte[1024];
int len=raf.read(buf);
raf.seek(4);//如果不重新设置的话,会报EOFException
int age=raf.readInt();
System.out.println(new String(buf,0,len));
System.out.println("age="+age);
}
public static void writeFile() throws IOException{
RandomAccessFile accessFile=new RandomAccessFile("ran.txt", "rw");
accessFile.write("lisi".getBytes());
accessFile.writeInt(97);
accessFile.close();
}
4.基本数据类型
DataInputStream 和DataOutputStream
用于操作基本数据类型,基本数据类型读取时如果byte型数据读取时顺序和存储时的顺序不同的话,最后一个整数的读取会有问题。利用
read方法读取基本类型数据,会自动读取下一个符合的数据类型的数据。
public static void write() throws IOException{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("demo.txt"));
dos.writeBoolean(false);
dos.writeByte(34);
dos.writeByte(23);
dos.writeByte(32);
dos.writeBoolean(true);
dos.close();
}
public static void read() throws IOException{
DataInputStream dis=new DataInputStream(new FileInputStream("demo.txt"));
boolean b=dis.readBoolean();
boolean b1=dis.readBoolean();
byte bt=dis.readByte();
byte bt1=dis.readByte();
byte bt2=dis.readByte();
//float c=dis.readFloat();
System.out.println(b+""+bt+b1+bt2);
}
5.ByteArrayOutputStream和ByteArrayInputStream
ByteArrayOutputStream缓冲区会随着数据的不断写入而自动增长,ByteArrayInputStream 在关闭此流后且没有生成 IOException 时,可以调用此类中的toByteArray()
和toString()
方法。源和目的都是在内存中,因为都开辟了缓冲区,所以不用调用close方法。
源设备:键盘System.in 硬盘 FileStream 内存 ArrayStream
目的设备:控制台 System.out 硬盘 FileStream 内存 ArrayStream
6.字节编码
public static void main(String[] args) throws Exception{
String string="你好";
//byte[] buf=string.getBytes("GBK");
byte[] buf=string.getBytes("UTF-8");
//byte[] buf=string.getBytes("ISO8859-1");
for (byte b : buf) {
System.out.println(b);
}
String str=new String(buf,0,buf.length, "UTF-8");
System.out.println(str);
}
7.综合例子
public class Test {
/*
* 有五个学生,每个学生有三门课的成绩, 从键盘上输入以上数据(包括姓名和三门课的成绩) 输入的格式是:zhangsan,30,30,56
* 计算出总成绩 并把学生的成绩和计算出的总成绩高低顺序存放在磁盘中的"student.tx"文件中 1.描述学生对象
* 2.定义一个可操作学生对象的工具类 思想:1.通过获取键盘录入的每一行数据,并将改行的数据取出封装成学生对象
* 2.因为学生很多,就需要存储,使用到集合,因为要对总分排序,所以用Treeset 3.将集合的信息写入到文件中
*/
public static void main(String[] args) throws IOException {
Comparator<Student>com=Collections.reverseOrder();
Set<Student> stus = StudentInfoTool.getStudents(com);
StudentInfoTool.writeToFile(stus);
}
}
class StudentInfoTool {
public static Set<Student> getStudents() throws IOException {
return getStudents(null);
}
public static Set<Student> getStudents(Comparator<Student> com)
throws IOException {
BufferedReader bfr = new BufferedReader(
new InputStreamReader(System.in));
String line = null;
Set<Student> stus;
if (com == null)
stus = new TreeSet<Student>();
else
stus = new TreeSet<Student>(com);
while ((line = bfr.readLine()) != null) {
if ("over".equals(line))
break;
String[] info = line.split(",");
Student stu = new Student(info[0], Integer.parseInt(info[1]),
Integer.parseInt(info[1]), Integer.parseInt(info[2]));
stus.add(stu);
}
bfr.close();
return stus;
}
public static void writeToFile(Set<Student> stus) throws IOException {
BufferedWriter bufw = new BufferedWriter(new FileWriter("student.txt"));
for (Student student : stus) {
bufw.write(student.toString() + "\t");
bufw.write(student.getSum() + "");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}
class Student implements Comparable {
private String name;
private int match, english, chinese;
private int sum;
Student(String name, int match, int english, int chinese) {
this.name = name;
this.match = match;
this.english = english;
this.chinese = chinese;
this.sum = match + english + chinese;
}
public String getName() {
return name;
}
public int getSum() {
return sum;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + sum;
return result;
}
@Override
public boolean equals(Object obj) {
while (!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student stu = (Student) obj;
return stu.name.equals(this.name) && stu.sum == this.sum;
}
@Override
public int compareTo(Object o) {
Student stu = (Student) o;
int num = new Integer(this.sum).compareTo(new Integer(stu.sum));
if (num == 0) {
return this.name.compareTo(stu.name);
}
return num;
}
@Override
public String toString() {
return "student[" + name + "," + match + "," + english + "," + chinese
+ "]";
}
}
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------