0、
    由于计算机中的数据基本都保存在硬盘中,因此操作文件中的数据是一种很常见的操作。在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写。针对文件的读写,JDK 专门提供了两个类,分别是 FileInputStream 和 FileOutputStream。

    1、
    FileInputStream 是 InputStream 的子类,它是操作文件的字节输入流,专门用于读取文件中的数据。由于从文件读取数据是重复的操作,因此需要通过循环语句来实现数据的持续读取。

    接下来通过一个案例来实现字节流对文件数据的读取。首先在 Eclipse 项目的根目录下创建一个文本文件 test.txt,在文件中输入内容“itcast”并保存。然后创建一个读取文本的类,具体代码如下所示。

    1. import java.io.FileInputStream;
    2. public class example01 {
    3. public static void main(String[] args) throws Exception{
    4. //创建一个文件字节输入流
    5. FileInputStream in = new FileInputStream("text.txt");
    6. //定义一个 int 类型变量 b,记住每次读取的一个字节
    7. int b = 0;
    8. while (true) {
    9. b = in.read(); //变量 b 记住读取的一个字节
    10. if (b == -1) { //如果读取的字节为 -1,说明读取到了文本末尾,跳出 while 循环
    11. break;
    12. }
    13. System.out.println(b);
    14. }
    15. in.close();
    16. }
    17. }
    18. console:
    19. 105
    20. 116
    21. 99
    22. 97
    23. 115
    24. 116

    代码块中创建的字节流 FileInputStream 通过 read()方法将当前项目中的文件“test.txt”中的数据读取并打印。通常情况下读取文件应该输出字符,这里之所以输出数字是因为硬盘上的文件是以字节的形式存在的。在“test.txt”文件中,字符‘i’’、‘t’、‘c’、‘a’、‘s’、‘t’各占一个字节,因此,最终结果现实的就是文件“test.txt”中的六个字节所对应的十进制数。需要注意的是,在读取文件数据时,必须保证文件在相应目录存在并且是可读的,否则会出现文件找不到的异常 FileNotFoundException。

    2、
    与 FileInputStream 相对应的是 FileOutputStream。FileOutputStream 是 OutputStream 的子类,它是操作文件的字节输入流,专门用于把数据写入文件。接下来通过一个案例演示如何将数据写入文件,如下所示。

    1. import java.io.FileOutputStream;
    2. public class example02 {
    3. public static void main(String[] args) throws Exception{
    4. //创建一个文件输出流
    5. FileOutputStream out = new FileOutputStream("example.txt");
    6. String string = "传智播客";
    7. byte[] b = string.getBytes(); //getBytes()方法可以将字符串转化成字节数组 byte[]
    8. for (int i = 0; i < b.length; i++) {
    9. out.write(b[i]);
    10. }
    11. out.close();
    12. }
    13. }

    程序运行后,会在当前根目录下生成一个新的文本文件 example.txt(运行程序后,该文件可能不会立刻显示在项目目录下,强制刷新即可),打开此文件,可以看到如下内容。
    QQ截图20200606102246.png

    2.1、
    从运行结果可以看出,通过 FileOutputStream 写数据时,自动创建了文件 example.txt,并将数据写入文件。需要注意的是,如果是通过 FileOutputStream 向一个已经存在的文件中写入数据,那么该文件中的数据首先会被清空,再写入新的数据。若希望在已存在的文件内容之后追加新内容,则可使用 FileOutputStream 的构造函数 FileOutputStream(String fileName, boolean append)来创建文件输出流对象,并把 append 参数的值设置为 true。接下来通过一个案例来如何将数据追加到文件末尾,如下所示。

    1. import java.io.*;
    2. public class example03 {
    3. public static void main(String[] args) throws Exception{
    4. OutputStream out = new FileOutputStream("example.txt",true); //这里使用到了面对对象的多态特性
    5. String string = "欢迎你";
    6. byte[] b = string.getBytes();
    7. for (int i = 0; i < b.length; i++) {
    8. out.write(b[i]);
    9. }
    10. out.close();
    11. }
    12. }

    程序运行后,查看项目当前目录下的文件“example.txt”,如下所示。
    QQ截图20200606103542.png
    从上图可以看出,程序同故宫字节输出流对象向文件“example.txt”写入“欢迎你”后,并没有将文件之前的数据清空,而是将新写入的数据追加到了文件的末尾。

    3、
    由于 IO 流在进行读写操作时会出现异常,在上面的程序中使用了 throws 关键字将异常抛出。然而一旦遇到 IO 异常,IO 流的 close()方法将无法得到执行,通常将关闭流的操作写在 finally 代码块中,接下来演示使用 try catch 方法抛出异常,如下所示。

    1. import java.io.*;
    2. public class example03.1 {
    3. public static void main(String[] args) {
    4. OutputStream out = null;
    5. try {
    6. out = new FileOutputStream("example.txt", true);
    7. String string = "欢迎你";
    8. byte[] b = string.getBytes();
    9. for (int i = 0; i < b.length; i++) {
    10. out.write(b[i]);
    11. }
    12. } catch (Exception e) {
    13. // TODO: handle exception
    14. e.printStackTrace();
    15. } finally { //将 close()方法写在 finally 中,使用 try catch 抛出异常,执行 close()方法
    16. try {
    17. out.close();
    18. } catch (IOException e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }
    23. }