Java 流操作

本文已被阅读过 Posted by Liao Can on 2015-03-27

Java 流操作

关键词:InputStreamOutputStreamReaderWriter

1. 字符流和字节流

JAVA IO 中的流操作分为两类:

  • 字节流主要操作字节类型数据(byte)。主要类是 InputStream(输入) 和 OutputStream(输出)。
  • 字符流主要操作字符类型数据,一个字符占两个字节。主要类是 Reader(输入) 和 Writer(输出)。

JAVA IO 中的流操作类,常常是以输入、输出两种形式成对提供。

在 JAVA IO 中,流操作的一般流程如下:

  1. 使用 File 类绑定一个文件。
  2. 把 File 对象绑定到流对象上。
  3. 进行读或写操作。
  4. 关闭流

字符流和字节流的区别

  • 字节流主要操作字节类型数据(byte);字符流主要操作字符类型数据,一个字符占两个字节。
  • 字节流在操作时本身不会用到缓冲区(内存),而是对文件本身直接操作的;字符流在操作时使用了缓冲区,通过缓冲区再操作文件。

2. FileReader 和 FileWriter

FileReader 和 FileWriter 用于输入输出文本文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.io.*;

public class ReaderAndWriterDemo {

public static void output(String filepath) throws IOException {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
Writer out = new FileWriter(f);
// Writer out = new FileWriter(f, true); // 追加内容方式

// 3.进行读或写操作
String str = "Hello World!!!\r\n";
out.write(str);

// 4.关闭流
// 字符流操作时使用了缓冲区,并在关闭字符流时会强制将缓冲区内容输出
// 如果不关闭流,则缓冲区的内容是无法输出的
// 如果想在不关闭流时,将缓冲区内容输出,可以使用 flush 强制清空缓冲区
out.flush();
out.close();
}

public static char[] input(String filepath) throws IOException {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
Reader input = new FileReader(f);

// 3.进行读或写操作
int temp = 0; // 接收每一个内容
int len = 0; // 读取内容
char[] c = new char[1024];
while ((temp = input.read()) != -1) {
// 如果不是-1就表示还有内容,可以继续读取
c[len] = (char) temp;
len++;
}
System.out.println("文件字符数为:" + len);

// 4.关闭流
input.close();

return c;
}

public static void main(String[] args) throws IOException {
String filepath = "d:\\test.txt";

output(filepath);
System.out.println("内容为:" + new String(input(filepath)));
}
}

3. InputStreamReader 和 OutputStreamWriter

InputStreamReader 和 OutputStreamWriter 可以将 InputStream 和 OutputStream 分别转换为 Reader 和 Writer。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.*;

public class OutputStreamWriterDemo {

public static void main(String args[]) throws IOException {
File f = new File("d:" + File.separator + "test.txt");
Writer out = new OutputStreamWriter(new FileOutputStream(f));
out.write("hello world!!");
out.close();
}
}

public class InputStreamReaderDemo {

public static void main(String args[]) throws IOException {
File f = new File("d:" + File.separator + "test.txt");
Reader reader = new InputStreamReader(new FileInputStream(f));
char c[] = new char[1024];
int len = reader.read(c);
reader.close();
System.out.println(new String(c, 0, len));
}
}

4. BufferedReader

BufferedReader 类用于从缓冲区中读取内容,所有的输入字节数据都放在缓冲区中。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BufferedReaderDemo {

public static void main(String args[]) throws IOException {
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("请输入内容:");
String str = buf.readLine();
if (str.equalsIgnoreCase("exit")) {
System.out.print("退出");
break;
}
System.out.println("输入的内容为:" + str);
}
}
}

5. PrintStream

PrintStream 提供了非常方便的打印功能。

事实上,我们常用的 System 中提供的静态成员 System.out 和 System.err 就是 PrintStream 对象。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;

public class PrintStreamDemo {

public static void main(String arg[]) throws Exception {
final String filepath = "d:\\test.txt";
// 如果现在是使用 FileOuputStream 实例化,意味着所有的数据都会输出到文件中
OutputStream os = new FileOutputStream(new File(filepath));
PrintStream ps = new PrintStream(os);
ps.print("Hello ");
ps.println("World!!!");
ps.printf("姓名:%s;年龄:%d", "张三", 18);
ps.close();
}
}

6. FileInputStream 和 FileOutputStream

FileInputStream 和 FileOutputStream 用于输入、输出文件。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.io.*;

public class FileStreamDemo {

private static final String FILEPATH = "d:\\test.txt";

public static void output(String filepath) throws IOException {
// 第1步、使用File类找到一个文件
File f = new File(filepath);

// 第2步、通过子类实例化父类对象
OutputStream out = new FileOutputStream(f);
// 实例化时,默认为覆盖原文件内容方式;如果添加true参数,则变为对原文件追加内容的方式。
// OutputStream out = new FileOutputStream(f, true);

// 第3步、进行写操作
String str = "Hello World\r\n";
byte[] bytes = str.getBytes();
out.write(bytes);

// 第4步、关闭输出流
out.close();
}

public static void input(String filepath) throws IOException {
// 第1步、使用File类找到一个文件
File f = new File(filepath);

// 第2步、通过子类实例化父类对象
InputStream input = new FileInputStream(f);

// 第3步、进行读操作
// 有三种读取方式,体会其差异
byte[] bytes = new byte[(int) f.length()];
int len = input.read(bytes); // 读取内容
System.out.println("读入数据的长度:" + len);

// 第4步、关闭输入流
input.close();
System.out.println("内容为:\n" + new String(bytes));
}

public static void main(String args[]) throws Exception {
output(FILEPATH);
input(FILEPATH);
}
}

7. ByteArrayInputStream 和 ByteArrayOutputStream

ByteArrayInputStream 和 ByteArrayOutputStream 用于在内存中输入、输出数据。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.*;

public class ByteArrayStreamDemo {

public static void main(String args[]) {
String str = "HELLOWORLD"; // 定义一个字符串,全部由大写字母组成
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 准备从内存ByteArrayInputStream中读取内容
int temp = 0;
while ((temp = bis.read()) != -1) {
char c = (char) temp; // 读取的数字变为字符
bos.write(Character.toLowerCase(c)); // 将字符变为小写
}
// 所有的数据就全部都在ByteArrayOutputStream中
String newStr = bos.toString(); // 取出内容
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(newStr);
}
}

8. PipedInputStream 和 PipedOutputStream

PipedInputStream 和 PipedOutputStream 可以在两个线程间进行通信。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.*;

public class PipedStreamDemo {

static class Send implements Runnable {

private PipedOutputStream pos = null;

Send() {
pos = new PipedOutputStream(); // 实例化输出流
}

@Override
public void run() {
String str = "Hello World!!!";
try {
pos.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 得到此线程的管道输出流
*/
PipedOutputStream getPos() {
return pos;
}
}

static class Receive implements Runnable {

private PipedInputStream pis = null;

Receive() {
pis = new PipedInputStream();
}

@Override
public void run() {
byte b[] = new byte[1024];
int len = 0;
try {
len = pis.read(b);
} catch (IOException e) {
e.printStackTrace();
}
try {
pis.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("接收的内容为:" + new String(b, 0, len));
}

/**
* 得到此线程的管道输入流
*/
PipedInputStream getPis() {
return pis;
}
}

public static void main(String args[]) {
Send s = new Send();
Receive r = new Receive();
try {
s.getPos().connect(r.getPis()); // 连接管道
} catch (IOException e) {
e.printStackTrace();
}
new Thread(s).start(); // 启动线程
new Thread(r).start(); // 启动线程
}
}

9. DataInputStream 和 DataOutputStream

DataInputStream 和 DataOutputStream 会一定格式将数据输入、输出。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.io.*;

public class DataStreamDemo {

public static final String FILEPATH = "d:\\order.txt";

private static void output(String filepath) throws IOException {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
DataOutputStream dos = new DataOutputStream(new FileOutputStream(f));

// 3.进行读或写操作
String names[] = {"衬衣", "手套", "围巾"};
float prices[] = {98.3f, 30.3f, 50.5f};
int nums[] = {3, 2, 1};
for (int i = 0; i < names.length; i++) {
dos.writeChars(names[i]);
dos.writeChar('\t');
dos.writeFloat(prices[i]);
dos.writeChar('\t');
dos.writeInt(nums[i]);
dos.writeChar('\n');
}

// 4.关闭流
dos.close();
}

private static void input(String filepath) throws IOException {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
DataInputStream dis = new DataInputStream(new FileInputStream(f));

// 3.进行读或写操作
String name = null; // 接收名称
float price = 0.0f; // 接收价格
int num = 0; // 接收数量
char temp[] = null; // 接收商品名称
int len = 0; // 保存读取数据的个数
char c = 0; // '\u0000'
try {
while (true) {
temp = new char[200]; // 开辟空间
len = 0;
while ((c = dis.readChar()) != '\t') { // 接收内容
temp[len] = c;
len++; // 读取长度加1
}
name = new String(temp, 0, len); // 将字符数组变为String
price = dis.readFloat(); // 读取价格
dis.readChar(); // 读取\t
num = dis.readInt(); // 读取int
dis.readChar(); // 读取\n
System.out.printf("名称:%s;价格:%5.2f;数量:%d\n", name, price, num);
}
} catch (EOFException e) {
System.out.println("结束");
} catch (IOException e) {
e.printStackTrace();
}

// 4.关闭流
dis.close();
}

public static void main(String args[]) throws IOException {
output(FILEPATH);
input(FILEPATH);
}
}

10. ZipInputStream 和 ZipOutputStream

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import java.io.*;
import java.util.zip.*;

public class ZipStreamDemo {

public static final String ZIP_FILE_PATH = "d:\\zipdemo.zip";

public static void demo01(String zipfilepath) throws IOException {
File file = new File(zipfilepath);
ZipFile zipFile = new ZipFile(file);
ZipEntry entry = zipFile.getEntry("mldn.txt");
System.out.println("压缩文件的名称:" + zipFile.getName());

File outputFile = new File("d:" + File.separator + "mldn_unzip.txt");
OutputStream out = new FileOutputStream(outputFile); // 实例化输出流
InputStream input = zipFile.getInputStream(entry); // 得到一个压缩实体的输入流
int temp = 0;
while ((temp = input.read()) != -1) {
out.write(temp);
}
input.close(); // 关闭输入流
out.close(); // 关闭输出流
}

/**
* 压缩一个文件
*/
public static void output1(String filepath, String zipfilepath) throws Exception {
// 1.使用 File 类绑定一个文件
// 定义要压缩的文件
File file = new File(filepath);
// 定义压缩文件名称
File zipFile = new File(zipfilepath);

// 2.把 File 对象绑定到流对象上
InputStream input = new FileInputStream(file);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));

// 3.进行读或写操作
zipOut.putNextEntry(new ZipEntry(file.getName()));
zipOut.setComment("This is a zip file.");
int temp = 0;
while ((temp = input.read()) != -1) { // 读取内容
zipOut.write(temp); // 压缩输出
}

// 4.关闭流
input.close();
zipOut.close();
}

/**
* 读取实体为一个文件的压缩包
*/
public static void input1(String zipfilepath, String filepath) throws Exception {
// 1.使用 File 类绑定一个文件
File zipFile = new File(zipfilepath);

// 2.把 File 对象绑定到流对象上
ZipInputStream input = new ZipInputStream(new FileInputStream(zipFile));

// 3.进行读或写操作
ZipEntry entry = input.getNextEntry(); // 得到一个压缩实体
System.out.println("压缩实体名称:" + entry.getName());

// 4.关闭流
input.close();
}

/**
* 压缩一个目录
*/
public static void output2(String dirpath, String zipfilepath) throws Exception {
// 1.使用 File 类绑定一个文件
// 定义要压缩的文件夹
File file = new File(dirpath);
// 定义压缩文件名称
File zipFile = new File(zipfilepath);

// 2.把 File 对象绑定到流对象上
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.setComment("This is zip folder.");

// 3.进行读或写操作
int temp = 0;
if (file.isDirectory()) { // 判断是否是文件夹
File lists[] = file.listFiles(); // 列出全部文件
for (int i = 0; i < lists.length; i++) {
InputStream input = new FileInputStream(lists[i]);
// 设置ZipEntry对象
zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + lists[i].getName()));
while ((temp = input.read()) != -1) {
zipOut.write(temp);
}
input.close();
}
}

// 4.关闭流
zipOut.close();
}

/**
* 解压实体为一个目录的压缩包
*/
public static void input2(String zipfilepath, String dirpath) throws Exception {
// 1.使用 File 类绑定一个文件
File file = new File(zipfilepath);
ZipFile zipFile = new ZipFile(file);

// 2.把 File 对象绑定到流对象上
ZipInputStream zis = new ZipInputStream(new FileInputStream(file));

// 3.进行读或写操作
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null) { // 得到一个压缩实体
System.out.println("解压缩" + entry.getName() + "文件。");
// 定义输出的文件路径
File outFile = new File(dirpath + File.separator + entry.getName());
if (!outFile.getParentFile().exists()) { // 如果输出文件夹不存在
outFile.getParentFile().mkdirs(); // 创建文件夹
}
if (!outFile.exists()) { // 判断输出文件是否存在
outFile.createNewFile(); // 创建文件
}
InputStream input = zipFile.getInputStream(entry); // 得到每一个实体的输入流
OutputStream out = new FileOutputStream(outFile); // 实例化文件输出流
int temp = 0;
while ((temp = input.read()) != -1) {
out.write(temp);
}
input.close(); // 关闭输入流
out.close(); // 关闭输出流
}

// 4.关闭流
zis.close();
}

public static void main(String[] args) throws Exception {
final String filepath = "d:\\demo.txt";
final String zipfilepath = "d:\\demo.zip";

final String dirpath = "d:\\demo2";
final String dirpath2 = "d:\\new";
final String zipfilepath2 = "d:\\demo2.zip";

// demo01(ZIP_FILE_PATH);
output1(filepath, zipfilepath);
input1(zipfilepath, filepath);

output2(dirpath, zipfilepath2);
input2(zipfilepath2, dirpath2);
}
}

11. ObjectInputStream 和 ObjectOutputStream

ObjectInputStream 和 ObjectOutputStream 是对象输入输出流,一般用于对象序列化。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.io.*;

public class ObjectStream {

public static class Person implements Serializable {

private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "姓名:" + this.name + ";年龄:" + this.age;
}
}

public static void writeObject(String filepath, Object obj[]) throws Exception {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
OutputStream out = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(out);

// 3.进行读或写操作
oos.writeObject(obj);

// 4.关闭流
oos.close();
}

public static Object[] readObject(String filepath) throws Exception {
// 1.使用 File 类绑定一个文件
File f = new File(filepath);

// 2.把 File 对象绑定到流对象上
InputStream input = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(input);

// 3.进行读或写操作
Object[] objects = (Object[]) ois.readObject();

// 4.关闭流
ois.close();
return objects;
}

public static void main(String args[]) throws Exception {
final String filepath = "d:\\object.txt";
Person per[] = {new Person("张三", 30), new Person("李四", 31), new Person("王五", 32)};
writeObject(filepath, per);
Object o[] = readObject(filepath);
for (int i = 0; i < o.length; i++) {
Person p = (Person) o[i];
System.out.println(p);
}
}
}

支付宝打赏 微信打赏

赞赏一下