Java 文件和输入输出
java.io包包含了你在Java中可能需要执行输入和输出(I/O)操作的几乎所有类。所有这些流代表了一个输入源和一个输出目的地。java.io包中的流支持多种数据类型,例如原始类型、对象、本地化字符等。
流
流可以被定义为一系列的数据。有两种类型的流:
- InputStream - InputStream用于从源读取数据。
-
OutputStream - OutputStream用于将数据写入目的地。
Java提供了强大而灵活的支持文件和网络相关的I/O,但本教程仅涵盖与流和I/O相关的基本功能。我们将逐个查看最常用的示例。
字节流
Java字节流用于执行8位字节的输入和输出。尽管有许多与字节流相关的类,但最常用的类是 FileInputStream 和 FileOutputStream。以下是一个示例,该示例使用这两个类将输入文件复制到输出文件中。
示例
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.
作为下一步,将上述程序编译并执行,将会创建一个与input.txt文件内容相同的output.txt文件。所以让我们将上述代码放入CopyFile.java文件中,并进行如下操作 –
$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.
作为下一步,编译上面的程序并执行,这将导致创建一个output.txt文件,其内容与我们在input.txt文件中的内容相同。因此,让我们将上述代码放在CopyFile.java文件中,并执行以下操作−
$javac CopyFile.java
$java CopyFile
标准流
所有编程语言都提供标准输入/输出支持,用户程序可以从键盘输入数据,然后在计算机屏幕上输出结果。如果您熟悉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
读写文件
正如之前所述,流可以被定义为一系列的数据。InputStream 用于从源头读取数据,而OutputStream 用于将数据写入目的地。
以下是处理输入和输出流的类的层次结构。
两个重要的流是 FileInputStream 和 FileOutputStream ,将在本教程中进行讨论。
FileInputStream
该流用于从文件中读取数据。可以使用关键字 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() 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。 |
还有其他重要的输入流可用,更多详细信息可以参考以下链接−
- ByteArrayInputStream
-
DataInputStream
FileOutputStream
FileOutputStream用于创建文件并将数据写入其中。在打开输出之前,如果文件不存在,流会创建一个文件。
这里有两个构造方法可用于创建FileOutputStream对象。
以下构造方法使用文件名作为字符串来创建一个输入流对象以写入文件−
OutputStream f = new FileOutputStream("C:/java/hello")
以下构造函数使用文件对象创建输出流对象以写入文件。首先,我们使用File()方法创建一个文件对象,如下所示 –
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
一旦你手头有OutputStream对象,那么就有一系列可用于向流中写入或执行其他操作的辅助方法。
Sr.No. | 方法与描述 |
---|---|
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个字节到输出流。 |
还有其他重要的输出流可用,详细内容可以参考以下链接:
- ByteArrayOutputStream
-
DataOutputStream
示例
以下是演示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] ); // 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,并以二进制格式写入给定的数字。同样的输出将显示在stdout屏幕上。
文件导航和I/O
还有其他几个类,我们将通过它们来了解文件导航和I/O的基础知识。
- File类
-
FileReader类
-
FileWriter类
Java中的目录
目录是一个可以包含其他文件和目录列表的文件。你可以使用 File 对象来创建目录,列出目录中可用的文件。有关完整详情,请检查可以在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