java的核心类库_Java核心类库——IO原理和用法

Java IO流(InputStream/OutputSteam)

什么是IO流?

byte序列的读写,Java中的IO流是实现输入/输出的基础.

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 importjava.io.FileInputStream;2 importjava.io.IOException;3 importjava.io.InputStream;4

5 public classInputStreamDemo {6 public static voidmain(String[] args)7 throwsIOException {8 String file = "out.txt";9 InputStream in = newFileInputStream(file);10 intb;11 while((b=in.read())!=-1){//read()方法

12 System.out.print(Integer.toHexString(b) + " ");13 }14 in.close();15

16 in = newFileInputStream(file);17 //in.available() 可以读取的数据个数,小文件一般是文件长度

18 byte[] buf = new byte[in.available()];19 in.read(buf);//read(byte[] buf)方法重载

20 in.close();21 for (bytec : 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 11010110

28 }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 classOutputStreamDemo {4 public static voidmain(String[] args)5 throwsIOException{6 String file = "out.txt";7 OutputStream out = newFileOutputStream(file);8 out.write(65);//在文件中是以16进制存储的,对应0x41

9 out.write(66);//0x42

10 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 importjava.io.BufferedInputStream;2 importjava.io.BufferedOutputStream;3 importjava.io.FileInputStream;4 importjava.io.FileOutputStream;5 importjava.io.IOException;6 importjava.io.InputStream;7

8 public classBufferedStreamDemo {9 public static void main(String[] args) throwsIOException {10 //BufferedInputStream普通写法

11 String file = "out.txt";12 InputStream ins = newFileInputStream(file);13 BufferedInputStream bufin= newBufferedInputStream(ins);14 intb;15 while((b=bufin.read())!=-1){16 System.out.println(Integer.toHexString(b));17 }18 //常用写法,只要用到FileInputStream的地方都可以套一个BufferedInputStream用来提升性能

19 BufferedInputStream in = newBufferedInputStream(20 new FileInputStream("out.txt"));21

22 //BufferedOutputStream

23 BufferedOutputStream out = newBufferedOutputStream(24 new FileOutputStream("out.txt"));25 out.write(65);26 }27 }

4.基本类型数据的写出和读入

DataOutputStream  方法:readInt()  readLong()  readBoolean()等

写出(写)

1 例子2 import java.io.*;3 public classDataOutDemo {4 public static voidmain(String[] args)5 throwsIOException{6 String file = "data.dat";//项目文件夹

7 OutputStream out = newFileOutputStream(file);8 //DataOutputStream 实现基本类型数据的序列化9 //将基本类型数据拆开为byte序列,写入到out流中

10 DataOutputStream dos = newDataOutputStream(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 importjava.io.DataInputStream;2 importjava.io.FileInputStream;3 importjava.io.IOException;4 importjava.io.InputStream;5

6 public classDataInDemo {7 public static voidmain(String[] args)8 throwsIOException{9

10 String file = "data.dat";11

12 InputStream in = newFileInputStream(file);13 //DataInputStream 从基本流中读取基本类型数据,实现基本14 //类型数据的反序列化

15 DataInputStream dis = newDataInputStream(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 fe

27 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 importjava.io.FileOutputStream;2 importjava.io.IOException;3 importjava.io.OutputStream;4

5 public classCharIODemo {6 public static voidmain(String[] args)7 throwsIOException{8 String str = "ABCD中国";9 System.out.println(str);10 //Java 的字符是16位 Unicode值,而文件是8位Byte序列11

12 //GBK

13 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 = newFileOutputStream(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 = newFileOutputStream(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-> String

42 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 importjava.io.BufferedInputStream;2 importjava.io.BufferedReader;3 importjava.io.FileInputStream;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6

7 public classTestReaderDemo {8 public static voidmain(String[] args)9 throwsIOException{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.txt

19 BufferedReader in = newBufferedReader(20 newInputStreamReader(21 newBufferedInputStream(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 importjava.io.IOException;2 importjava.io.PrintWriter;3 importjava.util.Scanner;4

5 public classSyncWriteDemo {6 public static voidmain(String[] args)7 throwsIOException{8 Scanner in = newScanner(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 importjava.io.BufferedInputStream;2 importjava.io.BufferedOutputStream;3 importjava.io.FileInputStream;4 importjava.io.FileOutputStream;5 importjava.io.ObjectInputStream;6 importjava.io.ObjectOutputStream;7 importjava.io.Serializable;8

9 public classObjectIODemo {10 public static voidmain(String[] args)11 throwsException{12 String file = "obj.dat";13 ObjectOutputStream out = newObjectOutputStream(14 newBufferedOutputStream(15 newFileOutputStream(file)));16 Foo foo =newFoo();17 out.writeObject(foo);//将foo引用的对象,序列化到文件中

18 out.close();19

20 //读出

21 ObjectInputStream in = newObjectInputStream(22 newBufferedInputStream(23 newFileInputStream(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 importjava.io.ByteArrayInputStream;2 importjava.io.ByteArrayOutputStream;3 importjava.io.ObjectInputStream;4 importjava.io.ObjectOutputStream;5

6 public classDeepcopyDemo {7 public staticObject deepCope(Object obj){8 try{9 //1. 对象序列化10 //缓冲流: 字节数组输出流

11 ByteArrayOutputStream buf =

12 newByteArrayOutputStream();13 //对象输出流

14 ObjectOutputStream out =

15 newObjectOutputStream(16 newByteArrayOutputStream());17

18 out.writeObject(obj);//序列化对象到buf中

19 out.close();20

21 //2 .对象的反序列化

22 byte[] ary =buf.toByteArray();23 ByteArrayInputStream bais =

24 newByteArrayInputStream(ary);25 ObjectInputStream in =

26 newObjectInputStream(bais);27 Object o = in.readObject();//从ary反序列化

28 in.close();29 returno;30

31 }catch(Exception e){32 e.printStackTrace();33 throw newRuntimeException(e);34 }35 }36 }

以上用到的ByteArrayInputStream和ByteArrayOutputStream

下面有一个ByteArrayInputStream和ByteArrayOutputStream的例子

例子

1 importjava.io.ByteArrayInputStream;2 importjava.io.ByteArrayOutputStream;3 importjava.io.IOException;4 importjava.util.Arrays;5

6 importcom.tarena.day18.IOUtils;7

8 public classByteArrayIODemo {9 public static voidmain(String[] args)10 throwsIOException{11 byte[] ary = {1,-1,127,-128};12 //{00000001, 11111111, 01111111, 10000000}

13 ByteArrayInputStream in = newByteArrayInputStream(ary);14 int b = in.read();//1 00000000 00000000 00000000 00000001

15 System.out.println(b);16 b =in.read();17 System.out.println(b);//255 00000000 00000000 00000000 11111111

18 b =in.read();19 System.out.println(b);//127 00000000 00000000 00000000 01111111

20 b =in.read();21 System.out.println(b);//128 00000000 00000000 00000000 10000000

22 b =in.read();23 System.out.println(b);//-1 11111111 11111111 11111111 11111111

24 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值