Java文件和I/O


Java提供的java.io包几乎包含你可能需要执行输入和输出(I/O)的每个类。

编程语言的I/O类库中经常使用这个抽象概念,它代表产出数据的数据源或者接收数据的接收端。

java.io包中的流支持许多数据,例如字节数组、String对象、文件、管道、Internet连接等。


流可以定义为数据序列,分为两类:

  • 输入流(InputStream):InputStream用于从源读取数据。

  • 输出流(OutputStream):OutputStream用于将数据写入目标。

Java为与文件和网络相关的I/O提供了强大而灵活的支持,但是本教程只涵盖与流和I/O相关的基本功能。

字节流

Java字节流用于执行8位字节的输入和输出,尽管有许多与字节流相关的类,但最常用的类是FileInputStreamFileOutputStream

以下是使用这两个类将输入文件复制到输出文件的示例:

import java.io.*;
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.

下一步,编译并执行上述程序,这将导致创建output.txt文件,其内容与input.txt中的内容相同。

$javac CopyFile.java
$java CopyFile

字符流

Java字节流用于执行8位字节的输入和输出,而Java字符流用于执行16位unicode的输入和输出。

尽管有许多与字符流有关的类,但最常用的类是FileReader 和 FileWriter。

在内部FileReader使用FileInputStream、FileWriter使用FileOutputStream,两者主要区别在于FileReader一次读取两个字节,而FileWriter一次写入两个字节。

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

import java.io.*;
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文件。

$javac CopyFile.java
$java CopyFile

标准流


所有的编程语言都支持标准I/O,用户程序可以从键盘上获取输入,然后在计算机屏幕上产生输出。如果你了解C或C ++编程语言,则必须了解三种

标准设备STDIN、STDOUT和STDERR。同样,Java提供了以下三个标准流:

  • 标准输入:用于输入数据到用户程序,通常使用键盘作为标准输入流,并表示为系统输入(System.in)

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

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

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

import java.io.*;
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

读写文件


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

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

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

file_io.jpg

FileInputStream

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

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

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

接下来的构造方法使用一个文件对象来创建一个输入流对象来读取文件,首先,我们使用File()方法创建一个文件对象,如下所示:

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

输入流对象中有一些辅助方法,可用于读取流或对流执行其他操作:

序号方法与说明
1

public void close() throws IOException{}

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

2

protected void finalize() throws IOException {}

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

3

public int read(int r) throws IOException{}

此方法从InputStream读取指定的数据字节,返回一个整数,代表数据的下一个字节,如果在文件末尾,则返回-1。

4

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

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

5

public int available() throws IOException{}

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

FileOutputStream

FileOutputStream用于创建文件并将数据写入其中,流在打开文件进行输出之前会创建一个文件(如果不存在)。

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

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

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

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

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

输出流对象中有一些辅助方法,可用于写入流或对流执行其他操作:

序号方法与说明
1

public void close() throws IOException{}

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

2

protected void finalize() throws IOException {}

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

3

public void write(int w) throws IOException{}

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

4

public void write(byte[] w)

将上述字节数组中的w.length个字节写入OutputStream。

以下是演示InputStream和OutputStream的示例:

import java.io.*;
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] );   //写入字节
            }
            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对象

    上调用的方法以及与目录有关的方法的列表。

    创建目录

    有两个有用的File实用程序方法,可用于创建目录:

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

    • 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);
          
            //立即创建目录。
            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 {
                //创建新的文件对象
                file = new File("/tmp");
    
                //文件和目录的数组
                paths = file.list();
    
                //对于路径数组中的每个名称
                for(String path:paths) {
                    //打印文件名和目录名
                    System.out.println(path);
                }
            } catch (Exception e) {
                //如果发生任何错误
                e.printStackTrace();
            }
        }
    }

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

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