---------------------- android培训、java培训、期待与您交流! ----------------------
ObjectOutputStream也是字节输出流的子类:
java.lang.Object java.io.OutputStream java.io.ObjectOutputStream
ObjectInputStream是字节输入流的子类:
java.lang.Object java.io.InputStream java.io.ObjectInputStream
ObjectOutputStream通过writeObject(Object obj) ObjectInputStream通过readObject() 通过一个简单的程序测试:
publicstaticvoid objetcSeri()throws Exception {
}
控制台 出现如下错误:
Exception in thread "main" java.io.NotSerializableException: com.huaxia.day21.Personat java.io.ObjectOutputStream.writeObject0(Unknown Source)at java.io.ObjectOutputStream.writeObject(Unknown Source)at com.huaxia.day21.ObjectSerializable.objetcSeri(ObjectSerializable.java:15)at com.huaxia.day21.ObjectSerializable.main(ObjectSerializable.java:9)
说明Person这个类没有实现Serializable接口
更正错误后发现硬盘中多了一个person.obejct文件
其内容为一些我们看不懂的字符:
那么我们是否通过ObjectInputStream读取到文件的内容呢?
public static void readObject() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.object"));
Person person = (Person)ois.readObject();
System.out.println(person);
}
控制台输出结果:name:johnny age:21 country:CHINA
我们来看一下Serializable接口的API
这意思是说:如果实现了序列化接口的类没有显示声明serialVersionUID变量,序列化运行时将计算一个默认的serialVersionUID的值为这个类基于类的变量方面的值
.我们强烈建议所有实现序列化接口的类都要显示的声明serialVersionUID变量,因为默认的serialVersionUID变量值对于类的修改是非常敏感的,因为他的值就是根据
类成员的签名而生成的而不是系统随机生成的,假设我们对类A进行序列化,在一般情况下我们可以反序列化得到类A的信息,如果我们一旦修改了类A,
那么我们再次反序列化就会出现java.io.InvalidClassException 异常的,因为第一次编译类A的时候他的id是一个值,
你修改类A后在再次编译id的值已经变了.因此为了保证在不同的编译器serialVersionUID变量的值一致性,
所以建议把该变量定义成一个private的常量.
下面来模拟这种情况:现在我修改Person类:如下
重新反序列化一次:
public static void readObject() throws Exception {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.object"));Person person = (Person)ois.readObject();System.out.println(person);}
控制台打印店异常:Exception in thread "main" java.io.InvalidClassException: com.huaxia.day21.Person; local class incompatible:
stream classdesc serialVersionUID = -379036032685453711,
local class serialVersionUID = 1208026685571330753
用来将文件或者文件夹封装成对象
---------------------------------------- 管道流:-------------------------------------------
在Java中,可以使用管道流进行线程之间的通信,输入流和输出流必须相连接,这样的通信有别于一般的Shared Data通信,其不需要一个共享的数据空间。
java.lang.Object java.io.OutputStream java.io.PipedOutputStream
package com.huaxia.day21; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream;
class Read implements Runnable { private PipedInputStream is; public Read(PipedInputStream is) { this.is = is; } public void run() { int len=0; byte[] buffer = new byte[1024]; try { //如果不使用循环,如果写入的数据超过1024,那么读的就不完整了 while((len=is.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); } is.close(); } catch (IOException e) { throw new RuntimeException("管道流读取失败"); }finally{ if(is!=null) try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } class Write implements Runnable { private PipedOutputStream os; public Write(PipedOutputStream os) { this.os = os; } public void run() { try { //向管道输出流写入数据 os.write("hello world!".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally{ if(os!=null) try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } } public class PipedStreamTest { public static void main(String[] args) throws IOException { PipedInputStream pis= new PipedInputStream(); PipedOutputStream pos = new PipedOutputStream(); //连接管道流,使之能够通信 pis.connect(pos); //启动写入线程 new Thread(new Write(pos)).start(); //启动读取线程 new Thread(new Read(pis)).start(); } }
java.lang.Object
java.io.RandomAccessFile
public static void readFile() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","r"); System.out.println(raf.readInt()); }
int
to the file as four bytes, high byte first.
public static void writeFile() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","rw"); //下面写入两个人名和其年龄 raf.write("张三".getBytes()); raf.writeInt(23); raf.write("李四".getBytes()); raf.writeInt(35); raf.close(); }
public static void readFile() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","r"); byte[] buffer = new byte[4]; raf.read(buffer);//读取4个字节 int age = raf.readInt();//再读取4个字节 System.out.println("name="+new String(buffer)+"\tage="+age); }
public static void readFile_2() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","r"); raf.seek(8*1); byte[] buffer = new byte[4]; raf.read(buffer);//读取4个字节 int age = raf.readInt();//再读取4个字节 System.out.println("name="+new String(buffer)+"\tage="+age); }
public static void writeFile_2() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","rw"); raf.seek(8*3); //下面写入两个人名和其年龄 raf.write("王五".getBytes()); raf.writeInt(99); raf.close(); }
java.lang.Object java.io.InputStream java.io.FilterInputStream java.io.DataInputStream 和
java.lang.Object java.io.OutputStream java.io.FilterOutputStream java.io.DataOutputStream
public static void writeData() throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream( "dataType.txt")); dos.writeInt(109); dos.writeDouble(123.089); dos.writeBoolean(true); dos.close(); } public static void readData() throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream( "dataType.txt")); int num = dis.readInt(); double d = dis.readDouble(); boolean b = dis.readBoolean(); System.out.println("int:"+num+"\tdouble:"+d+"\tboolean:"+b); }
输出结果:int:109 double:123.089 boolean:true
public static void writeData_2() throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream( "utfdata.txt")); dos.writeUTF("你好中国"); dos.close(); }
现在我们使用换行流往文件中写入相同的数据:
public static void writeData_3() throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("uft-8data.txt"),"utf-8"); osw.write("你好中国"); osw.close(); }
public static void readData_2() throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("utfdata.txt"),"utf-8"); BufferedReader bw =new BufferedReader(isr); //因为是测试,数据只有一行 就不循环 System.out.println(bw.readLine()); }
public static void readData_3() throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream("utfdata.txt")); System.out.println(dis.readUTF()); }
java.lang.Object java.io.InputStream java.io.ByteArrayInputStream
ByteArrayInputStream(byte[] buf) ByteArrayInputStream(byte[] buf, int offset, int length)
java.lang.Object java.io.OutputStream java.io.ByteArrayOutputStream ByteArrayOutputStream() ByteArrayOutputStream(int size)
我们知道在字节流中本来就封装了字节数组,那为什么还要出现这操作字节数组的流呢?
public static void main(String[] args) throws UnsupportedEncodingException { String value = "你好中国"; byte[] b = value.getBytes();// 默认按gbk编码 System.out.println(Arrays.toString(b)); System.out.println(new String(b)); }
输出结果:
public static void main(String[] args) throws UnsupportedEncodingException { String value = "你好中国"; byte[] b = value.getBytes();// 默认按gbk编码 System.out.println(Arrays.toString(b)); String decode = new String(b, "iso8859-1");// 默认按gbk解码 System.out.println(decode); byte[] b2 = decode.getBytes("iso8859-1"); System.out.println(Arrays.toString(b2)); System.out.println(new String(b,"gbk")); } 这个程序就可以解决这个问题,输出结果为:
public static void main(String[] args) { String value = "联通"; byte[] b = value.getBytes(); for(byte by : b){ //打印它的二进制形式 System.out.println(Integer.toBinaryString(by&255)); } }
我们知道GBK每两个字节表示一个字符,而UTF-8不是,那么在底层字节流在读取的时候,她怎么知道几个字节表示一个字符呢?
---------------------- android培训、java培训、期待与您交流! ----------------------