缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的(8k)缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
1.字节缓冲流:
1).输出流:OutputStream
|--FileOutputStream(基本流)
|--FilterOutputStream
|--BufferedOutputStream(缓冲流)
2).输入流:InputStream
|--FileInputStream(基本流)
|--FilterInputStream
|--BufferedInputStream(缓冲流)
3).构造方法:
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream对象,参数是一个输入流。InputStream是抽象
类,可以用子类对象
BufferedInputStream(Outputstream out) 创建一个 BufferedInputStream对象,参数是一个输出流。Outputstream是抽
象类,可以用子类对象
4).代码示例:
BufferedInputStream bin = new BufferedInputStream(new FileInputStream("demo.txt"));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("demo.txt"));
2.字符缓冲流:
1).输出流:Writer
|--OutputStreamWriter(转换流)
|--FileWriter(基本流)
|--BufferedWriter(缓冲流)
(特有方法:newLine():输出一个换行符)
2).输入流:Reader
|--InputStreamReader(转换流)
|--FileReader(基本流)
|--BufferedReader(缓冲流)
(特有方法:readLine():读取一行数据)转换流
3).构造方法:
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的 缓冲字符输入流。
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
4).代码示例:
BufferedReader bin = new BufferedReader(new FileReader("demo.txt"));
BufferedWriter bout = new BufferedWriter(new FileWriter("demo.txt"));
3.缓冲流的使用_案例_文本排序:
public static void main(String[] args) throws IOException {
//创建输入输出的缓冲流
BufferedReader bin = new BufferedReader(new FileReader("sort.txt"));
BufferedWriter bout = new BufferedWriter(new
FileWriter("sort_allright.txt"));
//Map存放序号和对应的句子
Map stringMap = new LinkedHashMap<>();
//用缓冲流的特有方法,一次读写一行
String s = null ;
while ((s = bin.readLine()) != null) {
//分割字符串
String[] arr = s.split("\\.");
stringMap.put(Integer.parseInt(arr[0]), arr[1]);
}
//按照序号遍历Map中的内容并写出
for (int i = 1; i < stringMap.size(); i++) {
bout.write(i + "." + stringMap.get(i));
bout.newLine();
}
//关闭资源
bin.close();
bout.close();
}
1.字符编码和字符集:
字符编码:
就是一套自然语言的字符与二进制数之间的对应规则。
计算机是以二进制存储,按照某种规则,将字符存储到计算机中,称为编码 。
将存储在计算机中的二进制数,按照某种规则解析显示出来,称为解码
字符集:
常见的字符集(编码表):记录了字符和数字的映射关系。当计算机存储“字符”时,实际存储的是这个字符对应的数字的二进制。
1.ASCII码表:最早的码表。记录了128个字符,每个字符使用1个字节表示。
2.中文的码表(GBxxxx)
1).GB2312:早期的码表,里面一共记录了7000多个汉字;现在已经不使用了。
2).GBK : 目前使用的码表。里面一共记录了2万多个汉字,每个汉字使用2个字节表示;
3).GB18030 : 未来要使用的码表。7万多汉字。每个汉字使用1,2,3个字节表示;
3.UTF-8码表:国际码表。有中文;字符采用1,2,3,4字节表示。每个中文使用:3个字节表示;
4.Unicode码表:国际码表,有中文(3,4千),每个字符使用2个字节表示。Java就是支持Unicode码表的。
5.ISO-8859-1码表:没有中文。
编码引出的问题:
乱码—解码与编码不一致
例如:Windows中文系统中就是使用的GBK的编码,在IDEA中默认的字符集是UTF-8,两种编码中汉字占用的字节数不同,(UTF-8占用三个字节)读取时就会出现乱码 解决:读取时将编码转换成一致
2.转换输出流和转换输入流:
1).转换输出流:
构造方法:
OutputStreamWriter(OutputStream in) : 创建一个用默认字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream("demo.txt"));
OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("demo.txt"),"GBK");
}
2).转换输入流:
构造方法:
InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流。
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
InputStreamReader in1 = new InputStreamReader(new FileInputStream("demo.txt"));
InputStreamReader in2 = new InputStreamReader(new FileInputStream("demo.txt"),"GBk");
}
3.转换输入输出流使用:
IDEA默认的字符集是UTF-8,Windows默认的是GBK,为了避免乱码,使用GBK读取文档,然后用UTF-8输出
public static void main(String[] args) throws IOException {
//创建指定字符集转换输出输入流,
InputStreamReader in = new InputStreamReader(
new FileInputStream("demo.txt"),"GBK");
OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo_copy.txt"),"UTF-8");
//按照字符读取
int b = 0;
while ((b = in.read()) != -1) {
out.write(b);
}
out.close();
in.close();
}
如果读取的输出的编码不一致就会乱码
序列化:
指将一个“对象连同属性值”一起存储在一个文件中,或者通过网络传输,这个过程叫:序列化。
反序列化;
指将之前序列化的对象,再次读取到程序中,并在内存中创建对象。
1.序列化流ObjectOutputStream类;
构造方法:
public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream。
注意:被序列化的对象必须实现:java.io.Serializable(接口)
此接口无任何抽象方法,这种接口叫:标记接口,表示开启了某些功能。
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_Student.txt"));
out.writeObject(new Student(1,"张三","男",23));
out.close();
}
2.反序列化ObjectInputStream类:
构造方法:
public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream。
注意:接收的Student必须是之前“序列化时”的那个包下的Student类型,不能是其它包下的,否则运行时异常。它必须是能够找到class文件的类
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_Student.txt"));
//返回Object类型
Student stu = (Student) in.readObject();
System.out.println(stu);
in.close();
}
3.版本号:
Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
例如:private static final long serialVersionUID = 2;
如果没有给定序列号,如果修改了序列化的类,再次反序列化的时候(没有再次序列化)就会抛异常,因为序列号不一样了,如果给定了序列号,则不会抛异常
4.禁止属性被序列化transient关键字
用transient关键字修饰属性,在序列化时该苏醒不会被序列化
当一个属性被transient修饰,反序列化出来的值时属性的默认值
1 张三 男 0//年龄属性被禁止序列化,输出为0
5.序列化的使用_序列化集合:
public static void main(String[] args) throws IOException, ClassNotFoundException {
//创建序列化的集合并初始化数据
ArrayList stuList = new ArrayList<>();
stuList.add(new Student(1,"张三","男",19));
stuList.add(new Student(2,"张四","女",20));
stuList.add(new Student(3,"张五","男",21));
stuList.add(new Student(4,"张六","女",22));
//创建序列化输出流和反序列化输入流
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("demo_xuliehuajihe.txt"));
ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo_xuliehuajihe.txt"));
//序列化集合
out.writeObject(stuList);
//关闭资源
out.close();
//反序列化集合,并接受返回的集合
ArrayList studentList = (ArrayList) in.readObject();
//遍历输出反序列化返回的数据
for (Student student : studentList) {
System.out.println(student);
}
in.close();
}
1.字节打印流PrintStream类
构造方法:
public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。
2.改变打印流的方向:
System.out.println():向控制台输出数据,System.out就是:PrintStream类型;默认被指向:控制台,想改变打印的方向,改变这个out就行
注意:
Out是System类的一个成员属性,所以可以用get/set方法访问
输出方法和控制台一样
使用示例:
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("demo.txt");
System.setOut(ps);
System.out.println("呵呵");
}