在解释Java中FileInputStream和FileReader的具体区别之前,我想讲述一下Java中InputStream和Reader的根本差异,以及分别什么时候使用InputStream和Reader。实际上, InputStream和Reader都是抽象类,并不直接地从文件或者套接字(socket)中读取数据。然而,它们之间的主要差别在于:InputStream用于读取二进制数据(字节流方式,译者注),Reader用于读取文本数据(字符流方式,译者注),准确地说,Unicode字符。那么,二进制数据和文本数据的区别是什么呢?当然,所有读取的东西本质上是字节,然后需要一套字符编码方案,把字节转换成文本。Reader类使用字符编码来解码字节,并返回字符给调用者。Reader类要么使用运行Java程序平台的默认字符编码,要么使用Charset对象或者String类型的字符编码名称,如“UTF-8”。尽管它是一个最简单的概念,当读取文本文件或从套接字中读取文本数据时,很多Java开发者会因没有指定字符编码而犯错。记住,如果你没有指定正确的编码,或者你的程序没有使用的协议中已存在的字符编码,如HTML的 “Content-Type(内容类型)”、XML文件头指定的编码,你可能无法正确地读取的所有数据。一些不是默认编码呈现的字符,可能变成“?”或小方格。一旦你知道stream和reader之间的根本区别,理解FileInputStream和FileReader之间的差异就很容易了。既可以让你从文件中读取数据,然而FileInputStream用于读取二进制数据,FileReader用来读取字符数据。

Java中FileReader vs FileInputStream

由于FileReader类继承了InputStreamReader类,使用的字符编码,要么由类提供,要么是平台默认的字符编码。请记住,InputStreamReader会缓存的字符编码。创建对象后,设置字符编码将不会有任何影响。让我们来看看如何使用Java中InputStream和FileReader的例子。你可以提供任何一个文件对象或一个包含文件位置的字符串,以开始读取文件的字符数据。这类似于FileInputStream,也提供了类似的用于读取文件源的构造函数。尽管建议使用BufferedReader来读取文件数据。我把我的eclipse的file.encoding设置成了UTF-8,然后再c盘新建一个data.txt并且输入一个永字,用记事本打开另存为UTF-8编码。这个时候我们在eclipse中运行程序,可以看到data.txt的打印二进制内容是efbbbfe6b0b8(通过Notepad++的HEX-Editor插件查看data.txt文件十六进制内容可以验证这一点),说明FileInputStream没有进行任何编码转换把data.txt的二进制内容读入java变量中。我们再来看下面一行输出  feff6c38永  就会发现FileReader通过UTF-8读取文件,然后对文件进行了编码,使其转换成unicode编码存入java变量中,这样才能在java中正确使用,因为java存储在内存里的变量都是unicode编码。如果我们把data.txt另存为ANSI(GBK)编码,FileReader还是通过UTF-8读取文件,然后对文件进行了unicode编码就会出现乱码问题。如果把eclipse的file.encoding设置成了GBK再运行程序就会打印正常,如下

d3c0
6c38永

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
 
/**
 * Java程序通过字节流和字符流的方式来读取文件数据。
 * 需强调FileInputStream和FileReader的关键区别在于:FileReader用于读取字符流,而FileInputStream用来读取原始字节流。
 * @author Javin Paul
 */
public class HowToReadFileInJava {
    public static void main(String args[]) {
 
        // 例1 – 使用FileInputStream 读取文件内容
        try (FileInputStream fis = new FileInputStream("c:/data.txt")) {
            int data = fis.read();
            while (data != -1) {
                System.out.print(Integer.toHexString(data));
                data = fis.read();
            }
        } catch (IOException e) {
            System.out.println("Failed to read binary data from File");
            e.printStackTrace();
        }
 
            System.out.println();
        // 例2 – Java中使用FileReader 读取文件数据
        try (FileReader reader = new FileReader("c:/data.txt")) {
            int character = reader.read();
            while (character != -1) {
                        System.out.print(Integer.toHexString(character));
                System.out.print((char) character);
                character = reader.read();
            }
        } catch (IOException io) {
            System.out.println("Failed to read character data from File");
            io.printStackTrace();
        }
    }
}

另存为UTF-8输出:

1
2
3
4
5

UTF-8
efbbbfe6b0b8
feff6c38永

另存为ANSI(GBK)输出:

 
1
2
3
4
5

UTF-8
d3c0
fffd�fffd�

第1个例子是按字节从文件中读取数据,因此势必会非常慢。FileInputStream的read() 方法是阻塞式的,读取字节或数据块,直到无数据输入。它要么返回数据的下一个字节,当到达文件末尾时,返回-1。这意味着,我们每循环读取一个字节,将其打印为十六进制字符串。顺便说一句,将InputStream转换成字节数组是可选的。另一方面,例2是按字符读取数据。继承自FileReader的InputStreamReader 的read() 方法读取单个字符,并返回该字符,当到达流末尾时,返回-1。这就是为什么你看到例2输出的文字跟文件中的完全一样。

这就是所有关于Java中FileInputStream和FileReader之间的区别。归根结底:使用FileReader或BufferedReader从文件中读取字符或文本数据,并总是指定字符编码;使用FileInputStream从Java中文件或套接字中读取原始字节流。

Java FileInputStream与FileReader的区别的更多相关文章

  1. [转]Java FileInputStream与FileReader的区别

    在解释Java中FileInputStream和FileReader的具体区别之前,我想讲述一下Java中InputStream和Reader的根本差异,以及分别什么时候使用InputStream和R ...

  2. InputStream和Reader,FileInputStream和 FileReader的区别

    一.InputStream和Reader的区别 InputStream和Reader都可以用来读数据(从文件中读取数据或从Socket中读取数据),最主要的区别如下: InputStream用来读取二 ...

  3. java中OutputStream字节流与字符流InputStreamReader 每一种基本IO流BufferedOutputStream,FileInputStream,FileOutputStream,BufferedInputStream,BufferedReader,BufferedWriter,FileInputStream,FileReader,FileWriter,InputStr

    BufferedOutputStream,FileInputStream,FileOutputStream,BufferedInputStream,BufferedReader,BufferedWri ...

  4. java 接口和抽象类的区别

    java 接口和抽象类的区别抽象类:1.含有抽象方法的类一定为抽象类,反过来抽象类,不一定含有抽象方法:2.抽象类必须用abstract来进行定义,抽象方法也必须用abstract来进行定义:3.抽象 ...

  5. JDK与Java SE/EE/ME的区别

    1. Java SE(Java Platform,Standard Edition). Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 Java 应用 ...

  6. java 静态方法和实例方法的区别

    转自 java 静态方法和实例方法的区别 静态方法和实例方法的区别主要体现在两个方面:   在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法 ...

  7. java中ArrayList 、LinkList区别

    转自:http://blog.csdn.net/wuchuanpingstone/article/details/6678653 个人建议:以下这篇文章,是从例子说明的方式,解释ArrayList.L ...

  8. java抽象类与接口的区别及用法

    java抽象类与接口的区别及用法 一.抽象类里面的方法可以有实现,但是接口里面的方法确是只能声明. 二.接口是设计的结果 :抽象类是重构的结果 . 三.java不支持多重继承,所以继承抽象类只能继承一 ...

  9. 【转】java int与integer的区别

    java int与integer的区别 int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象 1 ...

随机推荐

  1. 第一章 走进Java(待续)

    ·········

  2. 基于JNI,JAVA 调用 C++入门

    1.步骤一览 2.步骤详情 2.1. 编写Java类 native package com.ibugs.jni; /** * * @author i_bugs * */ public class CP ...

  3. Mycat实战之离散分片

    1 枚举分片(customer表) #### 1.1 修改配置信息加载配置文件 datanode hash-int vi partition-hash-int.txt db1=0 db2=1 [roo ...

  4. Gym 101606 F-Flipping Coins(概率dp)

    参考博客:http://www.cnblogs.com/kang000/p/8571071.html  (这篇博客写的真的走心,ORZ) 题意有n个硬币排成一排,开始的时候所有的硬币都是正面朝下,你必 ...

  5. mfs监控

    web gui 监控 gui_info.jpg (143.72 KB, 下载次数: 83) gui_most.jpg (209.36 KB, 下载次数: 82) gui_master_info.jpg ...

  6. DataTable 常用操作

    //定义表结构 DataTable dt = new DataTable(); dt.Columns.Add("FactoryId"); 或dt.Columns.Add(new D ...

  7. Win10 Tensorflow 配置Mask_RCNN

    1.安装Anaconda3 下载地址  Anaconda 官网下载地址:https://www.continuum.io/downloads 下载以后,点击exe程序,开始安装,详细的安装过程(图片参 ...

  8. SQL Server CLR全功略之一---CLR介绍和配置

    Microsoft SQL Server 现在具备与 Microsoft Windows .NET Framework 的公共语言运行时 (CLR) 组件集成的功能.CLR 为托管代码提供服务,例如跨 ...

  9. laravel实现多对多的分析

    在实际开发中多对多的开发还是比较常见的 1.1首先由migrate来创建表(文章表) 1.2同理创建标签表 1.3这是 我会的到如下结果: 2.1在数据迁移表contents中添加几个字段 publi ...

  10. web大文件上传控件-设置附加参数-Xproer.HttpUploader6

    自定义附加字段在up6.js中定义,也可以不用定义: 注意: 1.附加字段必须是字符串类型. 2.如果附加字段的值包含中文,在上传前必须使用encodeURIComponent进行编码.     在引 ...