流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
我们可以把输入输出流从以下几个方面分类:
(1)输入流或输出流(从流的方向划分)
(2)节点流或处理流(从流的分工划分)
(3)面向字符的流或面向字节的流(从流的内容划分)
图:
1.面字符的流----Reader和Writer类
字符流的源或目标通常是文本文件。字符流可以实现Java程序中的内部格式和文本文件、显示输出、键盘输入等外部格式之间的转换。Reader和Writer是java.io包中所有字符流的抽象基类。Reader和Writer的子类又可以分为两大类:节点流、处理流。蓝色为节点流;空白色为处理流。
使用例子:
(1)读取文本文件
代码:
import java.io.*;
class Reader{
public static void main(String[] args)
{
String fileName="D:/java/Hello.txt";
String line;
try{
//创建文件输入流并放入缓冲流中
BufferedReader in=new BufferedReader(new FileReader(fileName));
line =in.readLine();//读取一行内容
while((c=in.read())!=-1)
{
System.out.print((char)c);
}
in.close();//关闭缓冲流,文件输入流自动也被关闭
}
catch(IOException iox)//如果出现异常则处理
{
System.out.println("Problem reading"+fileName);
}
}
}
运行结果如下:
(2)写文本文件
import java.io.*;
class Write{
public static void main(String[] args)throws IOException
{
String fileName = "D:/java/HelloWorld.txt";
FileWriter writer=new FileWriter(fileName);//创建一个给定文件名的输出流对象
writer.write("Hello you one \n");//往流里写字符数组
writer.write("This is my hello world, \n");
writer.write("How do you think about it? \n");
writer.write("我也可以输入中文\n");
writer.close();//关闭流
}
}
运行结果:
2.面向字节的流---InputStream和OutputStream类
这种流通常用来读写诸如图片、声音之类的二进制数据。ObjectInputStream和ObjectOutputStream可以用来读、写对象;PipedInputStream和PipedOutputStream用来完成线程之间的通信;蓝色为节点流、透明为处理流。
使用例子:
(1)写二进制文件:
import java.io.*;
class Writebyte{
public static void main(String[] args){
String fileName="D:/data1.dat";
int value0 = 255, value1 = 0, value2 = -1;
try{
//将DataOutputStream与FileOutputStream连接可输出不同类型的数据
DataOutputStream out=new DataOutputStream(new FileOutputStream(fileName));
out.writeInt(value0);
out.writeInt(value1);
out.writeInt(value2);
out.close();
}
catch(IOException iox){
System.out.println("Problem writing"+ fileName);
}
}
}
(2)读二进制文件:
import java.io.*;
class Readbyte{
public static void main(String[] args){
String fileName="D:/data1.dat";
int sum = 0;
try{
DataInputStream instr = new DataInputStream(new BufferedInputStream(new FileInputStream(fileName)));
sum +=instr.readInt();
sum +=instr.readInt();
sum +=instr.readInt();
System.out.println("The sum is "+sum);
instr.close();
}
catch(IOException iox){
System.out.println("Problem reading"+fileName);
}
}
}
运行结果:
3.区别与联系
面向字符的流是专门用于字符数据的,面向字节的流通常用于一般目的的输入输出。从根本说,所有的数据都是由8位的字节组成,所以从逻辑上讲,所有的流可以被称为字节流。那么我们看看如何用字节流读取文本文件。
区别:
字节流读取的时候,读到一个字节就返回一个字节,字符流使用了字节流读到一个或多个字节时先去查指定的编码表,将查到的字符返回。
字节流可以处理所有类型数据,如图片、mp3、avi等,而字符流只能处理字符数据。
字符流和字节流如何联系呢?答案——通过转换流!
转换流是字节流和字符流之间的桥梁,该流对象中可以对读取到的字节数据进行啊制定编码表的编码转换。
什么时候使用?
(1)当字节和字符之间有转换动作时
(2)流操作的数据需要进行编码表的指定时
具体对象表现:
(1)InputStreamReader:字节到字符的桥梁
(2)OutputStreamWriter:字符到字节的桥梁
例子:使用InputStream类读取文本文件并显示
import java.io.*;
class InputStream{
public static void main(String[] args){
try{
FileInputStream s=new FileInputStream("D:/java/Hello.txt");
int c;
while((c = s.read())!= -1) System.out.write(c);
s.close();
}
catch(IOException iox){
System.out.println("Problem reading");
}
}
}
运行结果:
总结
使用时首先,考虑最原始的数据格式是什么,数据来源是什么,其次考虑是输入还是输出,是否需要转换流,是否需要格式化,还要考虑是否要缓冲。
数据来源:(1)是文件: FileInputStream, FileOutputStream, (字节流 )FileReader, FileWriter( 字符 );(2)是 byte[] : ByteArrayInputStream,ByteArrayOutputStream( 字节流 );(3)是 Char[]: CharArrayReader,CharArrayWriter( 字符流 );(4)是 String: StringBufferInputStream,StringBufferOuputStream ( 字节流 )StringReader, StringWriter( 字符流 );(5 )网络数据流: InputStream, OutputStream,( 字节流 )Reader, Writer( 字符流 )
数据格式:(1)二进制格式(只要不能确定是纯文本的) : InputStream,OutputStream 及其所有带 Stream 结束的子类 ;(2 )纯文本格式(含纯英文与汉字或其他编码方式); Reader, Writer及其所有带 Reader, Writer 的子类
输入输出用:(1)输入: Reader, InputStream 类型的子类;(2 )输出: Writer, OutputStream 类型的子类
要格式化的输出用:PrintStream, PrintWriter;
要缓冲用:BufferedInputStream,BufferedOutputStream,( 字节流 ) BufferedReader, BufferedWriter( 字符流 )