Java 输入输出流

Java 通过数据流、序列化和文件系统来实现系统的输入输出,把不同来源和目标的数据都统一抽抽象为数据流。Java 中的输入输出是十分强大而灵活的,不过代码稍显臃肿,往往要封装许多的对象和操作,I/O 的内容是很庞大的,因为涉及的领域很广泛:标准的输入输出、文件操作、网络数据流、字符串流、对象流、zip 文件流。

流的分类

按照流向区分

  • 输入流:程序可以从中读取数据的流。
  • 输出流:程序能向其写入数据的流。

按照数据传输单位区分

  • 字节流:以字节为单位传输数据的流
  • 字符流:以字符为单位传输数据的流
  • 节点流:用于直接操作目标设备的流
  • 过滤流:是一个对于已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能

java.io 常用类

JDK 的 java.io 中含有 Java 所有流封装,分别继承一下四种抽象类:

  1. InputStream : 继承自 InputStream 的流用于向程序中输入数据,数据单位为字节(8位)
  2. OutputStream : 继承自 OutputStream 的流都是程序中用于向外输出数据的,数据单位为字节(8位)
  3. Reader : 继承自 Reader 的流用于向程序中输入数据,数据单位为字符(16位)
  4. Writer : 继承自 Writer 的流都是程序用于向外输出数据的,数据单位为字符(16位)

在 Java 中,IO 部分的内容是很庞大的,涉及的领域很广泛,流是一个很形象的概念,当程序需要读取数据的时候,会开启一个通向数据源的流,这个数据源可以是文件、内存或者是网络连接,类似的,当程序需要写入数据的时候,会开启一个通向目的地的流,这之后可以通过流将信息”流向“目标。

如图:

Java_stream

输入输出类层级结构

Java_iocstream

Java 中的流分为两种:字节流和字符流,分别由四个抽象类来表示(每种流分输入、输出,故共四个):InputStream,OutputStream,Reader,Writer,Java 中其他多样的流均是由它们派生出来,stream 代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。

在 Java 的 IO 中,所有的 stream(包括 Inputstream 和 Outstream)都包括两种类型:

  1. 字节流 表示以字节为单位从 stream 中读取或往 stream 中写入信息,即 io 包中的 inputstream 类和 outputstream 类的派生类。通常用来读取二进制数据,如图象和声音。
  2. 字符流 以 Unicode 字符为导向的 stream,表示以 Unicode 字符为单位从 stream 中读取或往 stream 中写入信息。

Reader 和 Writer 主要解决的问题是国际化的问题,原先 I/O 类库只支持 8 位的字节流,因此不能有效的处理 16 位的 Unicode 字符流,Unicode 是国际化的字符集,故加上 Reader 和 Writer ,所有的 I/O 均支持 Unicode 了,此外新类库的性能也要更好一些。但是,Reader 和 Writer 并不是取代 InputSteam 和 OutputStem,有时,需要同时使用 ” 基于 byte 的类 “ 和 ”基于字符的类 “,为此,提供了两个 ”适配器 ” 类,InputStreamReader 负责将 InputStream 转化为 Reader ,而 OutputStreamWriter 则将 OutputStream 转化成 Writer。

按照输入输出划分文件流:

Java_iostream_InputStream

Java_iostream_OutputStream

输入输出

FileInputStream

从文件读取数据,对象可以通过 new 关键字来创建。

有多种构造方法。

可以通过使用字符串类型的文件名来创建一个输入流对象来读取文件。

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

也可以使用一个文件对象来创建一个输入流对象来读取文件。首先使用 File 方法创建一个对象文件:

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

创建 InputStream 对象后,可通过下面的方法来读取流或者进行其他流操作。

方法 描述
public void close() throws IOException{} 关闭此文件输入流并释放与此流有关的所有系统资源。抛出 IOException 异常。
protected void finalize()throws IOException {} 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出 IOException 异常。
public int read(int r)throws IOException{} 这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。
public int read(byte[] r) throws IOException{} 这个方法从输入流读取 r.length 长度的字节。返回读取的字节数。如果是文件结尾则返回 -1。
public int available() throws IOException{} 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。

其他输入流暂未总结,参考其他资料。

FileOutputStream

该类用来创建一个文件并向文件中写入数据。

如果该流在打开文件进行输出钱,目标文件不存在,那么该流会创建该文件。

有两个构造方法可以创建 FileOutputStream 对象。

使用字符串类型的文件名来创建一个输出流对象:

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

也可以用一个文件对象来创建一个输出流来写文件,首先使用 File() 方法来创建一个文件对象:

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

创建 OutputStream 对象完成后,可以使用下面的方法来写入流或者进行其他操作:

方法 描述
public void close() throws IOException{} 关闭此文件输入流并释放与此流有关的所有系统资源。抛出 IOException 异常。
protected void finalize() throws IOException {} 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出 IOException 异常。
public void write(int w) throws IOException{} 这个方法把指定的字节写到输出流中。
public void write(byte[] w) 把指定数组中 w.length 长度的字节写到 OutputStream 中。

####文件目录

创建目录

File 类中有两个方法可以用来创建文件夹:

  • mkdir() 方法创建一个文件夹,成功返回 true ,失败返回 false ,失败表明 File 对象指定的路径已经存在,或者整个路径还不存在,该文件夹不能创建
  • mkdirs() 方法创建一个文件夹和它的所有父文件夹

Notes:

Java 在 UNIX 和 Windows 自动按约定分别文件路径分隔符,在 Windows 版本的 Java 中使用分隔符 (/) ,依然会被解析,同样亦可用 \\

Demo:

1
2
3
4
5
6
7
8
public class CreateDir {
public static void main(String args[]) {
String dirname = "D:/tmp/user/java/bin";
File d = new File(dirname);
// 现在创建目录
d.mkdirs();
}
}
读取目录

一个目录就是一个 File 对象,它包含其他文件和文件夹

如果创建一个 File 对象并且他是一个目录,那么 isDirectory() 方法会返回 true

可以通过调用对象上 list() 方法,来提取包含的文件和文件夹列表

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class DirList {
public static void main(String args[]) {
String dirname = "D:/ProjectsJava/JavaDemo";
File f1 = new File(dirname);
if (f1.isDirectory()) {
System.out.println("目录 " + dirname);
String s[] = f1.list();
for (int i = 0; i < s.length; i++) {
File f = new File(dirname + "/" + s[i]);
// System.out.println(dirname + "/" + s[i]);
if (f.isDirectory()) {
System.out.println(s[i] + " 是一个目录");
} else {
System.out.println(s[i] + " 是一个文件");
}
}
} else {
System.out.println(dirname + " 不是一个目录");
}
}
}
删除目录和文件夹

删除文件可以采用 java.io.File.delete() 方法

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class DeleteFile {
public static void main(String args[]) {
File folder = new File("D:/tmp");
deleteFolder(folder);
}
//删除文件及目录
public static void deleteFolder(File folder) {
File[] files = folder.listFiles();
if(files!=null) {
for(File f: files) {
if(f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
folder.delete();
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!
0%