【正确答案】在介绍这两个流的区别之前,首先介绍InputStream和Reader的区别。
InputStream和Reader都可以用来读数据(从文件中读取数据或从Socket中读取数据),最主要的区别如下:InputStream用来读取二进制数(字节流),而Reader用来读取文本数据,即Unicode字符。那么二进制数与文本数据有什么区别呢?从本质上来讲,所有读取的内容都是字节,要想把字节转换为文本,需要指定一个编码方法。而Reader就可以把字节流进行编码从而转换为文本。当然,这个转换过程就涉及编码方式的问题,它默认采用系统默认的编码方式对字节流进行编码,也可以显式地指定一个编码方式,例如“UTF-8”。尽管这个概念非常简单,但是Java程序员经常会犯一些编码的错误,最常见的错误就是不指定编码方式。在读文件或从Socket读取数据的时候,如果没有指定正确的编码方式,读取到的数据可能就会有乱码,进而导致数据丢失。
FileInputStream和FileReader有着类似的区别,它们都用于从文件中读取数据,但是FilelnputStream用于从文件中读取二进制数据(字节流),而FileReader用于从文件中读取字符数据。FileReader继承自InputStreamReader,它要么使用系统默认的编码方式,要么使用InputStreamReader所使用的编码方式。需要注意的是,InputStreamReader缓存了字符编码,因此,在创建InputStreamReader对象以后,如果再对字符编码进行修改将没有任何作用。下面给出一个使用FileInputStream和FileReader的例子:
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
public class Test{
public static void mare(String args[])throws Exception{
//读取字节流
FiMnputStream fis=null;
try{
fis=new FilelnputStream("testInput.txt");
intdata=fis.read();
while(data!=-1){
System.out.print(Integer.toHexString(data));
data=fis.read();
}
}catch(IOException e){
e.printStackTrace();
}finally{
if(fis!=null)
try{
fis.close();
}catch(IOException e){
}
}
System.out.println();
//用FileReader读取字符
FileReader reader=null;
try{
reader=new FileReader("testInput.txt");
intcharacter=reader.read();
while(character!=-1){
System.out.print((char)character);
character=reader.read();
}
}catch(IOException io){
System.out.println("Failed to read character data from File");
io.printStackTrace();
}finally{
if(reader!=null)
try{
reader.close();
}catch(IOException e){
}
}
}
}
程序的运行结果为:
7465737420726561642066696c65
test readfile
从上面的代码可以看出,FileInputStream读取数据的方式是一个字节一个字节地读取,因此,读取速度会比较慢,同时,read方法是一个阻塞方法,它要么读取到一个字节,要么阻塞(等待可被读取的数据),这个方法的返回值为读取到的字节数,当读取到文件结尾的时候,会返回-1。在使用FilelnputStream的例子中,每个循环读取一个字节,然后转换为十六进制字符串输出。FileReader中的read方法每次读取一个字符,直到读取到文件结尾时,这个方法返回-1。
【答案解析】