橘子味的心
标题:Java文件和输入和输出(I/O)

java.io包几乎包含了在Java中执行输入和输出(I/O)所需的所有类。 所有这些流代表输入源和输出目的地。 java.io包中的流支持许多数据,如:原始,对象,本地化字符等。

1. 流(Streams)

流(Streams)可以定义为数据序列,它有两种 -

  • InPutStream - 它用于从源读取数据。
  • OutPutStream - 它用于将数据写入目标。

Java为与文件和网络相关的I/O提供强大而灵活的支持,但本教程只涵盖了流和I/O相关的非常基本的功能。下面将看到一些最常用的例子 -

1.1. 字节流
Java字节流用于执行8位字节的输入和输出。尽管有许多与字节流相关的类,但最常用的类是FileInputStreamFileOutputStream。以下示例使用这两个类将输入文件的内容复制到输出文件中 -

  1. import java.io.*;
  2. public class CopyFile {
  3.  
  4. public static void main(String args[]) throws IOException {
  5. FileInputStream in = null;
  6. FileOutputStream out = null;
  7.  
  8. try {
  9. in = new FileInputStream("D:\\input.txt");
  10. out = new FileOutputStream("D:\\output.txt");
  11. int c;
  12. while ((c = in.read()) != -1) {
  13. out.write(c);
  14. }
  15. }finally {
  16. if (in != null) {
  17. in.close();
  18. }
  19. if (out != null) {
  20. out.close();
  21. }
  22. }
  23. }
  24. }
  25. Java

假设在D盘下有一个文件:input.txt,它的内容如下 -

  1. This is test for copy file.
  2. power by yiibai.com
  3. Txt

下一步,编译上面的程序并执行它,它将创建一个:D:/output.txt文件,内容与D:/input.txt中的相同。

1.2. 字符流

Java字节流用于执行8位字节的输入和输出,而Java字符流用于执行16位unicode的输入和输出。 尽管有许多与字符流相关的类,但最常用的类是FileReaderFileWriter。 虽然FileReader内部使用FileInputStream类,而FileWriter内部使用FileOutputStream类,但主要区别在于FileReader一次读取两个字节,而FileWriter一次写入两个字节。

可以重新编写上面的例子,它使用这两个类将输入文件(具有unicode字符)复制到输出文件中 -

  1. import java.io.*;
  2. public class CopyFile {
  3.  
  4. public static void main(String args[]) throws IOException {
  5. FileReader in = null;
  6. FileWriter out = null;
  7.  
  8. try {
  9. in = new FileReader("D:/input.txt");
  10. out = new FileWriter("D:/output.txt");
  11.  
  12. int c;
  13. while ((c = in.read()) != -1) {
  14. out.write(c);
  15. }
  16. }finally {
  17. if (in != null) {
  18. in.close();
  19. }
  20. if (out != null) {
  21. out.close();
  22. }
  23. }
  24. }
  25. }
  26. Java

假设在D盘下有一个文件:input.txt,它的内容如下 -

  1. This is test for copy file.
  2. power by yiibai.com
  3. Txt

下一步,编译上面的程序并执行它,它将创建一个:D:/output.txt文件,内容与D:/input.txt中的相同。

2. 标准流

所有编程语言都支持标准I/O,用户的程序可以从键盘输入,然后在计算机屏幕上产生输出。 如果您了解C或C++编程语言,那么应该了解三个标准流:STDINSTDOUTSTDERR。 同样,Java提供以下三个标准流 -

  • 标准输入 - 用于将数据提供给用户程序,通常键盘用作标准输入流并表示为System.in
  • 标准输出 - 用于输出用户程序生成的数据,通常计算机屏幕用于标准输出流并表示为System.out
  • 标准错误 - 用于输出用户程序生成的错误数据,通常计算机屏幕用于标准错误流并表示为System.err

以下是一个简单的程序,它使用InputStreamReader来读取标准输入流,直到用户键入:q -

  1. import java.io.*;
  2. public class ReadConsole {
  3.  
  4. public static void main(String args[]) throws IOException {
  5. InputStreamReader cin = null;
  6.  
  7. try {
  8. cin = new InputStreamReader(System.in);
  9. System.out.println("Enter characters, 'q' to quit>");
  10. char c;
  11. do {
  12. c = (char) cin.read();
  13. System.out.print(c);
  14. } while(c != 'q');
  15. }finally {
  16. if (cin != null) {
  17. cin.close();
  18. }
  19. }
  20. }
  21. }
  22. Java

将上面的代码保存在ReadConsole.java文件中,并尝试编译并执行它,如下面的程序所示。 程序继续读取并输出用户输入的字符,直到按q退出 -

  1. $javac ReadConsole.java
  2. $java ReadConsole
  3. Enter characters, 'q' to quit>
  4. 1
  5. 1
  6. a
  7. a
  8. C
  9. C
  10. Java

3. 读写文件

如前所述,流可以定义为数据序列。 InputStream用于从源读取数据,OutputStream用于将数据写入目标。

以下是处理输入和输出流的类层次结构。

两个重要的流是:FileInputStreamFileOutputStream,将在本教程中讨论。

3.1. FileInputStream

此流用于从文件中读取数据。 可以使用关键字new创建对象,并且有几种类型的构造函数可用。

以下构造函数将文件名作为字符串来创建输入流对象以读取文件 -

  1. InputStream f = new FileInputStream("D:/java/hello.txt");
  2. Java

以下构造函数采用文件对象来创建输入流对象以读取文件。 首先,使用File()方法创建一个文件对象,如下所示 -

  1. File f = new File("D:/java/hello.txt");
  2. InputStream f = new FileInputStream(f);
  3. Java

当创建了InputStream对象,就可以使用一些辅助方法来读取流或在流上执行其他操作。

编号 方法 描述
1 public void close() throws IOException{} 此方法关闭文件输出流。 释放与该文件关联的所有系统资源,抛出IOException
2 protected void finalize()throws IOException {} 此方法清除与文件的连接。 确保在没有对此流的引用时调用此文件输出流的close()方法,抛出IOException
3 public int read(int r)throws IOException{} 此方法从InputStream读取指定的数据字节,并返回一个int值。 返回数据的下一个字节,如果它是文件的末尾,则返回-1
4 public int read(byte[] r) throws IOException{} 此方法将输入流中的r.length个字节读入数组。返回读取的总字节数。 如果它到达文件的结尾,则返回-1
5 public int available() throws IOException{} 给出可以从此文件输入流中读取的字节数。 返回一个int值。

还有其他重要的输入流可用,有关更多详细信息,请参阅以下链接 -

3.2. FileOutputStream

FileOutputStream用于创建文件并将数据写入文件。 如果文件尚不存在,则会在打开文件以进行输出之前创建该文件。

这里有两个构造函数,可用于创建FileOutputStream对象。

以下构造函数将文件名作为字符串来创建输入流对象以写入文件 -

  1. OutputStream f = new FileOutputStream("D:/java/hello.txt")
  2. Java

下面的构造函数接受一个文件对象来创建一个输出流对象来写入该文件。 首先,使用File()方法创建一个文件对象,如下所示 -

  1. File f = new File("D:/java/hello.txt");
  2. OutputStream f = new FileOutputStream(f);
  3. Java

当创建了OutputStream对象,就使用它的一些辅助方法来写入流或在流上执行其他操作。

编号 方法 描述
1 public void close() throws IOException{} 此方法关闭文件输出流,释放与该文件关联的所有系统资源。抛出IOException
2 protected void finalize()throws IOException {} 此方法清除与文件的连接,确保在没有对此流的引用时调用此文件输出流的close()方法。抛出IOException
3 public void write(int w)throws IOException{} 此方法将指定的字节写入输出流。
4 public void write(byte[] w) 将长度为w.length的字节从字节数组写入OutputStream

还有其他重要的输出流,有关更多详细信息,请参阅以下链接 -

示例

以下是演示如何使用InputStreamOutputStream类对象的示例 -

  1. import java.io.*;
  2. public class fileStreamTest {
  3.  
  4. public static void main(String args[]) {
  5.  
  6. try {
  7. byte bWrite [] = {11,21,3,40,5};
  8. OutputStream os = new FileOutputStream("D:/test.txt");
  9. for(int x = 0; x < bWrite.length ; x++) {
  10. os.write( bWrite[x] ); // writes the bytes
  11. }
  12. os.close();
  13.  
  14. InputStream is = new FileInputStream("D:/test.txt");
  15. int size = is.available();
  16.  
  17. for(int i = 0; i < size; i++) {
  18. System.out.print((char)is.read() + " ");
  19. }
  20. is.close();
  21. } catch (IOException e) {
  22. System.out.print("Exception");
  23. }
  24. }
  25. }
  26. Java

上面的代码将创建文件test.txt并将以二进制格式写入给定的数字数据,同样也会在屏幕上输出。

4. 文件导航和I/O

可通过其他几个类来了解文件导航和I/O的基础知识。如下 -

4.1. 目录操作

目录是一个文件,它可以包含其他文件和目录的列表。 使用File对象创建目录,列出目录中可用的文件。 有关完整的详细信息,请查看在File对象上调用的所有方法的列表以及与目录相关的内容。

4.1.1. 创建目录

有两种File类的方法,可用于创建目录 -

  • mkdir()方法创建一个目录,创建成功时返回true,失败时返回false。 失败表示File对象中指定的路径已存在,或者由于整个路径尚不存在或权限问题而无法创建目录。
  • mkdirs()方法创建目录和目录的所有上级目录。

以下示例创建一个目录:D:/tmp/user/java/bin -

示例

  1. import java.io.File;
  2. public class CreateDir {
  3.  
  4. public static void main(String args[]) {
  5. String dirname = "D:/tmp/user/java/bin";
  6. File d = new File(dirname);
  7.  
  8. // 创建目录及父级目录
  9. d.mkdirs();
  10. }
  11. }
  12. Java

编译并执行上面的代码来创建目录:D:/tmp/user/java/bin

注 - Java会根据约定自动处理UNIX和Windows上的路径分隔符。如果在Windows版本的Java上使用正斜杠(/),则路径仍将正确解析。

4.1.2. 列出目录

可以使用File对象的list()方法列出目录中可用的所有文件和目录,如下所示 -

  1. import java.io.File;
  2. public class ReadDir {
  3.  
  4. public static void main(String[] args) {
  5. File file = null;
  6. String[] paths;
  7.  
  8. try {
  9. // 创建一个File对象
  10. file = new File("D:/software");
  11.  
  12. // 文件和目录的数组
  13. paths = file.list();
  14.  
  15. // 对于路径数组中的名称
  16. for(String path:paths) {
  17. // 打印文件名和目录名
  18. System.out.println(path);
  19. }
  20. } catch (Exception e) {
  21. // if any error occurs
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. Java

执行上面代码,它将根据D:/software目录中目录和文件产生以下结果 -

  1. apache-maven-3.5.4
  2. apache-tomcat-9.0.14
  3. Aptana_Studio
  4. eclipse
  5. EditPlusPortable
  6. javajars
  7. kafka_2.11-2.0.0
  8. mysql-5.7.23-winx64
  9. Navicat Premium 11
  10. php-cs-fixer.phar
  11. spring-2.0.5.RELEASE
  12. ... ...
  13. Shell