流的概念
流是一个很抽象的概念,当程序需要读写数据时,就会开启一个通向数据源的流,这个数据源可以是文件、内存或者网络连接,在程序读写数据过程中,数据就像在“流”动一样。
由上图可知,流代表经过管道流通的数据。为了进行数据的输入和输出操作,JAVA把不同的输入和输出源(例如键盘、文件和网络连接等)抽象表述为流。
按流向不同,可以分为输入流和输出流。按处理单位不同,可以分为字节流(在数据读取和写入时以字节为单位)和字符流(在数据读取和写入时以字符为单位)。
字节流包括InputStream和OutputStream两个基础类。字符流包括Reader和Writter两个基础类。
字节与字符的概念
字节:通过网络传输信息(或硬盘、内存中存储信息)的单位。字节是用于计量存储容量和传输容量的一种计量单位,1个字节等于8个二进制位。是一个很具体的存储空间。
字符:人们使用的记号,符号。 如'1', '中', 'a', '$', '¥', ……
下面是几种不同编码方式中字符和字节的对应关系:
①、ASCII码中,一个英文字母(不分大小写)占1个字节的空间,一个中文汉字占2个字节。
②、Unicode编码中,一个英文和一个中文都占2个字节。
③、UTF-8编码中,一个英文字符1个字节,一个中文字符3个字节。
字节流和字符流之间的转化
一般在处理图片、多媒体等原始字节信息时,选用字符流,如FileInputStream/FileOutputStream等。如果文件包含的是字符信息,应选用字符流,例如FileReader、FileWriter等。在字符流和字节流相互转化时下需要注意编码问题,如果使用错误的编码格式,流信息将会失真,出现乱码。
InputStreamReader是字节流通向字符流的桥梁,可以完成字节流向字符流的转化。它使用指定的字符集读取字节并将其解码为字符。为提高效率,可以考虑使用BufferedReader包装InputStreamReader。
package test.io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = new FileInputStream("D:\\1.txt");
isr = new InputStreamReader(fis, "UTF-16LE");
br = new BufferedReader(isr);
String content = br.readLine();
System.out.println(isr.getEncoding() + ";" +content);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(isr != null){
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
OutputStreamWriter是字符流通向字节流的桥梁,可以完成字符流到字节流的转化。通过BufferedWriter对OutputStreamWriter进行包装,提高效率。
private void writeFile() {
// TODO Auto-generated method stub
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream("D:\\1.txt");
osw = new OutputStreamWriter(fos, "UTF-8");
bw = new BufferedWriter(osw);
bw.write("测试输入输出流。");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{
if(bw != null){
bw.close();
}
if(osw != null){
osw.close();
}
if(fos != null){
fos.close();
}
}catch (IOException e) {
// TODO: handle exception
}
}
}
使用close()方法会默认执行flush()方法,将缓冲区信息输出。