Java IO流与对象IO序列化(转)
来源:互联网 发布:淘宝上能买手机号码 编辑:程序博客网 时间:2024/06/01 08:45
byte序列的读写,Java中的IO流是实现输入/输出的基础.
Java将数据从源(文件、内存、键盘、网络)读入到内存 中,形成了流,然后将这些流还可以写到另外的目的地(文件、内存、控制台、网络),之所以称为流,是因为这个数据序列在不同时刻所操作的是源的不同部分。
2、分类
按照不同的分类标准,IO流分为不同类型。主要有以下几种方式:按照数据流方向、数据处理的单位和功能。还有一些分类比如:对象流、缓冲流、压缩流、文件流等等。其实都是节点流和处理流的子分类。不管流的分类是多么的丰富和复杂,其根源来自于四个基本的类。这个四个类的关系如下:
字节流
字符流
输入流
InputStream
Reader
输出流
OutputStream
Writer
2.1输入流与输出流。
数据从内存到硬盘,通常认为是输出流,即写操作;相反,从硬盘到内存,通常认为是输入流,即读操作;这里的输入、输出是从内存的角度划分的。
2.2字节流和字符流
字节流和字符流区别非常简单,它们的用法几乎一样。区别在于字节流和字符流所处理的最小数据单元不同。
处理最小数据单元
基类
字节流
8
In/OutStream
字符流
16
Reader/writer
3.3节点流和处理流
节点流是可以从或向一个特定的地方(节点)读写数据,也叫 低级流。如FileReader。
处理流是在对节点流封装的基础上的一种流,通过封装后来实现数据的读写功能,也叫高级流。
节点流
未经封装,low level stream
处理流
封装过, high level stream
常用节点流
父 类 InputStream OutputStream Reader Writer
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流
数 组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
字符串 StringReader StringWriter 对字符串进行处理的节点流
管 道 PipedInputStream PipedOutputStream PipedReader PipedWriter 对管道进行处理的节点流
常用处理流(关闭处理流使用关闭里面的节点流)
父 类 InputStream OutputStream Reader Writer
缓冲流 BufferedImputStrean BufferedOutputStream BufferedReader BufferedWriter
----需要父类作为参数构造,增加缓冲功能,避免频繁读写硬盘,可以初始化缓冲数据的大小,由于带了缓冲功能,所以就写数据的时候需要使用flush 方法咯 转换流 *InputStreamReader OutputStreamWriter- 要inputStream 或OutputStream 作为
参数,实现从字节流到字符流的转换数据流 *DataInputStream DataOutputStream -提供将基础数据类型写入到文件中,或者
读取出来,为什么要有这个流呢?看这样的分析,如果没有这种流的话,有一个long,本身只占8 个字节,如果我要写入到文件,需要转成字符串,然后在转成字符数组,那空间会占用很多,但是有了这种流之后就很方便了,直接将这8 个字节写到文件就完了。。是不是既节约了内存空间有让程序写起来更加方便简单了呐。写倒是很简单,但是读取的时候就注意了,根据读取的数据类型,指针会往下移,所以你写的顺序必须要和读的顺序一致才能完成正确的需求.
3.4 Java输入输出流
总结。
分类
字节输入流
字节输出流
字符输入流
字符输出流
抽象基类
InputStream
OutputStream
Reader
Writer
访问文件
FileInputStream
FileOutputStream
FileReader
FileWriter
访问数组
ByteArrayInputStream
ByteArrayOutputStream
CharArrayReader
CharArrayWriter
访问管道
PipedInputStream
PipedOutputStream
PipedReader
PipedWriter
访问字符串
StringReader
StringWriter
缓冲流
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
转换流
InputStreamReader
OutputStreamWriter
对象流
ObjectInputStream
ObjectOutputStream
抽象基类
FilterInputStream
FilterOutputStream
FilterReader
FilterWriter
打印流
PrintStream
PrintWriter
推回输入流
PushbackInputStream
PushbackReader
特殊流
DataInputStream
DataOutputStream
1)
InputStream : 抽象类读取数据的过程 包含读取方法read();
in 模仿了读取小说的过程
简单说 : in是读取文件的
OutputStream:抽象了写出数据的过程 包含写出方法write();
out模仿了写笔记记录的过程
简单说 : out是写入文件的
基本的byte流
InputStream(抽象方法read())
|--- FileInputStream(read()在文件上读取) 节点流
|
|--- FilterInputStream 过滤器流,输入流功能的扩展
| |--- DataInputStream(readInt()) 基本类型数据的读取
| |--- BufferedInputStream 提供读取缓冲区管理
| --- ObjectInputStream 过滤器流,依赖基本byte流,扩展对象的反序列化
OutputStream(抽象方法write())
|--- FileOutputStream(write()在文件上写实现写入) 节点流
|
|--- FilterOutputStream 过滤器流,输出流功能的扩
| |--- DataOutputStream(writerInt()) 基本类型数据的写出
| |--- BufferedOutputStream 提供了输出缓冲区管理
| --- ObjectOutputStream 过滤器流,依赖基本byte流,扩展对象的序列化
注意:除节点流外都是过滤器流
字符流,可以处理字符编码,底层依赖于byte流
Reader 读取文本
| --- InputStreamReader 过滤去,依赖基本byte输入流
| 实现文本编码的解析
|
| --- BufferedReader 过滤器, 需要依赖Reader 实例
| 提供了readLine()方法, 可以在文本文件中读取一行
| 是常用的文本读取方法
Writer
| --- OutputStreamWriter 过滤器,,依赖基本byte输出流
| 实现文本编码
| --- PrintWriter 过滤器,依赖于Writer 流
| 提供了输出文本常有方法println()
2) EOF = End of File = -1 (文件读到末尾会返回-1)
3) 输入流的基本方法
InputStream in = new InputStream(file) / /file是文件名
int b = in.read(); 读取一个byte无符号填充到int底八位,-1是EOF
int.read(byte[] buf) 读取数据填充到buf中
int.read(byte[] buf,int start,int size) 读取数据填充到buf中
in.close 关闭输入流
4)输出流的基本方法:
OutputStream out = new OutputStream(file) / /file是文件名
out.write(int b) 写出一个byte 到流 b 的底八位写出
out.write(byte[] buf) 将buf的一部分写入流中
out.write(byte[] buf, int start, int size) 将buf的一部分写入流中
out.flush() 清理缓存
out.close
1.FileInputStream (read()在文件上读取) 节点流
方法: read() 从输入流中读取数据的下一个字节
read(byte[] buf) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf中
read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。
例
1 import java.io.FileInputStream; 2 import java.io.IOException; 3 import java.io.InputStream; 4 5 public class InputStreamDemo { 6 public static void main(String[] args) 7 throws IOException { 8 String file = "out.txt"; 9 InputStream in = new FileInputStream(file);10 int b;11 while((b=in.read())!=-1){//read()方法12 System.out.print(Integer.toHexString(b) + " ");13 }14 in.close();15 16 in = new FileInputStream(file);17 //in.available() 可以读取的数据个数,小文件一般是文件长度18 byte[] buf = new byte[in.available()];19 in.read(buf);//read(byte[] buf)方法重载20 in.close();21 for (byte c : buf) {22 System.out.print(Integer.toHexString(c & 0xff) + " ");23 // c & 0xff --->将16进制写成0xff的格式24 //ffffffd6---> d625 //11111111 11111111 11111111 11010110 &对应相乘26 //00000000 00000000 00000000 11111111 0xff27 //00000000 00000000 00000000 1101011028 }29 }30 }
2 FileOutputStream(write()在文件上写实现写入) 节点流
方法 :write(int b) 将指定的字节写入此输出流。
write(byte[] buf) 将 b.length 个字节从指定的 byte 数组写入此输出流。
write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
例子
1 import java.io.*; 2 3 public class OutputStreamDemo { 4 public static void main(String[] args) 5 throws IOException{ 6 String file = "out.txt"; 7 OutputStream out = new FileOutputStream(file); 8 out.write(65);//在文件中是以16进制存储的,对应0x41 9 out.write(66);//0x4210 byte[] buf = {(byte)0xd6,(byte)0xd0};11 out.write(buf);12 out.flush();//刷出缓存,清理缓冲区,保证可靠写 13 out.close();14 }15 }
3.BufferedInputStream和BufferedOutputStream 的 用法
BufferedInputStream(FileInputStream in)
BufferedOutputStream(FileOutputStream out)
可以提高性能
例子
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 8 public class BufferedStreamDemo { 9 public static void main(String[] args) throws IOException {10 //BufferedInputStream普通写法11 String file = "out.txt";12 InputStream ins = new FileInputStream(file);13 BufferedInputStream bufin= new BufferedInputStream(ins);14 int b;15 while((b=bufin.read())!=-1){16 System.out.println(Integer.toHexString(b));17 }18 //常用写法,只要用到FileInputStream的地方都可以套一个BufferedInputStream用来提升性能19 BufferedInputStream in = new BufferedInputStream(20 new FileInputStream("out.txt"));21 22 //BufferedOutputStream23 BufferedOutputStream out = new BufferedOutputStream(24 new FileOutputStream("out.txt"));25 out.write(65);26 }27 }
4.基本类型数据的写出和读入
DataOutputStream 方法:readInt() readLong() readBoolean()等
写出(写)
1 例子 2 import java.io.*; 3 public class DataOutDemo { 4 public static void main(String[] args) 5 throws IOException{ 6 String file = "data.dat";//项目文件夹 7 OutputStream out = new FileOutputStream(file); 8 //DataOutputStream 实现基本类型数据的序列化 9 //将基本类型数据拆开为byte序列,写入到out流中10 DataOutputStream dos = new DataOutputStream(out);11 dos.write(-2);12 dos.writeInt(-2);13 dos.writeLong(-2);14 dos.writeByte(-2);15 dos.writeDouble(-2);16 dos.writeShort(-2);17 dos.writeFloat(-2);18 dos.writeBoolean(true);19 dos.writeChar('中');20 dos.close();21 22 }23 }
DataInputStream 方法: writeInt() writeChar() 等8种
读入(读)
1 import java.io.DataInputStream; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 public class DataInDemo { 7 public static void main(String[] args) 8 throws IOException{ 9 10 String file = "data.dat";11 12 InputStream in = new FileInputStream(file);13 //DataInputStream 从基本流中读取基本类型数据,实现基本14 //类型数据的反序列化15 DataInputStream dis = new DataInputStream(in);16 int b = dis.read();17 int i = dis.readInt();18 long l= dis.readLong();19 byte bx = dis.readByte();20 double d = dis.readDouble();21 short s = dis.readShort();22 float f = dis.readFloat();23 boolean bol = dis.readBoolean();24 char c = dis.readChar();25 dis.close();26 System.out.print( b +" ");//254 fe27 System.out.print(i+" ");28 System.out.print(l+" ");29 System.out.print(bx+" ");30 System.out.print(d+" ");31 System.out.print(s+" ");32 System.out.print(f+" ");33 System.out.print(bol+" ");34 System.out.print(c+" ");35 36 }37 }
5 字符串的序列化(文字的编码方案)
从char序列到byte序列 的转换,叫"编码"
1) String 字符串本质上是Char
2)utf-16be 编码-----将16位char从中间切开为2个byte
utf -16be是将 unicode char[] 序列化为byte[]的编码方案
能够支持65535个字符编码,英文浪费空间
如:
char[] = ['A', 'B', '中']
对应 0041,0042,4e2d
utf-8:国际标准,是将unicode编码为byte序列的方案,采用变长编码 1-N方案,其中英文1个byte,中文3个byte
unicoded的" 中": 4e 2d = 01001110 00101101
utf-8的"中":e4 b8 ad =11100100 10111000 10101101
1110xxxx 10xxxxxx 10xxxxxx
以0开头的是英文(0-127)
110表示连续2字节表示一个字符
1110表示连续3字节表示一个字符
每个数据字节以10开头
GBK: 中国标准,支持20000+中日韩文,英文编码1byte,中文2byte
与unicode不兼容,中文windows默认gbk
ISO8859-1:只支持255个英文字符,不支持中文(Sun服务器默认编码,如tomcat等)
例子
1 import java.io.FileOutputStream; 2 import java.io.IOException; 3 import java.io.OutputStream; 4 5 public class CharIODemo { 6 public static void main(String[] args) 7 throws IOException{ 8 String str = "ABCD中国"; 9 System.out.println(str);10 //Java 的字符是16位 Unicode值,而文件是8位Byte序列11 12 //GBK13 System.out.println("GBK编码方案,对字符编码");14 String file = "gbk.txt";15 OutputStream out = new FileOutputStream(file);//默认GBK编码方案16 byte[] gbk = str.getBytes("GBK");17 out.write(gbk);18 out.close();19 IOUtils.print(file);20 //UTF-16BE,每个编码是2个字节21 System.out.println("UTF-16BE编码方案,对字符编码");22 file = "utf-16be.txt";23 out = new FileOutputStream(file);24 byte[] utf16be = str.getBytes("UTF-16BE");25 out.write(utf16be);26 out.close();27 IOUtils.print(file);28 29 //UTF-8,英文是1个字节,中文是3个字节30 System.out.println("UTF-8编码方案,对字符编码");31 file = "utf-8.txt";32 out = new FileOutputStream(file);33 byte[] utf8 = str.getBytes("UTF-8");//编码string -> byte[]34 out.write(utf8);35 out.close();36 IOUtils.print(file);37 38 byte[] buf = IOUtils.read("utf-8.txt");39 //new String(buf,"UTF-8"),构造器可以将 byte编码序列40 //解码为 char序列(字符串)41 String s = new String(buf,"UTF-8");//解码byte-> String42 System.out.println(s);43 }44 }
6 字符流IO(Reader Writer)
1) 字符的处理,一次处理一个字符(unicode编码)
2) 字符的底层仍然是基本的字节流
3) 字符流的基本实现
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWriter 提供char流到byte流,按照编码处理
4) 字符流的过滤器
是字符读写的功能扩展,极大的方便了文本的读写操作
BufferedReader : readLine() 一次读取一行
PrintWriter : println() 一次打印一行
5)读取一个文本文件
InputStream is = new FileInputStream("test.txt");
Reader in = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(in);
或者
BufferedReader in = new BufferedReader(new FileReader(filename));
例子:
1 import java.io.BufferedInputStream; 2 import java.io.BufferedReader; 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 public class TestReaderDemo { 8 public static void main(String[] args) 9 throws IOException{10 //Scanner BufferedReader都是流的功能扩展,是过滤器11 // 不能单独使用,最终需要依赖于基本byte流(in)12 //Scanner 提供了nextLine()方法//Java5以后13 //BufferedReader 提供了 readLine()方法,读取一行14 //readLine()读取到文件末尾返回null15 16 //逐行读取文本文件,显示到系统控制台17 //工作中常用18 String file = "in.txt"; //为当前工作区workspace/项目名/in.txt19 BufferedReader in = new BufferedReader(20 new InputStreamReader(21 new BufferedInputStream(22 new FileInputStream(file)),"gbk"));23 String str;24 while((str = in.readLine()) != null){25 System.out.println(str);26 }27 in.close();28 }
6)写出一个文本文件
PrintWriter out = new PrintWriter(new FileWriter(new FileOutputStream(filename)));
或者
PrintWriter out = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream(filename)))
例子
1 import java.io.IOException; 2 import java.io.PrintWriter; 3 import java.util.Scanner; 4 5 public class SyncWriteDemo { 6 public static void main(String[] args) 7 throws IOException{ 8 Scanner in = new Scanner(System.in); 9 String file = "sync.txt";10 PrintWriter out = new PrintWriter(file,"UTF-8");11 while(true){12 String str = in.nextLine();13 out.println(str);14 if("q".equalsIgnoreCase(str)){15 break;16 }17 }18 out.close();19 }20 }
7)系统的默认编码,中文一般是GBK
如何查看默认编码?
String encoding = System.getProperty("file.encoding");
7 对象的IO序列化和深层复制
什么是对象序列化:
将对象Object转换为byte序列,反之叫做对象的反序列华
1)序列化流,是过滤流
ObjectOutputStream 方法 writeObject() 对象的序列化
ObjectInputStream 方法readObject() 对象的反序列化
2)序列化接口(Serializable)
对象必须实现"序列化接口Serializable"才能进行序列化,否则将出现不能序列化的异常
Serializable是一个空的接口,没有任何方法 ,仅作为序列化的一个标识
3)JavaBean 规范规定,Java类必须实现Serializable接口
Java API中的类大多是符合Java Bean规范的,基本都实现了Serializable
4) 对象的序列化可以变相实现对象的深层复制
例子
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.io.Serializable; 8 9 public class ObjectIODemo {10 public static void main(String[] args) 11 throws Exception{12 String file = "obj.dat";13 ObjectOutputStream out = new ObjectOutputStream(14 new BufferedOutputStream(15 new FileOutputStream(file)));16 Foo foo =new Foo();17 out.writeObject(foo);//将foo引用的对象,序列化到文件中18 out.close();19 20 //读出21 ObjectInputStream in = new ObjectInputStream(22 new BufferedInputStream(23 new FileInputStream(file)));24 Foo foo1 = (Foo)in.readObject();//对象反序列化25 in.close();26 System.out.println(foo1.name);27 28 System.out.println("深层复制:对象被复制,对象属性也被复制");29 System.out.println(foo==foo1);//false 对象复制了(一层)30 System.out.println(foo.name == foo1.name);//false ,属性被复制了(二层)31 //利用序列化 和 反序列化 可以简洁的实现 对象的深层复制32 }33 34 }35 class Foo implements Serializable{//Serializable没有声明方法36 String name = "Tom";37 }
浅层复制与深层复制
1)java的默认规则是浅层复制,性能好,但隔离性差,如(clone(),Arrays.copyOf)
浅层复制 : 对象的引用不同,但对象中属性的引用相同
2)利用序列化可以实现深层复制
深层复制: 对象的引用不同,但对象中的属性的引用也不相同
例
1 import java.io.ByteArrayInputStream; 2 import java.io.ByteArrayOutputStream; 3 import java.io.ObjectInputStream; 4 import java.io.ObjectOutputStream; 5 6 public class DeepcopyDemo { 7 public static Object deepCope(Object obj){ 8 try{ 9 //1. 对象序列化10 // 缓冲流: 字节数组输出流11 ByteArrayOutputStream buf =12 new ByteArrayOutputStream();13 //对象输出流14 ObjectOutputStream out = 15 new ObjectOutputStream(16 new ByteArrayOutputStream());17 18 out.writeObject(obj);//序列化对象到buf中19 out.close();20 21 //2 .对象的反序列化22 byte[] ary = buf.toByteArray();23 ByteArrayInputStream bais = 24 new ByteArrayInputStream(ary);25 ObjectInputStream in = 26 new ObjectInputStream(bais);27 Object o = in.readObject();//从ary反序列化28 in.close();29 return o;30 31 }catch(Exception e){32 e.printStackTrace();33 throw new RuntimeException(e);34 }35 }36 }
以上用到的ByteArrayInputStream和ByteArrayOutputStream
下面有一个ByteArrayInputStream和ByteArrayOutputStream的例子
例子
1 import java.io.ByteArrayInputStream; 2 import java.io.ByteArrayOutputStream; 3 import java.io.IOException; 4 import java.util.Arrays; 5 6 import com.tarena.day18.IOUtils; 7 8 public class ByteArrayIODemo { 9 public static void main(String[] args) 10 throws IOException{11 byte[] ary = {1,-1,127,-128};12 // {00000001, 11111111, 01111111, 10000000}13 ByteArrayInputStream in = new ByteArrayInputStream(ary);14 int b = in.read();//1 00000000 00000000 00000000 0000000115 System.out.println(b);16 b = in.read();17 System.out.println(b);//255 00000000 00000000 00000000 1111111118 b = in.read(); 19 System.out.println(b);//127 00000000 00000000 00000000 0111111120 b = in.read();21 System.out.println(b);//128 00000000 00000000 00000000 1000000022 b = in.read();23 System.out.println(b);//-1 11111111 11111111 11111111 1111111124 in.close();25 26 ByteArrayOutputStream out = new ByteArrayOutputStream();//默认开辟32byte的数组作为输出目标27 //如果满了就自动扩容28 //out:[0,0,0,0,0,0,0,.....]29 //30 out.write(1);//[1,0,0,0,0,0,....]31 out.write(-2);//[1,fe,0,0,0,0,0,....]32 out.write(-1);//[1,fe,ff,0,0,0,0,....]33 out.close();34 byte[] buf = out.toByteArray();//复制有效部分35 IOUtils.print(buf);//[01, fe, ff ]36 }37 38 }39 40 41
- Java IO流与对象IO序列化(转)
- Java IO流与对象IO序列化
- Java IO流与对象IO序列化
- java.io 与对象序列化 笔记
- Java的IO流与对象的序列化浅谈
- Java IO流(对象序列化)
- python的io 与java的io流的使用及对象的序列化
- Java IO 对象的序列化与反序列化
- 警告@SuppressWarnings("serial")与对象序列化(Java IO)
- 【JAVA开发之IO流1-5】IO流之Object流与序列化对象存储
- Java IO 对象流与序列化 Java编程思想读书笔记
- Java IO _对象序列化
- Java IO _对象序列化
- 【JAVA IO】_对象序列化笔记
- 【JAVA IO】_对象序列化笔记
- Java IO _对象序列化
- 【JAVA IO】_对象序列化笔记
- IO流与序列化
- 引用计数的写时拷贝
- Java NIO整理(转)
- linux桥街模式
- windows python install Matplotlib
- 深入分析 Java I/O 的工作机制(转)
- Java IO流与对象IO序列化(转)
- php字符串函数(2)替换、分割、填充、去除
- Java 序列化的高级认识(转)
- Java序列化的机制和原理(转)
- Java序列化(转)
- eclipse 中 tomcat的配置
- Java程序员面试中的多线程问题(转)
- Java多线程编程总结(转)
- java多线程总结一(转)