使用FileInputStream读取本地文件
4854字,阅读需时17分钟

前面了解了流的概念。本节探讨如何通过FileInputStream读取本地文件。本地文件是指存储在本地磁盘中的文件,我们存储到电脑中的图片、视频、音乐、文档资料都属于本地文件。

这些本地文件都可以用相对应的程序打开。图片可以用Windows自带的照片查看器或画图程序打开查看;音乐和视频可以用Windows自带的Media Player或暴风影音等播放器打开;文档资料可以用办公软件Word等程序打开编辑。这些程序在开发过程中,都需要使用编程语言提供的文件读写技术。

在介绍文件读写技术之前,有必要先了解一下二进制文件和文本文件。二进制文件和文本文件在物理存储上并没有什么区别,存储在硬盘上的文件都是以二进制方式存储的。二者的区别在于解释数据的逻辑不同。程序读取文本文件时,可以以字符方式读取,也可以以字节方式读取,将读取的数据解释为ASCII或unicode编码,也就是解释为字符,读取的字符可以直接输出到屏幕上显示出来;当程序读取二进制文件时,是以字节方式读取的,对读取数据的解释由读取程序决定。如读取图片文件时,读取图片的程序需要了解该文件的结构,并解释读取的数据,如果不了解该图片文件的结构,读取图片文件就会失败,也就无法把图片显示出来了。

从前面的讨论可知,Java提供的FileInputStream类适合于读取二进制文件,而不太适合读取文本文件。当然也可以读取文本文件,不过需要做相应地读取处理,否则遇到中文就会出现乱码。

用FileInputStream读取文件流程如下:

image.png       

图1 用FileInputStream读取文件过程

 

用FileInputStream读取文件时,可以先用File类打开本地文件,然后实例化FileInputStream对象时,传入已打开文件的File对象,就可以调用FileInputStream的read方法从文件读取数据了。

FileInputStream也提供了另外一种构造方法,该构造方法直接传入文件的存储路径,而无需实例化File对象。该构造方法把实例化File对象的语句放到了构造方法里面。

例1:使用FileInputStream的read()方法读取文本文件。

public class FileInputStrameDemo {
public static void main(String[] args) {
    // TODO Auto-generated method stub
    //实例化File对象,准备读取read.txt文件
    File  file = new File("d:\\read.txt");
    try {
        //实例化FileInputStream
        //FileInputStream构造方法要求传入File对象
        FileInputStream fis = new FileInputStream(file);
        int  b;
        try {
            while( (b = fis.read()) != -1 )
            {
                System.out.print((char)b);
            }
             fis.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }  
}
 
}

例子程序用FileInputStream读取文本文件,被读取的文本文件存储在D盘根目录下,文件名称为read.txt。使用FileInputStream读取文件数据之前,需要先实例化File对象,File类的构造方法要求传入被读取的文件路径。然后,实例化FileInputStream对象,并通过FileInputStream类的构造方法传入已实例化的File对象。因为FileInputStream在实例化过程中可能会抛出异常,因此需要用try-catch语句捕获异常。

FileInputStream类提供了多种读取文件的方法,例子程序使用了read()方法,该方法用于从输入流中读取数据的下一个字节,并返回读到的字节值,若遇到流的末尾,返回-1。程序通过while循环读取文件的所有数据,每读取一个字节就输出到控制台,输出之前需要做类型转换,将整型转换为字符输出。程序输出结果如下图所示:

image.png

图 2 例1示例程序程序输出结果

 

例子程序的read()方法只能一个字节一个字节地读取。FileInputStream类还提供了read(byte[] b) 方法读取文件数据,该方法用于从输入流中读取b.length个字节的数据,并将数据存储到缓冲区数组b中,返回的是实际读到的字节数。

例2:使用FileInputStream的read(byte[] b)方法读取文本文件。

package com.milihua.fileinputdemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamDemo2 {
 
public static void main(String[] args) {
    // TODO Auto-generated method stub
    // TODO Auto-generated method stub
    //实例化File对象,准备读取read.txt文件
    File  file = new File("d:\\read.txt");
    try {
        //实例化FileInputStream
        //FileInputStream构造方法要求传入File对象
        FileInputStream fis = new FileInputStream(file);
        try {
            //创建了一个和文件大小一样的缓冲区,刚刚好 
         byte[] buf = new byte[fis.available()]; 
         fis.read(buf);
 fis.close();
         System.out.println(new String(buf)); 
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
       
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }  
}
}

 FileInputStream类提供了一个available()方法,该方法在读取本地文件时,返回文件的总字节数。程序声明了一个byte数组,并通过new关键字分配与被读取文件大小相同的空间,然后调用read(byte[] b)方法一次性读取文件全部数据。

显示中文乱码的问题

如果文本文件含有中文字符,建议使用read(byte[] b)方法读取整个文本文件,并将读取文件后的byte数组转换为字符串类型,这样做的好处是不会出现乱码。

修改read.txt文件,加入英文诗句的中文翻译,用例1程序读取文件,输出结果如下图所示:

image.png

图 3 例1读取含中文内容的文件输出结果

 

从输出结果可以看出,英文诗句下面的中文翻译显示为乱码。原因是FileInputStream类read()方法每次读取文件都是按照1个字节读取的,而中文字符都是用两个字节表示的,输出时自然就乱码了。

另外,在Java语言中,中文和英文字符默认都被处理为unicode编码,unicode编码都是用两个字节表示一个字符,既然中文和英文都是用2个字节表示一个字符,为什么英文字符输出没有问题呢?原因是在unicode编码中,英文字符依然是ASCII编码,多出的一个字节值为0没有用到。

使用例2程序读取read.txt文件,程序输出结果如下图所示:

image.png

图 4 例2读取含中文内容的文件输出结果

从图中可以看出,使用read(byte[] b)方法可以正确读取含中文内容的文本文件。

文章小结

FileInputStream一般用来读取二进制文件,如果要读取文本文件,建议使用FileInputStream的read(byte[] b)方法读取整个文本文件,并将读取文件后的byte数组转换为字符串类型。用循环语句读取文件时,必须设定中止循环条件,一般以读取到文件尾部为中止条件。

我要评论
全部评论
郎宏林
授课老师
授课老师简介
项目经理,系统分析和架构师,从事多年中文信息处理技术。熟悉项目管理、擅长项目需求分析和设计、精通Java、C#、Python等编程语言。
下载APP

手机、电脑同步学

用微信或手机浏览器扫描二维码,即可下载APP。

  • 备案号:鲁ICP备15001146号
  • @1997-2018 潍坊米粒花网络技术有限公司版权所有