serializable果某个类实现 以下两个接口,, 那么他们的序列化方式会有某种不同, 而真正来处理实现序列化的操作就是ObjectInputStream
ObjectOutputStream
interface Serializable 是 一个标记性接口,,实现该接口,则由JVM 自动实现, 实现类的 序列化和反序列化。
管道流的主要作用是可以进行两个线程之间的通信,分为管道输出流和管道输入流,如果想要进行管道输出,则必须把输出流连在输入流之上。
线程1->PipedOutputStream(输出流)|PipedInputStream(输入流)->线程2要注意使用connect连接
PipedOutputStream PipedInputStream 连接起来就是一个管道,管道输出流可以向管道写入数据 管道输入流可以从管道读取数据这种Decorator 装饰 的设计模式 大大增强了java流的功能可以在构造流的时候连接 管道输入输出流 也可以通过connect函数连接
练习代码:
public class PiedInputStreamDemo {
public static void main(String[] args) {
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream();
try {
pi.connect(po);
} catch (IOException e) {
throw new RuntimeException("管道流连接异常");
}
Read read= new Read(pi);
Write write = new Write(po);
new Thread(read).start();
new Thread(write).start();
}
}
class Read extends Thread{
PipedInputStream pi;
Read(PipedInputStream pipi){
this.pi = pipi;
}
@Override
public void run() {
try {
byte[] value = new byte[1024];
int len = 0;
len = pi.read(value);
System.out.println(new String(value,0,len));
} catch (Exception e) {
throw new RuntimeException("管道流读取异常");
}finally{
try {
pi.close();
} catch (IOException e) {
throw new RuntimeException("管道流关闭异常");
}
}
}
}
class Write extends Thread{
PipedOutputStream po;
Write(PipedOutputStream pipo){
this.po = pipo;
}
@Override
public void run() {
try {
po.write("管道流写入的数据.........".getBytes());
} catch (IOException e) {
throw new RuntimeException("管道流写入异常");
}finally{
try {
po.close();
} catch (IOException e) {
throw new RuntimeException("管道流关闭异常");
}
}
}
}
该类不算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。其实完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读r,读写rw;如果模式为只读r。不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。如果模式为rw。操作的文件不存在,会自动创建,如果存在,则不覆盖。public class RandomAccessDemo { static File file = new File("RandomAccessFileTest.txt"); public static void main(String[] args) { method_1(); method_2(); } public static void method_1(){ RandomAccessFile raf = null; try { raf = new RandomAccessFile(file, "rw"); raf.write("张三".getBytes()); //写入一个字节,也就是8位二进制数,不能完全保留数据 //raf.write(69); //按四个字节将 int 写入该文件,先写高字节 raf.writeInt(69); raf.write("李四".getBytes()); raf.writeInt(23); } catch (FileNotFoundException e) { throw new RuntimeException("随机读取流创建失败"); }catch(IOException ex){ throw new RuntimeException("读取写入数据异常"); }finally{ if(raf != null) try { raf.close(); } catch (IOException e) { throw new RuntimeException("随机读取流关闭异常"); } } } public static void method_2(){ RandomAccessFile raf = null; try { raf = new RandomAccessFile(file, "r"); byte[] value = new byte[4]; //设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 raf.seek(8); //尝试跳过输入的 n 个字节以丢弃跳过的字节。 //raf.skipBytes(8); raf.read(value); System.out.println("name=" + new String(value)); //再次调用read()指针会自增 System.out.println("age=" + raf.readInt()); } catch (Exception e) { throw new RuntimeException("随机读文件流异常"); }finally{ if(raf != null){ try { raf.close(); } catch (IOException e) { throw new RuntimeException("随机读取流关闭异常"); } } } } }
可以用于操作基本数据类型的数据的对象练习代码:/* *可以操作基本数据类型的对象 */ public class DateStreamDemo { public static void main(String[] args) { write_1(); read_1(); writeUTF(); readUTF(); } public static void write_1(){ DataOutputStream dato = null; try { dato = new DataOutputStream(new FileOutputStream("DataOutputStream.txt")); dato.write(234); dato.writeBoolean(true); dato.writeDouble(2.654); } catch (Exception e) { throw new RuntimeException("数据流异常"); }finally{ if(dato != null){ try { dato.close(); } catch (IOException e) { throw new RuntimeException("数据流关闭异常"); } } } } public static void read_1(){ DataInputStream dis = null; try { dis = new DataInputStream(new FileInputStream("DataOutputStream.txt")); int num =dis.read(); boolean b = dis.readBoolean(); double d = dis.readDouble(); System.out.println("num=" + num+ "\nboolean=" + b + "\ndouble=" + d); } catch (Exception e) { throw new RuntimeException("数据流读取异常"); }finally{ if(dis != null){ try { dis.close(); } catch (IOException e) { throw new RuntimeException("数据读取流关闭异常"); } } } } public static void writeUTF(){ DataOutputStream dos = null; try { dos = new DataOutputStream(new FileOutputStream("UTF.txt")); dos.writeUTF("你好");//用这种方法写入的数据只能用DataInputStream对象读取
} catch (Exception e) { throw new RuntimeException("数据写入流异常"); }finally{ if(dos != null){ try { dos.close(); } catch (IOException e) { throw new RuntimeException("数据写入流关闭异常"); } } } } public static void readUTF(){ DataInputStream dis = null; try{ dis = new DataInputStream(new FileInputStream("UTF.txt")); System.out.println(dis.readUTF()); }catch(IOException e){ throw new RuntimeException("数据读取流异常"); }finally{ if(dis != null){ try { dis.close(); } catch (IOException e) { throw new RuntimeException("数据读取流关闭异常"); } } } } }
ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组。ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可以改变长度的字节数组。这就是数据目的地。因为这两个流对象都操作数组,并没有使用系统资源。所以,不用进行close关闭。在流操作规律讲解时:源设备
- 键盘 System.in,硬盘 FileStream,内存 ArrayStream
目的设备
- 控制台 System.out,硬盘 FileStream,内存 ArrayStream
同理
- CharArrayReader与CharArrayWrite(操作字符数组)
- StringReader与StringWrite(操作字符串)
都是以内存为目的和源的操作
练习代码:public class ByteArrayStreamDemo { public static void main(String[] args) { //ByteArrayInputStream 是InputStream的子类,所以可以调用父类的方法 ByteArrayInputStream bin = new ByteArrayInputStream("hello world!".getBytes()); ByteArrayOutputStream bot = new ByteArrayOutputStream(); int i = 0; while((i = bin.read()) != -1){ bot.write(i); } System.out.println(bot.size()); System.out.println(bot.toString()); } }
字符流的出现为了方便操作字符更重要的是加入了编码转换通过子类转换流来完成
- InputStreamReader
- OutputStreamWriter
在两个对象进行构造的时候可以加入字符集
编码表的由来
- 计算机只能识别二进制数据,早起留来是电信号
- 为了方便应用计算机,让他可以识别各个国家的文字。
- 就将各个国家的文字用数字来表示,并一一对应,形成一张表。
- 这就是编码表
常见的编码表
- ASCII:美国标准信息交换码。用一个字节的7位可以表示。
- ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示。
- GB2312:中国的中文编码表。
- GBK:中国的中文编码表升级,融合了更多的中文文字符号。
- Unicode:国际标准码,融合了多种文字。所以文字都用两个字节来表示,java语言使用的就是Unicode
- UTF-8:最多用三个字节来表示一个字符。
- ......
编码:字符串变成字节数组解码:直接数组变成光字符串。String-->byte[]:str.getBytes(charsetName);byte[] -->String:new String(byte[],charsetName);练习代码:public class EncodeDemo { public static void main(String[] args) { method_1(); encode(); } public static void method_1(){ OutputStreamWriter outw = null; try { //指定编码格式 outw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8"); outw.write("你好"); //outw.flush(); } catch (Exception e) { // TODO: handle exception }finally{ if(outw != null){ try { outw.close(); } catch (IOException e) { throw new RuntimeException("转换写入流关闭异常"); } } } } // 编码:字符串变成字节数组 // 解码:直接数组变成光字符串。 // String-->byte[]:str.getBytes(charsetName); // byte[] -->String:new String(byte[],charsetName); public static void encode (){ String s = "你好"; try { byte[] value = s.getBytes("gbk"); System.out.println(Arrays.toString(value)); System.out.println(new String(value,"gbk")); //如果出现解码错误,需要用解码的格式编码后解码 String str = new String(value,"ISO8859-1"); System.out.println(str); byte[] temp = str.getBytes("ISO8859-1"); System.out.println(Arrays.toString(temp)); System.out.println(new String(temp,"gbk")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("编码异常"); } } }