01.第一章:缓冲流_概述
1).我们之前使用字节/字符的基本流时,使用数组的方式比较快。
2).基于这种原因,Java类库中提供了一种“缓冲流”类,它们内部自动带了“数组”,而且自动向数组中读、写数据,这种流:叫:缓冲流。由于它内部带了数组,所以可以大大提高程序的读写效率。它们内部的“数组”就叫:缓存区。
3).缓冲流的类结构:
A).字节流:
1).输出流:OutputStream(三种输出的方法)
|–FileOutputStream(基本流) 读取速度慢
|–FilterOutputStream(不学)
|–BufferedOutputStream(缓冲流–今天学)
2).输入流:InputStream(两种读取的方法)
|–FileInputStream(基本流) 读取速度慢
|–FilterInputStream(不学)
|–BufferedInputStream("缓冲流–今天学)
B).字符流:
1).输出流:Writer(五种输出的方法)
|–OutputStreamWriter(转换流–今天学) 可以指定字符集
|–FileWriter(基本流) 读取速度慢,且不能指定编码方式
|–BufferedWriter(缓冲流–今天学)
2).输入流:Reader(两种读取的方法)
|–InputStreamReader(转换流–今天学) 可以指定字符集
|–FileReader(基本流) 读取速度慢,且不能指定编码方式
|–BufferedReader(缓冲流–今天学)
注意:
1).缓冲流的前缀都带:Buffered
2).缓冲流基本没有特有方法,都是从父类继承/重写的。只是他们内部的工作方式不同,可以提供”缓存区”来提高程序的读写效率。
02.第一章:缓冲流_字节缓冲流
1).输出流:BufferedOutputStream
2).输入流:BufferedInputStream
无特有方法,跟基本流一样操作,就是:效率高。
public class Demo {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// copy1();//3509 毫秒(缓冲流--一次读写一个字节)
// copy2();//280 毫秒(缓冲流--一次读写一个字节数组)
// copy3();//361061 毫秒(基本流--一次读写一个字节)
copy4();//875 毫秒(基本流--一次读写一个字节数组)
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start) + " 毫秒");
}
private static void copy4() {
try (FileInputStream in = new FileInputStream("d:\\视频.itcast");
FileOutputStream out = new FileOutputStream("d:\\视频_copy3.itcast")
) {
//一次读写一个字节数组
int len = 0;
byte[] byteArray = new byte[1024];
while ((len = in.read(byteArray)) != -1) {
out.write(byteArray,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy3() {
try (FileInputStream in = new FileInputStream("d:\\视频.itcast");
FileOutputStream out = new FileOutputStream("d:\\视频_copy3.itcast")
) {
//一次读写一个字节
int b = 0;
while ((b = in.read()) != -1) {
out.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy2() {
//1.构造一个输入流
try (BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\视频.itcast"));
BufferedOutputStream bufOut = new BufferedOutputStream(
new FileOutputStream("d:\\视频_copy2.itcast"))
) {
//一次读写一个字节数组
int len = 0;
byte[] byteArray = new byte[1024];
while ((len = bufIn.read(byteArray)) != -1) {
bufOut.write(byteArray,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copy1() {
//1.构造一个输入流
try (BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\视频.itcast"));
BufferedOutputStream bufOut = new BufferedOutputStream(
new FileOutputStream("d:\\视频_copy1.itcast"))
) {
//一次读写一个字节
int b = 0;
while ((b = bufIn.read()) != -1) {
bufOut.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
03.第一章:缓冲流_字符缓冲流
1).输出流:BufferedWriter
特有方法:newLine():输出一个换行符“\r\n”;
2).输入流:BufferedReader
特有方法:readLine():读取一行数据。
3).示例代码:
public class Demo {
public static void main(String[] args) {
//1.字符缓冲输入流
try (BufferedReader bufIn = new BufferedReader(
new FileReader("d:\\demo01.txt"));
BufferedWriter bufOut = new BufferedWriter(
new FileWriter("d:\\demo01_copy.txt"))
) {
//一次读一行
String row = null;
while((row = bufIn.readLine()) != null){//注意:读取一行,不包括换行符
bufOut.write(row);
bufOut.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
04.第一章:缓冲流_练习_文本排序_案例分析
05.第一章:缓冲流_练习_文本排序_案例实现
public class Demo {
public static void main(String[] args) {
//1.构造一个输入流--按行读--字符缓冲输入流
try (BufferedReader bufIn = new BufferedReader(new FileReader("demo01.txt"));
BufferedWriter bufOut = new BufferedWriter(new FileWriter("demo01_copy.txt"))
) {
//一次读写一行
String row = null;
Map<Integer, String> map = new HashMap<>();
while ((row = bufIn.readLine()) != null) {//row = 3.xxxxxx
String id = row.substring(0, row.indexOf("."));
String str = row.substring(row.indexOf(".") + 1);
map.put(Integer.parseInt(id), str);
}
//循环写入
for (int i = 1; i <=9 ; i++) {
String str = map.get(i);//xxxxx
str = i + "." + str;//1.xxxxx
bufOut.write(str);
bufOut.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
06.第二章:转换流_编码引出的问题
1).如果磁盘上有一个GBK编码的文件,我们使用程序用UTF-8编码读取,这样就会产生:乱码的现象。
2).FileWriter和FileReader不能指定编码方式,固定用系统默认的(UTF-8)读取,很不灵活。
3).它们的父类提供了指定编码的方式:
Writer |--OutputStreamWriter(转换流)(可以指定字符集) 父类 |--FileWriter(子类)(只能使用系统默认字符集) Reader |--InputStreamReader(转换流)(可以指定字符集) 父类 |--FileReader(子类)(只能使用系统默认字符集)
07.第二章:转换流_转换输出流OutputStreamWriter的使用
public class Demo {
public static void main(String[] args) {
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("demo04.txt"),"GBK")) {
osw.write("你好");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
08.第二章:转换流_转换输入流InputStreamReader的使用
public class Demo {
public static void main(String[] args) {
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("demo04.txt"),"GBK")) {
int c = 0;
while ((c = isr.read()) != -1) {
System.out.println((char)c);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
09.第二章:转换流_练习_转换文件编码
1).复制一个GBK的文件,新文件要求是:UTF-8编码的。
2).代码:
public class Demo {
public static void main(String[] args) {
//1.构造一个输入流--由于要指定GBK读取,所以使用:转换流
//2.构造一个输出流,使用UTF-8编码
try (InputStreamReader in = new InputStreamReader(
new FileInputStream("demo05.txt"),"GBK");
OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo05_UTF8.txt"),"UTF-8")
) {
//一次读取一个字符
int c = 0;
while ((c = in.read()) != -1) {//按GBK读取的
out.write(c);//按UTF-8输出
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
10.第三章:序列化_概述
1).什么是“序列化”:指将一个内存中的“对象”,连同“属性值”一起存储到文件中。
2).什么是“反序列化”:指将之前序列化的对象,从文件中再读取进来,并在内存中再次创建对象。
11.第三章:序列化_序列化流ObjectOutputStream类
public class Student implements Serializable{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo {
public static void main(String[] args) {
//创建一个序列化流对象
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo07_obj.txt"))) {
Student stu = new Student("成龙", 17);
//序列化对象
oos.writeObject(stu);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
12.第三章:序列化_反序列化ObjectInputStream类
public class Demo {
public static void main(String[] args) {
//1.创建一个反序列化对象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo07_obj.txt"))) {
//读取对象
Object obj = ois.readObject();//在内存中创建一个Student对象
//强转
Student stu = (Student)obj;
System.out.println(stu);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
13.第三章:序列化_关于版本号
public class Student implements Serializable{
public String name;
public int age;
private static final long serialVersionUID = 2L;
}
14.第三章:序列化_禁止属性被序列化transient关键字
1).如果类中的某个属性不希望被序列化,可以被声明为:transient
2).示例:
public class Student implements Serializable{
public String name;
public transient int age;//当序列化Student对象时,此属性的值不会被序列化到文件中
}
15.第三章:序列化_练习_序列化集合
1).不建议一个文件中序列化多个对象。可以将多个对象存储到一个List集合中,然后将这个集合对象序列化到文件中。
2).序列化:
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("成龙", 17);
Student stu2 = new Student("甄子丹", 15);
Student stu3 = new Student("洪金宝", 19);
ArrayList<Student> stuList = new ArrayList<>();
stuList.add(stu1);
stuList.add(stu2);
stuList.add(stu3);
//序列化
try (ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("demo10_obj.txt"))) {
//序列化集合
out.writeObject(stuList);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3).反序列化:
public class Demo02 {
public static void main(String[] args) {
try (ObjectInputStream objIn = new ObjectInputStream(
new FileInputStream("demo10_obj.txt"))) {
//反序列化
Object obj = objIn.readObject();
List<Student> stuList = (List<Student>)obj;
//验证
for (Student stu : stuList) {
System.out.println(stu);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
16.第四章:打印流_概述
1).打印流:
1).字节打印流:PrintStream
2).字符打印流:PrintWriter
2).特点:
1).只有输出流,没有输入流;
2).可以向控制台打印,也可以向文件中打印
17.第四章:打印流_字节打印流PrintStream类
public class Demo {
public static void main(String[] args) {
PrintStream ps = System.out;
ps.println("HelloWorld!");
//改变它的方向
try (PrintStream ps2 = new PrintStream("demo11.txt")) {
//将ps2赋值到System中,代替之前的out
System.setOut(ps2);
//再打印
System.out.println("我爱");
System.out.println("Java");
System.out.println("呵呵");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
=============================================================
学习目标总结:
01.能够使用字节缓冲流读取数据到程序
02.能够使用字节缓冲流写出数据到文件
03.能够明确字符缓冲流的作用和基本用法
04.能够使用缓冲流的特殊功能
05.能够阐述编码表的意义
1).编码表中存储的各国的“文字”和“十进制数字”的映射关系。目的存储这个文字时,
要存储它对应的十进制的二进制表示方式。
ASCII:a --> 97 --> 计算机:97的二进制
b --> 98 --> 计算机:98的二进制
GBK:"你" --> 50403 --> 计算机:50403的二进制
06.能够使用转换流读取指定编码的文本文件
07.能够使用转换流写入指定编码的文本文件
08.能够使用序列化流写出对象到文件
09.能够使用反序列化流读取文件到程序中