目录
一、缓冲流
1.概述
缓冲流,也叫高效流,是对4个基本的FileXxx
流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流:
BufferedInputStream
,BufferedOutputStream
- 字符缓冲流:
BufferedReader
,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
2.字节缓冲流
1) 构造方法
public BufferedInputStream(InputStream in)
:创建一个 新的缓冲输入流。public BufferedOutputStream(OutputStream out)
: 创建一个新的缓冲输出流。
构造举例,代码如下:
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
字节缓冲输入流:
public class Demo015IO {
public static void main(String[] args)throws Exception {
File file = new File("aaa.txt");
InputStream is = new FileInputStream(file);
//BufferedInputStream方法中传入的是InputStream
BufferedInputStream bis = new BufferedInputStream(is);
byte[] bs = new byte[1024];
int len ;
while((len=bis.read(bs))!=-1){
System.out.println(new String(bs,0,len,"UTF-8"));
}
bis.close();
is.close();
}
}
2)效率测试
节点流慢,缓冲流快!
public class BufferedDemo {
public static void main(String[] args) throws FileNotFoundException {
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
){
// 读写数据
int len;
byte[] bytes = new byte[8*1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
}
} catch (IOException e) {
e.printStackTrace();
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
}
}
缓冲流使用数组复制时间:666 毫秒
3.字符缓冲流
1)构造方法
public BufferedReader(Reader in)
:创建一个 新的缓冲输入流。public BufferedWriter(Writer out)
: 创建一个新的缓冲输出流。
构造举例,代码如下:
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
2)特有方法
字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。
- BufferedReader:
public String readLine()
: 读一行文字。 - BufferedWriter:
public void newLine()
: 写一行行分隔符,由系统属性定义符号。
字符缓冲输入流:
/**
* 字符缓冲流 BufferedRerader
*/
public class Demo016IO {
public static void main(String[] args) throws Exception {
File file = new File("aaa.txt");
Reader r = new FileReader(file);
BufferedReader br = new BufferedReader(r);
String str;
//readline 读一行
while((str = br.readLine())!=null){
System.out.println(str);
}
br.close();
r.close();
}
}
字符缓冲输出流:
/**
* 写出去
*/
public class Demo017IO {
public static void main(String[] args) throws Exception{
File file = new File("suibian.txt");
Writer w = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(w);
bw.write("随便写,不用敲,好开心");
bw.newLine();
bw.flush();
bw.close();
w.close();
}
}
二、转换流
1.字符编码和字符集
按照某种规则,将字符存储到计算机中,称为编码 。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码 。当编码和解码所用的字符集不同时,就会发生乱码!
2.常见字符集
3.InputStreamReader类
1)构造方法
InputStreamReader(InputStream in)
: 创建一个使用默认字符集的字符流。InputStreamReader(InputStream in, String charsetName)
: 创建一个指定字符集的字符流。
构造举例,代码如下:
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");
2)指定编码读取
public class ReaderDemo2 {
public static void main(String[] args) throws IOException {
// 定义文件路径,文件为gbk编码
String FileName = "E:\\file_gbk.txt";
// 创建流对象,默认UTF8编码
InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));
// 创建流对象,指定GBK编码
InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");
// 定义变量,保存字符
int read;
// 使用默认编码字符流读取,乱码
while ((read = isr.read()) != -1) {
System.out.print((char)read); // ��Һ�
}
isr.close();
// 使用指定编码字符流读取,正常解析
while ((read = isr2.read()) != -1) {
System.out.print((char)read);// 大家好
}
isr2.close();
}
}
4.OutputStreamWriter类
1)构造方法
OutputStreamWriter(OutputStream in)
: 创建一个使用默认字符集的字符流。OutputStreamWriter(OutputStream in, String charsetName)
: 创建一个指定字符集的字符流。
构造举例,代码如下:
OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("out.txt"));
OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("out.txt") , "GBK");
2)指定编码写出
public class OutputDemo {
public static void main(String[] args) throws IOException {
// 定义文件路径
String FileName = "E:\\out.txt";
// 创建流对象,默认UTF8编码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName));
// 写出数据
osw.write("你好"); // 保存为6个字节
osw.close();
// 定义文件路径
String FileName2 = "E:\\out2.txt";
// 创建流对象,指定GBK编码
OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK");
// 写出数据
osw2.write("你好");// 保存为4个字节
osw2.close();
}
}
三、数据处理流
可以处理基本类型+String,保留数据的类型。前提是读取顺序与写出顺序一致,否则读取数据不正确
/**
* 放入一个int类型的1到文件中
*/
public class DataIOStream {
public static void main(String[] args)throws Exception {
int i = 980;
// 文件
File file = new File("F:\\输入输出流\\data.txt");
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
// 写出一个整数
dos.writeInt(i);// ?
dos.flush();
dos.close();
//读
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int a = dis.readInt();
System.out.println(a*2);//1960
dis.close();
}
}
四、序列化
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据
、对象的类型
和对象中存储的属性
等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。
1.ObjectOutputStream类
1)构造方法
public ObjectOutputStream(OutputStream out)
: 创建一个指定OutputStream的ObjectOutputStream。
FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
2)序列化操作
- 一个对象要想序列化,必须满足两个条件:
- 该类必须实现
java.io.Serializable
接口,Serializable
是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException
。 - 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用
transient
关键字修饰。
2.ObjectInputStream类
1)构造方法
public ObjectInputStream(InputStream in)
: 创建一个指定InputStream的ObjectInputStream。
代码演示:
public class Person implements Serializable {
private String name;
private int age;
private boolean gender;
public Person() {
}
public Person(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
序列化与反序列化:
public class PersonSerializable {
public static void main(String[] args)throws Exception {
// 对象
Person p = new Person("张三",20,true);
// 文件
File file = new File("F:\\输入输出流\\objFile.txt");
// 原始的输出流
OutputStream os = new FileOutputStream(file);
// 处理流 序列化
ObjectOutputStream ots = new ObjectOutputStream(os);
ots.writeObject(p);//输出的是看不懂的东西,但程序能看懂
ots.flush();
ots.close();
os.close();
//读 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object obj = ois.readObject();
System.out.println(obj);//Person{name='张三', age=20, gender=true}
ois.close();
}
}