Java - 文件和 I/O


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

溪流

流可以定义为数据序列。有两种流 -

  • InPutStream - 输入流用于从源读取数据。

  • OutPutStream - OutputStream 用于将数据写入目的地。

流

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

字节流

Java字节流用于执行8位字节的输入和输出。虽然与字节流相关的类有很多,但最常用的类是FileInputStreamFileOutputStream。以下是一个使用这两个类将输入文件复制到输出文件的示例 -

例子

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {

   public static void main(String args[]) throws IOException {  
      FileInputStream in = null;
      FileOutputStream out = null;

      try {
         in = new FileInputStream("input.txt");
         out = new FileOutputStream("output.txt");
         
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}

现在让我们有一个包含以下内容的文件input.txt -

This is test for copy file.

下一步,编译并执行上述程序,这将创建与 input.txt 内容相同的 output.txt 文件。因此,让我们将上述代码放入 CopyFile.java 文件中并执行以下操作 -

$javac CopyFile.java
$java CopyFile

字符流

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

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

例子

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyFile {

   public static void main(String args[]) throws IOException {
      FileReader in = null;
      FileWriter out = null;

      try {
         in = new FileReader("input.txt");
         out = new FileWriter("output.txt");
         
         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}

现在让我们有一个包含以下内容的文件input.txt -

This is test for copy file.

下一步,编译并执行上述程序,这将创建与 input.txt 内容相同的 output.txt 文件。因此,让我们将上述代码放入 CopyFile.java 文件中并执行以下操作 -

$javac CopyFile.java
$java CopyFile

标准流

所有编程语言都提供对标准 I/O 的支持,用户的程序可以从键盘获取输入,然后在计算机屏幕上产生输出。如果您了解 C 或 C++ 编程语言,那么您一定了解三种标准设备 STDIN、STDOUT 和 STDERR。同样,Java 提供了以下三个标准流 -

  • 标准输入- 用于将数据提供给用户的程序,通常使用键盘作为标准输入流并表示为System.in

  • 标准输出- 用于输出用户程序产生的数据,通常计算机屏幕用于标准输出流并表示为System.out

  • 标准错误- 用于输出用户程序产生的错误数据,通常计算机屏幕用于标准错误流并表示为System.err

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

例子

import java.io.InputStreamReader;

public class ReadConsole {

   public static void main(String args[]) throws IOException {
      InputStreamReader cin = null;

      try {
         cin = new InputStreamReader(System.in);
         System.out.println("Enter characters, 'q' to quit.");
         char c;
         do {
            c = (char) cin.read();
            System.out.print(c);
         } while(c != 'q');
      }finally {
         if (cin != null) {
            cin.close();
         }
      }
   }
}

让我们将上述代码保留在 ReadConsole.java 文件中,并尝试编译并执行它,如以下程序所示。该程序继续读取并输出相同的字符,直到我们按“q” -

$javac ReadConsole.java
$java ReadConsole
Enter characters, 'q' to quit.
1
1
e
e
q
q

读写文件

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

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

文件IO

两个重要的流是FileInputStreamFileOutputStream,本教程将对此进行讨论。

文件输入流

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

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

InputStream f = new FileInputStream("C:/java/hello");

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

File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);

一旦您掌握了InputStream对象,就会有一个帮助器方法列表,可用于读取流或在流上执行其他操作。

先生。 方法及说明
1

public void close() 抛出 IOException{}

该方法关闭文件输出流。释放与该文件关联的所有系统资源。抛出 IOException。

2

protected void Finalize() 抛出 IOException {}

此方法会清除与文件的连接。确保当不再有对此流的引用时,调用该文件输出流的 close 方法。抛出 IOException。

3

公共 int read(int r) 抛出 IOException{}

该方法从InputStream中读取指定字节的数据。返回一个 int。返回数据的下一个字节,如果是文件末尾,则返回-1。

4

public int read(byte[] r) 抛出 IOException{}

此方法将 r.length 字节从输入流读取到数组中。返回读取的总字节数。如果是文件末尾,则返回-1。

5

public int available() 抛出 IOException{}

给出可以从此文件输入流读取的字节数。返回一个 int。

文件输出流

FileOutputStream 用于创建文件并向其中写入数据。如果文件尚不存在,则流将创建一个文件,然后再打开它进行输出。

以下是两个可用于创建 FileOutputStream 对象的构造函数。

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

OutputStream f = new FileOutputStream("C:/java/hello") 

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

File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);

一旦您掌握了OutputStream对象,就会有一系列辅助方法,可用于写入流或在流上执行其他操作。

先生。 方法及说明
1

public void close() 抛出 IOException{}

该方法关闭文件输出流。释放与该文件关联的所有系统资源。抛出 IOException。

2

protected void Finalize() 抛出 IOException {}

此方法会清除与文件的连接。确保当不再有对此流的引用时,调用该文件输出流的 close 方法。抛出 IOException。

3

public void write(int w)抛出 IOException{}

此方法将指定的字节写入输出流。

4

公共无效写入(字节[] w)

将 w.length 个字节从上述字节数组写入到 OutputStream。

例子

以下是演示输入流和输出流的示例 -

import java.io.OutputStream;

public class fileStreamTest {

   public static void main(String args[]) {
   
      try {
         byte bWrite [] = {11,21,3,40,5};
         OutputStream os = new FileOutputStream("test.txt");
         for(int x = 0; x < bWrite.length ; x++) {
            os.write( bWrite[x] );   // writes the bytes
         }
         os.close();
     
         InputStream is = new FileInputStream("test.txt");
         int size = is.available();

         for(int i = 0; i < size; i++) {
            System.out.print((char)is.read() + "  ");
         }
         is.close();
      } catch (IOException e) {
         System.out.print("Exception");
      }	
   }
}

上面的代码将创建文件 test.txt 并以二进制格式写入给定的数字。标准输出屏幕上的输出也是如此。

Java 中的目录

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

创建目录

有两种有用的文件实用程序方法,可用于创建目录 -

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

  • mkdirs ()方法创建一个目录以及该目录的所有父目录。

以下示例创建“/tmp/user/java/bin”目录 -

例子

import java.io.File;

public class CreateDir {

   public static void main(String args[]) {
      String dirname = "/tmp/user/java/bin";
      File d = new File(dirname);
      
      // Create directory now.
      d.mkdirs();
   }
}

编译并执行上述代码,创建“/tmp/user/java/bin”。

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

列出目录

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

例子

import java.io.File;

public class ReadDir {

   public static void main(String[] args) {
      File file = null;
      String[] paths;
  
      try {      
         // create new file object
         file = new File("/tmp");

         // array of files and directory
         paths = file.list();

         // for each name in the path array
         for(String path:paths) {
            // prints filename and directory name
            System.out.println(path);
         }
      } catch (Exception e) {
         // if any error occurs
         e.printStackTrace();
      }
   }
}

这将根据/tmp目录中可用的目录和文件产生以下结果-

输出

test1.txt
test2.txt
ReadDir.java
ReadDir.class