1、 流的概念
流(Stream)的概念代表的是程序中数据的流通,数据流是一串连续不断的数据的集合。在Java程序中,对于数据的输入/输出操作是以流(Stream)的方式进行的。可以把流分为输入流和输出流两种。程序从输入流读取数据,向输出流写入数据。在java程序中,从输入流读取数据(读到内存中),而从输出流输出数据(从内存存储到文件或显示到屏幕上),参见图
如果数据流中最小的数据单元是字节,那么称这种流为字节流;如果数据流中最小的数据单元是字符,那么称这种流为字符流。在I/O类库中,java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流,java.io.Reader和java.io.Writer分别表示字符输入流和字符输出流。
Java中的流可以按如下方式分类:
●按流的方向不同分为:输入流、输出流
●按处理数据的单位不同分为:字节流、字符流
●按功能不同分为:节点流、处理流
Java语言中,控制数据流的类都放在java.io包中,java.io包中有两大继承体系。以byte处理为主的Stream类,他们的命名方式是XXXStream;以字符处理为主的Reader / Writer类,他们的命名方式XXXReader或XXXWriter。InputStream、OutputStream、Reader、Writer这四个类,是这两大继承体系的父类,如表所示
抽象基类
高级流(缓冲流)
低级流(节点流).
字节流INPUTSTREAM
FILELNPUTSTREAM
BUFFEREDLNPUTSTREAM
BUFFEREDOUTPUTSTREAM
FILEOUTPUTSTREAM
OUTPUTSTREAM
字符流 READER
BUFFEREDREADER
FILEREADER
BUFFEREDWRITER
FILEWRITER
WRITER
(PRINTWRITER)
2、 InputStream字节输入流的层次结构图与常用方法
(1)层次结构
在java.io包中,java.io.InputStream表示字节输入流,java.io.OutputStream表示字节输出流,它们都是抽象类,不能被实例化。所有字节输入流都是InputStream类的直接或者间接子类。输入流的类层次结构如下图所示。
(2)常用方法
InputStream是表示输入字节流的所有类的超类,InputStream类常用的方法如表所示。
方法 | 含义 |
int read() | 一次读取一个byte的数据,并以int类型把数据返回来,如果没有数据可以读了,会返回”-1” |
int read(byte[] buffer) | 把所读取到的数据放在这个byte数组中,返回一个int型的数据,这个int型数据存储了返回的真正读取到的数据byte数 |
int read(byte[] buffer,int offset,int length) | 读取length个字节,并存储到一个字节数组buffer中,并从offset位置开始返回实际读取的字节数 |
void close() | 关闭此输入流并释放与该流关联的所有系统资源 |
3、 OutputStream字节输出流的层次结构图与常用方法
1. 层次结构
所有字节输出流都是OutputStream类的直接或者间接子类,输出流的类层次结构如图所示。
2. 常用方法
OutputStream是表示输出字节流的所有类的超类,OutputStream类常用的方法如表所示
方法 | 含义 |
void write(byte[] buffer) | 将要输出的数组先放在一个byte数组中,然后用这个方法一次把一组数据输出出去 |
void write(byte[] buffer,int off,int len) | 将指定字节数组中从偏移量off 开始的 len 个字节写入此输出流 |
abstract void write(int b) | 将指定的字节写入此输出流 |
void close() | 关闭此输出流并释放与此流有关的所有系统资源 |
void flush() | 刷新此输出流并强制输出所有缓冲的输出字节 |
4、 字符流应用
注意:存文件时要用utf-8编码,否则与我们的工作区编码方式 不匹配,出现乱码
【例】读字符文件
public class Test{
@Test
public void test07() throws IOException {
//文本文件的编码方式改为utf-8
// BufferedReader(Reader in) Reader我们选的是FileReader--->FileReader(File
// file)
File path = new File("d:" + File.separator + "java" + File.separator + "io");
File file = new File(path, "test01.txt");
FileReader fr = new FileReader(file);
// 理解为是一个工具类,他专门用来读文本文件内容
BufferedReader br = new BufferedReader(fr);
while(true) {
String str = br.readLine();// 一次读取一行文本
if (str != null) {
System.out.println(str);
} else {
break;
}
}
}
}
【例】写字符流文件
public class Test{
@Test
public void test08() throws IOException {
//确认文件是utf-8编码
File path = new File("d:" + File.separator + "java" + File.separator + "io");
File file = new File(path, "test01.txt");
FileWriter fileWriter=null;
//第一个参数是为是否append
BufferedWriter bw=null;
try {
fileWriter = new FileWriter(file,true);//第二个参数是表示是否向文件中追加内容
bw=new BufferedWriter(fileWriter);
bw.write("问:没声音吗");//写文本
bw.newLine();//换行
//bw.flush();//刷新后,文本写入文件
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{ //记着关闭流
//如果调用了关闭流的方法,就不用手动调bw.flush()
bw.close();
fileWriter.close();
}
}
}
【例】文本文件拷贝(字符流)
public class Test{
@Test
public void test09() throws IOException{
//从d:/java/io/test01.txt读
//每读到一行,向d:/java/io/test02.txt写入
//step1 初始化输入输出流
FileReader fr=null;
BufferedReader br=null;
FileWriter fw=null;
BufferedWriter bw=null;
try {
System.out.println("开始初始化输入输出流");
//初始化输入流
File path = new File("d:" + File.separator + "java" + File.separator + "io");
File inputFile = new File(path, "test01.txt");
fr=new FileReader(inputFile);
br=new BufferedReader(fr);
//初始化输出流
File outputFile = new File("d:" + File.separator + "java" + File.separator + "io"+File.separator +"test02.txt");
fw=new FileWriter(outputFile,true);
bw=new BufferedWriter(fw);
//step2 死循环从输入流(也就是text01.txt)一行一行读
while(true){
//一次读取一行
String content=br.readLine();
if(content!=null){//如果读到的内容不为null
System.out.println("读到了一行,开始写入");
bw.write(content);
bw.newLine();
}else{
System.out.println("拷贝完成");
break;
}
}
} catch (Exception e) {
// 打印异常
e.printStackTrace();
}finally{
//关闭流
bw.close();
fw.close();
br.close();
fr.close();
}
}
}
4、 字节流应用
【例】文本文件拷贝(字节流
//字节流拷贝
@Test
public void test07(){
//FileInputStream BufferedInputStream
//FileOutputStream BufferedOutputStream
File file=new File("E:" + File.separator + "java6" + File.separator + "filestudy", "01.png");
FileInputStream in=null;
BufferedInputStream bis=null;
File file2=new File("E:" + File.separator + "java6" + File.separator + "filestudy", "10.png");
FileOutputStream out=null;
BufferedOutputStream bos=null;
try {
in=new FileInputStream(file);
bis=new BufferedInputStream(in);
out = new FileOutputStream(file2);
bos=new BufferedOutputStream(out);
//读取到的字节的长度
int b;
//bis.read() 每次读取到的字节数,注意此处给b重新赋值 ,否则死循环
while((b=bis.read())!=-1){
//把b长度的字节写入到bos里
bos.write(b);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
bos.close();
out.close();
bis.close();
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}