文章目录
前言
Java中java.io包几乎包含了所有我们需要用到的和输入输出(Input和Output, 即I/O)操作相关的类。所有这些输入输出操作都包含了输入流和输出流,java.io包中的流支持很多类型的数据,例如基础数据类型、对象和各地语言字符等等。
流
流(stream)可以定义为一序列的数据。流可以分为两种:
- 输入流InputStream - InputStream可以用来从数据源读取数据。
- 输出流OutputStream - OutputStream可以用来将数据写入文件。
Java为与文件和网络相关的I/O提供了强大而灵活的支持,不过本教程只涵盖了与流和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.
接着,编译上面的程序然后执行,执行完成后会程序会创建一个output.txt文件,这个文件的内容和input.txt一样。我们只需要创建一个CopyFile.java文件,将上面代码复制到这个文件里,然后执行下面的命令语句:
javac CopyFile.java
java CopyFile.java
字符流
Java字节流用于处理8比特位字节的输入和输出,而Java字符流用于处理16比特位unicode的输入和输出。尽管有很多类与字符流相关,但最常用的是FileReader和FileWriter类。虽然从底层实现上来看,FileReader类使用的是FileInputStream类,而FileWriter使用的是FileOutPutStream类,但是两者主要的差别是FileReader每次读两个字节,而FileWriter每次写两个字节。
我们可以将上面复制输入文件的程序实例改写为FileReader和FileWriter来实现。
程序实例
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.java
标准流
所有的编程语言都提供标准的I/O,用户的程序可以使用标准I/O流来从键盘输入、从电脑屏幕输出。如果你了解C或C++语言的话,那你一定知道有3个标准的输入输出:STDIN、STDOUT和STDERR。与其相似,Java也提供3中标准流:
- 标准输入流 - 用于将数据馈送到用户程序,通常将键盘用作标准输入流,其调用为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
读取文件
如前文所述,流(stream)可以被定义为一序列的数据。InputStream用于从文件读取数据,OutputStream用于将数据写入目标文件。
下图是Java中用于处理输入输出流的类及层次。
其中,两个重要的处理流的类是FileInputStream和FileOutputStream,下文将会对这两个类进行介绍。
FileInputStream
FileInputStream类用来从文件读取数据。FileInputStream类的对象可以使用new关键字来创建,有多个构造器可供使用。
下面语句使用文件名作为构造器参数来创建对象读取文件:
InputStream f = new FileInputStream("C:/java/hello");
下面语句首先创建了一个File文件,然后将文件作为构造器参数来创建FileInputStream对象读取文件:
File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);
一旦获得了输入流对象,我们就可以通过一系列方法来读取流或做其它操作。
序号 | 方法 & 描述 |
---|---|
1 | public void close() throws IOException{} 用于关闭文件输入流。 |
2 | protected void finalize() throws IOException {} 用于清空文件的连接。 |
3 | public int read(int r) throws IOException{} 从输入流读取指定字节长度的数据。 |
4 | public int read(byte[] r) throws IOException{} 从输入流读取r.length()长度的字节到数组中。 |
5 | public int available() throws IOException{} 返回可以从输入流中读取字节的长度。 |
除了FileInputStream类之外,Java还提供了其它有用的类来处理输入流:
- ByteArrayInputStream
- DataInputStream
FileOutputStream
FileOutputStream用来将数据写入创建的文件中。如果在写入文件之前文件不存在的话,输出流会打开文件之前创建该文件。
和FileInputStream一样,FileOutputStream也可以通过下面两种方式创建对象。
首先是,使用文件名作为构造器参数来创建流对象:
OutputStream f = new FileOutputStream("C:/java/hello");
其次是,先创建一个File文件对象,然后将File对象作为参数传入FileOutputStream流对象。
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
一旦获得了输出流对象,我们就可以通过一系列方法来将数据写入流或做其它操作。
序号 | 方法 & 描述 |
---|---|
1 | public void close() throws IOException{} 用于关闭文件输出流。 |
2 | protected void finalize() throws IOException{} 用于清空文件的连接。 |
3 | public void write(int w) throws IOException{} 将指定长度的字节写入输出流。 |
4 | public void write(byte[] w) 将w.length()长度的字节数组写入输出流。 |
除了FileOutputStream类之外,Java还提供了其它有用的类来处理输出流:
- ByteArrayOutputStream
- DataOutputStream
程序实例
下面程序展示了如何使用操作输入流和输出流。
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文件,并将给定的数字以二进制形式写入文件,控制台中输出的和文件中的内容相同。
File类和I/O
我们可以使用下面几个类来进行文件和I/O操作:
- File类
- FileReader类
- FileWriter类
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系统上使用正斜杠(/),路径仍将正确解析。
列举目录
我们可以使用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();
//遍历paths数组
for(String path:paths) {
//打印文件名和目录名
System.out.println(path);
}
} catch (Exception e) {
//出现错误时打印错误信息
e.printStackTrace();
}
}
}
程序运行后会输出/tmp目录下的所有文件和目录:
test1.txt
test2.txt
ReadDir.java
ReadDir.class
关注公众号「小白轻松学编程」
更多交流,欢迎微信搜索并关注公众号「小白轻松学编程」!
博客里所有教程会第一时间在公众号上更新哟,扫码关注一下吧~