在上面的关系图中可以看出:
Writer 是所有的输出字符流的父类,它是一个抽象类。
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。
PipedWriter 是向与其它线程共用的管道中写入数据,
BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。
【案例】向文件中写入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 字符流
* 写入数据
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args)
throws
IOException {
String fileName=
"D:"
+File.separator+
"hello.txt"
;
File f=
new
File(fileName);
Writer out =
new
FileWriter(f);
String str=
"hello"
;
out.write(str);
out.close();
}
}
|
注意:这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为:
Writer out =new FileWriter(f,true);
这样,当你运行程序的时候,会发现文件内容变为:hellohello如果想在文件中换行的话,需要使用“\r\n”比如将str变为String str="\r\nhello";这样文件追加的str的内容就会换行了。
(1)其是字符流和字节流之间的桥梁
(2)可对读取到的字节数据经过指定编码转换成字符
(3)可对读取到的字符数据经过指定编码转换成字节
当字节和字符之间有转换动作时;
流操作的数据需要编码或解码时。
InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。
【案例】将字节输出流转化为字符输出流
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/**
* 将字节输出流转化为字符输出流
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args)
throws
IOException {
String fileName=
"d:"
+File.separator+
"hello.txt"
;
File file=
new
File(fileName);
Writer out=
new
OutputStreamWriter(
new
FileOutputStream(file));
out.write(
"hello"
);
out.close();
}
}
|
【案例】将字节输入流转换为字符输入流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 将字节输入流变为字符输入流
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args)
throws
IOException {
String fileName=
"d:"
+File.separator+
"hello.txt"
;
File file=
new
File(fileName);
Reader read=
new
InputStreamReader(
new
FileInputStream(file));
char
[] b=
new
char
[
100
];
int
len=read.read(b);
System.out.println(
new
String(b,
0
,len));
read.close();
}
}
|
File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。
【案例 】创建一个文件
1
2
3
4
5
6
7
8
9
10
11
|
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
File f=
new
File(
"D:\\hello.txt"
);
try
{
f.createNewFile();
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
|
【案例2】File类的两个常量
1
2
3
4
5
6
7
|
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
System.out.println(File.separator);
System.out.println(File.pathSeparator);
}
}
|
此处多说几句:有些同学可能认为,我直接在windows下使用\进行分割不行吗?当然是可以的。但是在linux下就不是\了。所以,要想使得我们的代码跨平台,更加健壮,所以,大家都采用这两个常量吧,其实也多写不了几行。
【案例3】File类中的常量改写案例1的代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator+
"hello.txt"
;
File f=
new
File(fileName);
try
{
f.createNewFile();
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
|
【案例4】删除一个文件(或者文件夹)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator+
"hello.txt"
;
File f=
new
File(fileName);
if
(f.exists()){
f.delete();
}
else
{
System.out.println(
"文件不存在"
);
}
}
}
|
【案例5】创建一个文件夹
1
2
3
4
5
6
7
8
9
10
11
|
/**
* 创建一个文件夹
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator+
"hello"
;
File f=
new
File(fileName);
f.mkdir();
}
}
|
【案例6】列出目录下的所有文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* 使用list列出指定目录的全部文件
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator;
File f=
new
File(fileName);
String[] str=f.list();
for
(
int
i =
0
; i < str.length; i++) {
System.out.println(str[i]);
}
}
}
|
注意使用list返回的是String数组,。而且列出的不是完整路径,如果想列出完整路径的话,需要使用listFiles.它返回的是File的数组。
【案例7】列出指定目录的全部文件(包括隐藏文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 使用listFiles列出指定目录的全部文件
* listFiles输出的是完整路径
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator;
File f=
new
File(fileName);
File[] str=f.listFiles();
for
(
int
i =
0
; i < str.length; i++) {
System.out.println(str[i]);
}
}
}
|
【案例8】判断一个指定的路径是否为目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 使用isDirectory判断一个指定的路径是否为目录
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator;
File f=
new
File(fileName);
if
(f.isDirectory()){
System.out.println(
"YES"
);
}
else
{
System.out.println(
"NO"
);
}
}
}
|
【案例9】递归搜索指定目录的全部内容,包括文件和文件夹
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
* 列出指定目录的全部内容
* */
import
java.io.*;
class
hello{
public
static
void
main(String[] args) {
String fileName=
"D:"
+File.separator;
File f=
new
File(fileName);
print(f);
}
public
static
void
print(File f){
if
(f!=
null
){
if
(f.isDirectory()){
File[] fileArray=f.listFiles();
if
(fileArray!=
null
){
for
(
int
i =
0
; i <filearray.length; i++)=
""
{=
""
递归调用=
""
print(filearray[i]);=
""
}=
""
else
{=
""
system.out.println(f);=
""
}<=
""
pre=
""
>
<p></p>
<h2>
10
.RandomAccessFile类</h2>
<p>该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。该对象特点:</p>
<p>该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。</p>
<p>该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)</p>
<p>注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。可以用于多线程下载或多个线程同时写数据到文件。</p>
<p align=
"left"
>【案例】使用RandomAccessFile写入文件</p>
<p align=
"left"
></p>
<pre
class
=
"brush:java;"
>
/**
* 使用RandomAccessFile写入文件
* */
import
java.io.*;
class
hello{
public
static
void
main(String[]args)
throws
IOException {
StringfileName=
"D:"
+File.separator+
"hello.txt"
;
File f=
new
File(fileName);
RandomAccessFile demo=newRandomAccessFile(f,
"rw"
);
demo.writeBytes(
"asdsad"
);
demo.writeInt(
12
);
demo.writeBoolean(
true
);
demo.writeChar(
'A'
);
demo.writeFloat(
1
.21f);
demo.writeDouble(
12.123
);
demo.close();
}
}</pre>
<p></p>
<h1>Java IO流的高级概念</h1>
<h2>编码问题</h2>
<p>【案例 】取得本地的默认编码</p>
<p></p>
<pre
class
=
"brush:java;"
>
/**
* 取得本地的默认编码
* */
publicclass CharSetDemo{
public
static
void
main(String[] args){
System.out.println(
"系统默认编码为:"
+ System.getProperty(
"file.encoding"
));
}
}</pre>
<p></p>
<p>【案例 】乱码的产生</p>
<p></p>
<pre
class
=
"brush:java;"
>
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.OutputStream;
/**
* 乱码的产生
* */
public
class
CharSetDemo2{
public
static
void
main(String[] args)
throws
IOException{
File file =
new
File(
"d:"
+ File.separator +
"hello.txt"
);
OutputStream out =
new
FileOutputStream(file);
byte
[] bytes =
"你好"
.getBytes(
"ISO8859-1"
);
out.write(bytes);
out.close();
}
//输出结果为乱码,系统默认编码为GBK,而此处编码为ISO8859-1
}</pre>
<h2>对象的序列化</h2>
<p>对象序列化就是把一个对象变为二进制数据流的一种方法。</p>
<p>一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。先让我们实现一个具有序列化能力的类吧:</p>
<p>【案例 】实现具有序列化能力的类</p>
<p></p>
<pre
class
=
"brush:java;"
>
import
java.io.*;
/**
* 实现具有序列化能力的类
* */
public
class
SerializableDemo
implements
Serializable{
public
SerializableDemo(){
}
publicSerializableDemo(String name,
int
age){
this
.name=name;
this
.age=age;
}
@Override
public
String toString(){
return
"姓名:"
+name+
" 年龄:"
+age;
}
private
String name;
private
int
age;
}</pre>
<p></p>
<p>【案例 】序列化一个对象 – ObjectOutputStream</p>
<p></p>
<pre
class
=
"brush:java;"
>
import
java.io.Serializable;
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.ObjectOutputStream;
/**
* 实现具有序列化能力的类
* */
public
class
Person
implements
Serializable{
public
Person(){
}
public
Person(String name,
int
age){
this
.name = name;
this
.age = age;
}
@Override
public
String toString(){
return
"姓名:"
+name +
" 年龄:"
+age;
}
private
String name;
private
int
age;
}
/**
* 示范ObjectOutputStream
* */
public
class
ObjectOutputStreamDemo{
public
static
voidmain(String[] args)
throws
IOException{
File file = newFile(
"d:"
+ File.separator +
"hello.txt"
);
ObjectOutputStream oos=
new
ObjectOutputStream(
new
FileOutputStream(
file));
oos.writeObject(newPerson(
"rollen"
,
20
));
oos.close();
|