整理 Java I/O (二):针对文件的输入/输出流 - FileInput/OutputStream、FileReader/Writer

有时候我们需要从一个文件中读取数据,有可能是一张图片、一个文本或者一个媒体文件。这个时候就需要用到文件输入/输出流了。

Java提供了以下几个针对文件的输入输出流

  • FileInputStream

    从系统文件中获取输入字节,用于读取诸如图像数据之类的原始字节流。
  • FileOutputStream

    将数据写入File或者FileDescriptor中使用的流,用于写入诸如图像数据之类的原始字节的流。
  • FileReader

    用来读取字符文件的便捷类,用于读取字符流。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
  • FileWriter

    用来写入字符文件的便捷类,用于写入字符流。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。

FileInputStream

构造方法

  • FileInputStream(File file)

    通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
  • FileInputStream(FileDescriptor fdObj)

    通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
  • FileInputStream(String name)

    通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

其他方法

  • available()

    返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
  • close()

    关闭此文件输入流并释放与此流有关的所有系统资源。
  • getChannel()

    返回与此文件输入流有关的唯一 FileChannel 对象。
  • getFD()

    返回表示到文件系统中实际文件的连接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。
  • read()

    从此输入流中读取一个数据字节。
  • read(byte[] b)

    从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
  • read(byte[] b, int off, int len)

    从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
  • skip(long n)

    从输入流中跳过并丢弃 n 个字节的数据。

FileOutputStream

构造方法

  • FileOutputStream(File file)

    创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
  • FileOutputStream(File file, boolean append)

    创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
  • FileOutputStream(FileDescriptor fdObj)

    创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
  • FileOutputStream(String name)

    创建一个向具有指定名称的文件中写入数据的输出文件流。
  • FileOutputStream(String name, boolean append)

    创建一个向具有指定 name 的文件中写入数据的输出文件流。

其他方法

  • close()

    关闭此文件输出流并释放与此流有关的所有系统资源。
  • getChannel()

    返回与此文件输出流有关的唯一 FileChannel 对象。
  • getFD()

    返回与此流有关的文件描述符。
  • write(byte[] b)

    将 b.length 个字节从指定 byte 数组写入此文件输出流中。
  • write(byte[] b, int off, int len)

    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
  • write(int b)

    将指定字节写入此文件输出流。

FileReader

构造方法

  • FileReader(File file)

    在给定从中读取数据的 File 的情况下创建一个新 FileReader。
  • FileReader(FileDescriptor fd)

    在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。
  • FileReader(String fileName)

    在给定从中读取数据的文件名的情况下创建一个新 FileReader。

FileWriter

构造方法

  • FileWriter(File file)

    根据给定的 File 对象构造一个 FileWriter 对象。
  • FileWriter(File file, boolean append)

    根据给定的 File 对象构造一个 FileWriter 对象。
  • FileWriter(FileDescriptor fd)

    构造与某个文件描述符相关联的 FileWriter 对象。
  • FileWriter(String fileName)

    根据给定的文件名构造一个 FileWriter 对象。
  • FileWriter(String fileName, boolean append)

    根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

因为FileOutputStream并没有重写父类的flush方法,所以在FileOutputStream中,flush方法并没有执行任何操作,所以可以不必调用。

FileInputStream/FileOutputStream复制图片视频

/**
 * 字节输入输出流
 * 
 * @author 
 *
 */
public class CopyFile {
    private FileOutputStream fos;
    private FileInputStream fis;

    public static void main(String[] args) {
        CopyFile copyFile = new CopyFile();
        copyFile.copyCompleteFile(new File("D:\\李宗盛 - 给自己的歌.mp3"), new File(
                "D:\\完整复制.mp3"));
        copyFile.copyFragmentFile(new File("D:\\李宗盛 - 给自己的歌.mp3"), new File(
                "D:\\片段复制.mp3"));
    }

    private void copyCompleteFile(File file, File newFile) {
        try {
            fis = new FileInputStream(file);
            fos = new FileOutputStream(newFile);

            if (fis.markSupported()) {
                System.out.println("FileInputStream 支持mark、reset方法");
            } else {
                System.out.println("FileInputStream 不支持mark、reset方法");
            }

            long time = System.currentTimeMillis();
            // 一个字节一个字节的复制
            int i = 0;
            while ((i = fis.read()) != -1) {
                fos.write(i);
                fos.flush();
            }
            System.out.println("复制完成,共耗时: "
                    + (System.currentTimeMillis() - time) + " 毫秒。");

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private void copyFragmentFile(File file, File newFile) {
        // 将字节读取到数组中,然后输出
        try {
            fis = new FileInputStream(file);
            fos = new FileOutputStream(newFile);

            int length = 0;
            byte[] arr = new byte[1024];
            long time = System.currentTimeMillis();
            while ((length = fis.read(arr)) != -1) {
                if (fis.available() > 400000) {
                    fis.skip(length);
                    continue;
                }
                fos.write(arr, 0, length);
                fos.flush();
            }
            System.out.println("复制完成,共耗时: "
                    + (System.currentTimeMillis() - time) + " 毫秒。");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

运行这段代码会复制两个文件,一个是完整的歌曲,另外一个就是歌曲片段...

FileReader/FileWriter复制文本文件

public class CopyFile {

    private FileWriter writer;
    private FileReader reader;

    public static void main(String[] args) {
        CopyFile copyFile = new CopyFile();
        copyFile.writeFile(new File("D:\\text.txt"));
        copyFile.readFile(new File("D:\\text.txt"));
    }

    private void readFile(File file) {
        try {
            reader = new FileReader(file);
            if (reader.markSupported()) {
                System.out.println("FileReader 支持mark、reset方法");
            } else {
                System.out.println("FileReader 不支持mark、reset方法");
            }

            System.out.print((char) reader.read()); // 输出a

            reader.skip(4); // 跳过bcde四个字符

            int length = 0;
            char[] arr = new char[2];
            while ((length = reader.read(arr)) != -1) {
                System.out.print(new String(arr, 0, length)); // 输出fghijklmnopqrs
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private void writeFile(File file) {
        try {
            String string = "abcde";
            writer = new FileWriter(file);
            writer.write(string.toCharArray());
            writer.write(102);
            writer.write("ghijk");
            writer.write("lmnop", 0, 3);
            writer.write("lmnopqrst", 3, 5);
            writer.append('t');
            writer.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}