Java IO使用总结

Java IO 总结

IO 是什么?其实就是Java中的一种输入和输出功能,也可以理解为对文件的写入和读出的操作。Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出源抽象表述为”流”。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
流有输入和输出,输入时是流从数据源流向程序。输出时是流从程序传向数据源,而数据源可以是内存,文件,网络或程序等。

在Java中有输入、输出两种IO流,每种输入、输出流又分为字节流和字符流两大类。


Java IO.png

在介绍IO流之前,我们先明白Java中字节和字符的关系。

1.字节与字符

1.1 概念
  • 字节:每个字节(byte)有8bit组成
  • 字符:一个汉字或者英文字母
1.2 两者关系

Java采用unicode编码,2个字节来表示一个字符,而一个字符表示一个汉字或英文字母,具体字符与字节之间的大小转换视编码情况而定,这些不是我们需要关心的事情,我们只需要知道不同的编码对应的转换规则不一样。有时候读取的数据是乱码,就是因为编码方式不一致,需要进行转换,然后再按照unicode进行编码。

getBytes(String charsetName)使用指定的编码方式将此String编码为 byte 序列,并将结果存储到一个新的 byte 数组中。如果不指定将使用操作系统默认的编码方式,我的电脑默认的是GBK编码。

 String str = "hello world 你好哦";
        int byte_len = str.getBytes().length;
        int len = str.length();
        System.out.println("字节长度为:" + byte_len);
        System.out.println("字符长度为:" + len);
// 编译工具为IDEA,输出结果如下
字节长度为:21
字符长度为:15
系统默认编码方式:UTF-8

2.IO流的分类

2.1 输入流和输出流

根据数据流向不同分为:输入流和输出流。

输入流:从流中读取数据
输出流:将数据写入到流中
输入输出流.jpg
2.2输入流和输出流

字节流和字符流和用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同。
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。字节流和字符流的区别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

2.3节点流和处理流

按照流的角色来分,可以分为节点流和处理流。
可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流,称为节点流,节点流也被成为低级流。
处理流是对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能,处理流也被称为高级流。

//节点流,直接传入的参数是IO设备
FileInputStream fis = new FileInputStream("test.txt");
//处理流,直接传入的参数是流对象
BufferedInputStream bis = new BufferedInputStream(fis);
  1. 节点流
类型 字符流 字节流
File(文件) FileReader
FileWriter
FileInputStream
FileOutputStream
Memory Array CharArrayReader
CharArrayWriter
ByteArrayInputStream
ByteArrayOutputStream
Memory Array StringReader
StringWriter
Pipe(管道) PipedReader
PipedWriter
PipedInputStream
PipedOutputStream
  1. 处理流 ,用来包装节点流
类型 字符流 字节流
Buffering BufferedReader
BufferedWriter
BufferedInputStream
BufferedOutputStream
Filtering FilterReader
FilterWriter
FilterInputStream
FilterOutputStream
Converting between Bytes and Characters InputStreamReader
OutputStreamWriter
Object Serialization ObjectInputStream
ObjectOutputStream
DataConversion DataInputStream
DataOutputStream
Counting LineNumberReader LineNumberInputStream
Peeking Ahead PushbackReader PushbackInputStream
Printing PrintWriter PrintStream

(1)Buffering缓冲流:在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader与BufferedWriter、BufferedInputStream与BufferedOutputStream。
(2)Filtering 滤流:在数据进行读或写时进行过滤:FilterReader与FilterWriter、FilterInputStream与FilterOutputStream。
(3)Converting between Bytes and Characters 转换流:按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader):InputStreamReader、OutputStreamWriter。
(4)Object Serialization 对象流 :ObjectInputStream、ObjectOutputStream。
(5)DataConversion数据流: 按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream 。
(6)Counting计数流: 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream。
(7)Peeking Ahead预读流: 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream。
(8)Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。

3.IO流的四大基类

3.1 字符流 Reader和Writer

字符流原理:
Reader是字符输入流的父类
Writer是字符输出流的父类
字符流是以字符(char)为单位读写数据的,一次处理一个unicode
字符流的底层仍然是基本的字节流

  Reader常用方法:

   int read():读取一个字符,返回的int值“低16位”有效
   int read(char[] chs):从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量

  Writer的常用方法:

    void write(int c):写出一个字符,写出给定int值“低16位”表示的字符
    void write(char[] chs):将给定字符数组中所有字符写出
    void write(String str):将给定的字符串写出
    void write(char[] chs,int offset,int len):将给定的字符数组中从offset处开始连续的len个字符写出

3.2 字符输入流
  InputStream是所有字节输入流的父类,其定义了基础的读取方法,如下:
  int read():读取一个字节,以int形式返回,该int值的“低8位”有效,若返回值为-1则表示EOF
  int read(byte[] d):尝试最多读取给定数组length个字节并存入该数组,返回值为实际读取到的字节量

  OutputStream是所有字节输出流的父类,其定义了基础的写出方法,如下:

  void write(int d):写出一个字节,写的是给定的int的“低8位”
  void write(byte[] d):将给定的字节数组中的所有字节全部写出
  

4.常见用法

4.1 对象序列化
 // 创建写出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
 // 对象写出流
 ObjectOutputStream oos = new ObjectOutputStream(bos);
 // 写对象
 oos.writeObject(this);
 // 关闭
 oos.close();

 // 创建写出流
 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
 // 转成对象流
 ObjectInputStream ois = new ObjectInputStream(bis);
 personClone = (Person) ois.readObject();
 ois.close();
4.2 文件读写
// 字节流方式写出
FileOutputStream fos = new FileOutputStream("fos.txt");
String str = "Hello,World";
byte[] date = str.getBytes();
fos.write(date);
System.out.println("写出完毕");
fos.close();

// 字节流方式写入
FileInputStream fis = new FileInputStream("fos.txt");
int d = -1;
while((d=fis.read())!=-1){
    System.out.print((char)d);
}
fis.close();


4.3 转换流读写

// 转换流写入
FileOutputStream fos = new FileOutputStream("osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
osw.write("测试");
osw.close();

// 转换流读取
FileInputStream fis = new FileInputStream("osw.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");
int d = -1;
while((d=isr.read())!=-1){
    System.out.print((char)d);
}
isr.close();

4.4 缓冲流读写

//创建缓冲字节输出流
FileOutputStream fos = new FileOutputStream("fos.txt");
//所有字节被存入缓冲区,等待一次性写出
BufferedOutputStream bos = new BufferedOutputStream(fos);
String str = "Hello Java";
byte[] date = str.getBytes();
bos.write(date);
//关闭流之前,缓冲输出流会将缓冲区内容一次性写出
bos.close();

 //创建缓冲字节输入流
FileInputStream fis = new FileInputStream("fos.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
int d = -1;
//缓冲读入,实际上并非是一个字节一个字节从文件读取
while((d=bis.read())!=-1){
    System.out.println(d);
}
bis.close();

5.总结

使用IO流通过四点来完成:

5.1 明确数据的来源和数据到达的目的地。

来源:输入流 [InputStream,Reader]。
目的:输出流 [OutputStream,Writer]。

5.2操作的数据是否是纯文本。

是:字符流,使用Reader与Writer;
否:字节流,使用InputStream与OutputStream。

5.3明确要使用哪个具体的对象。 通过设备来进行区分:

源设备:内存用数组,硬盘就加file,键盘用System.in;
目的设备:内存用数组,硬盘就加file,键盘用System.out。

5.4明确是否还需要其他额外功能:例如

(1)是否需要较高的效率,即是否需要使用缓冲区,是就加上Buffered;
(2)是否需要转换,是,就使用转换流,InputStreamReader 和 OutputStreamWriter。

你可能感兴趣的:(Java IO使用总结)