黑马程序员技术交流社区
标题:
[石家庄校区]就业班JavaSE高级部分day10 缓冲流 转换流 序列...
[打印本页]
作者:
湿漉漉的文字控
时间:
2018-11-26 16:02
标题:
[石家庄校区]就业班JavaSE高级部分day10 缓冲流 转换流 序列...
就业班JavaSE高级部分day10 缓冲流 转换流 序列化流 打印流
基本流:
Filexxx
包装流:
在基本流的外面增加一些便捷功能,最终读写的还是基本流,包装流只增强的
基本流的功能
缓冲流:
BufferedOutputStream:字节缓冲输出流
extents OutputStream
能够使用子类的共用方法
格式
BufferedOutputStream bos = new BufferedOutputStream(OutputStream
out)
BufferedInputStream::字节缓冲输入流
extents InputStream
能够使用子类的共用方法
格式
BuffInputStream bis = new BuffInputStream(InputStream in)
BuffWriter:字符缓冲输出流
extends Writer
能够使用子类共用的方法
特有方法:
void newLine(); 写入一个行分隔符,根据不同的操作系统,获取不同的行分隔符
格式
BufferedWriter bw = new BufferedWriter(Writer out);
BufferedReader:字符缓冲输入流
extends Reader
能够使用子类共用的方法
特有方法:
String readLine();一次读取一行字符串,(遇行的终止符号即停止)不包括换行符,返回
值为null.
格式:
BufferedReader br = new BufferedReader(Reader in);
案例:把文件中的段落排序
步骤分析:
1. 创建ArrayList集合, 泛型用String
2. 创建BufferedReader对象, 构造方法中传递FileReader对象, 指向模块下的in.txt
3. 创建BufferedWriter对象, 构造方法中传递FileWriter对象, 指向模块下的out.txt
4. 使用BufferedReader对象中的方法readLine, 以行的方式读取文本
5. 把读取到的文本存储到ArrayList集合中
6. 使用Collections集合工具类的方法sort, 对集合中的元素按照自定义规则排序
7. 遍历ArrayList集合, 获取每一个元素
8. 使用BufferedWriter对象中的方法write, 把遍历得到的元素写入到文本中(内存缓冲区)
9. 写换行
10. 释放资源
import
java.io.*;
import
java.util.ArrayList;
import
java.util.Collections;
import
java.util.Comparator;
public class
Test5
{
public static void
main(String[]
args
)
throws
IOException
{
BufferedReader
br
=
new
BufferedReader(
new
FileReader(
"day10
\\
in.txt"
));
BufferedWriter
bw
=
new
BufferedWriter(
new
FileWriter(
"day10
\\
out.txt"
));
//
创建一个集合 用来存储读出来的数据 和进行排序
ArrayList<String>
list
=
new
ArrayList<>();
//
调用
BufferedReader
对象中的
readLine
方法一次读取一行 创建一个变量用来接收
read
出来的值
String
line
;
while
((
line
=
br
.readLine()) !=
null
)
{
//
把的出来的
line
放到集合中
list
.add(
line
);
}
//
根据首字符正序排序
//Collections.sort(list, (o1, o2) -> o1.charAt(0) - o2.charAt(0));
list
.sort((
o1
,
o2
) ->
o1
.charAt(
0
) -
o2
.charAt(
0
));
//
遍历集合放到
out
文件中
for
(String
s
:
list
)
{
//
写入文件
bw
.write(
s
);
//
写入不包括换行符所以调用
newLine
换行
bw
.newLine();
}
//
释放资源
bw
.close();
br
.close();
}
}
转换流:
编码:字符(能看懂)-->字节(不能看懂)
解码:字节(看不懂)-->字符(能看懂)
字符编码
是一套自然语言的字符与二进制之间的对应规则
乱码问题:
原因:
读写编码不一致
java.io.Reader
|_ InputStreamReader: 转换字符输入流 byte --查指定码表--> char, char[], String
|_ FileReader byte --查UTF-8码表--> char
java.io.Writer
|_ OutputStreamWriter: 转换字符输出流 char, char[], String --查指定码表--> byte
|_ FileWriter char --查UTF-8码表--> byte
案例:
需求:
使用转换流, 读取GBK编码文件"我是GBK文件.txt"中的"你好", 转写到UTF-8编码文件"我是
UTF8文件.txt"中, 保证UTF-8文件打开也能看到正确的中文
分析:
GBK编码文件中保存的字符, 是根据GBK查询到的byte. UTF-8文件中, 要写入根据UTF-
8查到的byte
GBK"你好"的byte --> 按GBK读 --> "你好" --> 按UTF-8写 --> UTF-8"你好"的byte
InputStreamReader OutputStreamWriter
read() write()
使用InputStreamReader读取GBK编码文件时, 需要指定编码为GBK
使用OutputStreamWriter将读取到的字符, 按照UTF-8写入到UTF-8编码文件
边读边写类似于复制文件
释放资源
代码:
public
class
Test
{
public
static
void
main
(
String
[]
args
)
throws
IOException
{
// 创建转换输入流对象, 指向GBK文件, 同时指定按照GBK来读取
InputStreamReader
isr
=
new
InputStreamReader
(
new
FileInputStream
(
"day10\\我是GBK.txt"
),
"GBK"
);
// 创建转换输出流对象, 路径填写utf8文件, 同时指定按照UTF-8来写
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
new
FileOutputStream
(
"day10\\我是UTF8文件.txt"
),
"UTF-8"
);
// 循环读写: 类似于文件复制, 一次读写一个字符
int
ch
;
while
((
ch
=
isr
.
read
())
!=
-
1
) {
// 读到一个写一个
osw
.
write
(
ch
);
}
// 刷新缓冲区并释放资源
osw
.
close
();
isr
.
close
();
}
}
对象序列化流: ObjectOutputStream
java.io.ObjectOutputStream类: 对象字节输出流
// 构造方法
ObjectOutputStream(OutputStream out)
// 特有成员方法
void writeObject(Object obj): 将对象写出
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18);
oos.writeObject(s);
// 释放资源
oos.close();
注意:
被读写的对象的类必须实现"
java.io.Serializable
"接口, 否则会抛出"
NotSerializableException"
对象反序列化流: ObjectInputStream
java
.
io
.
ObjectInputStream类
:
对象字节输入流
// 构造方法
ObjectInputStream
(
InputStream
in
)
// 特有成员方法
Object
readObject
():
读取对象
// 创建对象输入流
ObjectInputStream
oos
=
new
ObjectInputStream
(
new
FileInputStream
(
"student.txt"
));
// 读对象
Object
o
=
oos
.
readObject
();
Student
s
=
(
Student
)
o
;
System
.
out
.
println
(
s
);
// 释放资源
oos
.
close
();
transient瞬态关键字: 避免属性序列化
static 修饰的成员变量属于类不属于对象, 所以不能序列化
transient 修饰的成员变量, 不能被序列化
transient 应用场景:
如果对象的某个属性不希望被序列化, 可以使用 transient 修饰, 这样就不会被对象流写到文件中
InvalidClassException异常: 原因和解决方案
serialVersionUID序列号的作用:
序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会
发生变化
当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException
为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是
一样的
打印流PrintStream: 概述和使用
PrintStream特点
:
1.
只有输出流
,
没有输入流
2.
PrintStream不会抛出IOException
3.
有特殊方法
print
(),
println
(),
可以输出任意类型的值
,
原样输出
java
.
io
.
PrintStream类
:
字节打印流
// 构造方法
PrintStream
(
File
file
):
创建字节打印流
,
输出到一个文件
PrintStream
(
OutputStream
out
):
创建字节打印流
,
输出到一个字节输出流
PrintStream
(
String
fileName
):
创建字节打印流
,
输出到一个文件路径
注意事项
:
如果用
write
(
97
)
方法
,
会查编码表
97
->
a
如果用
print
(
97
),
println
(
97
),
则原样输出
97
int
->
'9''7'
->
byte
->
文件
97
System
.
out
.
println
();
PrintStream
out
;
java
.
lang
.
System类
:
// 静态方法
static
void
setOut
(
PrintStream
out
):
设置System
.
out的输出
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2