01.第一章:缓冲流_概述

1).什么是缓冲流:之前使用字节流的两个基本流:FileOutputStreamFileInputStream,以及字符流的两个流:

   FileWriterFileReader,在使用它们时,一次读、写一个字节数组/字符数组的形式非常快。我们用的字节数组/字符数组

   就相当于一个缓存区

2).由于这种方式非常快,所以Java类库中也提供了一种缓冲流”--这些缓冲流内部自带一个缓存区--byte/char数组

   用这些流可以提高我们的读、写效率。

3).这些缓冲流基本上没有增加任何的方法,仍然是使用我们学过的方法,只是它们内部的工作方式不一样。

02.第一章:缓冲流_字节缓冲流【两个】

字节流:

A).输出流:OutputStream

|--FileOutputStream(子类)

|--FilterOutputStream(不学)

|--BufferedOutputStream(字节缓冲流)
B).输入流:InputStream

|--FileInputStream(子类)

|--FilterInputStream(不学)

|--BufferedInputStream(字节缓冲流)

注:这两个缓冲流没有增加任何方法,仍然使用父类的方法,只是内部的工作方式不同。

IO流学习总结_java

 

03.第一章:缓冲流_字符缓冲流【两个】

字符流:

A).输出流:Writer

|--OutputStreamWriter(转换流--今天讲)

|--FileWriter(子类--基本流)

|--BufferedWriter(缓冲流)

新增特有方法:newLine():输出一个换行符(\r\n)

B).输入流:Reader

|--InputStreamReader(转换流--今天讲)

|--FileReader(子类--基本流)

|--BufferedReader(缓冲流)

新增特有方法:readLine():读取一行。【不读取换行符】

public class Demo {
public static void main(String[] args) {
try (BufferedReader bufIn = new BufferedReader(new FileReader("demo02.txt"));
BufferedWriter bufOut = new BufferedWriter(new FileWriter("demo02_copy_2.txt"))
) {
//1.一次读写一个字符
/*int c = 0;
while ((c = bufIn.read()) != -1) {//从缓存区读
bufOut.write(c);//写入缓存区
}*/

//2.一次读写一个字符数组
/*char[] chArray = new char[512];
int len = 0;
while ((len = bufIn.read(chArray)) != -1) {//从缓存区读
bufOut.write(chArray,0,len);//写入缓存区
}*/

//3.一次读写一行
String row = null;
while((row = bufIn.readLine()) != null){//从缓存区读
bufOut.write(row);//写入缓存区
bufOut.newLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

04.第一章:缓冲流_练习_文本排序_案例分析

1).读取出师表_.txt”--按行读--BufferedReader://3.侍中、侍郎郭攸之.....

2).解析读取的行,解析为两部分:第一部分:3,第二部分:内容:侍中、侍郎郭攸之.....

3).for(int i = 1 ; i <= 9 ; i++){

String str = map.get(i);//i作键,取内容

out.write(i + "." + str);//1.xxxx
   }

05.第一章:缓冲流_练习_文本排序_案例实现

public class Demo {
public static void main(String[] args) {
try (BufferedReader bufIn = new BufferedReader(new FileReader("出师表_源.txt"));
BufferedWriter bufOut = new BufferedWriter(new FileWriter("出师表_复制.txt"))
) {

//定义一个Map
Map<Integer, String> map = new HashMap<>();
//一次读取一行
String row = null;
while ((row = bufIn.readLine()) != null) {//row = 3.侍中、侍郎郭攸之.....
//解析row
Integer id = Integer.valueOf(row.substring(0, 1));//id = 3
String str = row.substring(1);//str = ".侍中、侍郎郭攸之.....";
//存储到Map中
map.put(id, str);
}
//写个for循环
for (int i = 1; i <= 9 ; i++) {
//用i做键,到map中取值
String str = map.get(i);
//输出到文件
bufOut.write(i + str);
bufOut.newLine();
}
System.out.println("复制完毕!");

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

-------------------------------------------------------------

06.第二章:转换流_编码引出的问题

1).当磁盘上有一个“GBK”编码的文件时,如果我们用IDEA读取,由于IDEA默认编码方式为:UTF-8

    所以会导致读取到程序中的数据:乱码。

2).FileReaderFileWriter只能根据当前运行时环境(IDEA)的编码方式,不能灵活的更改为其它方式。

3).我们可以使用它们的父类:

1).字符输出流:Writer

   |--OutputStreamWriter(转换流)--可以指定编码表

API:从字符流到字节流的桥梁

     程序中:"你好"--> 编码表 --> 字节 --> 字节流 --> 文件

|--FileWriter(基本流)--只能使用默认编码表

2).字符输入流:

   |--InputStreamReader(转换流)--可以指定编码表

API:从字节流到字符流的桥梁

程序中:"你好"<-- 编码表 <-- 字节 <--字节流 <-- 文件

|--FileReader(基本流)--只能使用默认编码表

4).这两个转换流就可以指定某种编码方式来读、写文件。

07.第二章:转换流_转换输出流OutputStreamWriter的使用

public class Demo {
public static void main(String[] args) {
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("demo05_GBK.txt"),"GBK")) {
osw.write("你好");
} 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("demo05_GBK.txt"),"GBK")) {
int c = 0;
while ((c = isr.read()) != -1) {
System.out.println((char)c);
}
} 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读取
try (InputStreamReader in = new InputStreamReader(
new FileInputStream("demo06_GBK.txt"),"GBK");
//2.用UTF-8输出
OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo06_utf8.txt"),"UTF-8")
) {
int c = 0;
while ((c = in.read()) != -1) {
out.write(c);
}
System.out.println("转换完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}
}

------------------------------------------------------------

10.第三章:序列化_概述:

1).什么是序列化:将内存中的对象(包括:包名,类名)”连同属性名,值一起存储到一个文件中,这个过程叫:序列化。

2).什么是反序列化:将之前序列化的对象,再次的读取到内存中,并创建对象,为属性赋值,这个过程叫:反序列化。

11.第三章:序列化_序列化流ObjectOutputStream

1).注意:被序列化的类,必须实现:java.io.Serializable接口

2).示例代码:

public class Student implements Serializable {
String name;
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) {
Student stu = new Student("成龙", 17);

//序列化对象
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("demo08_obj.txt"))) {

oos.writeObject(stu);

System.out.println("完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}
}

12.第三章:序列化_反序列化ObjectInputStream

public class Demo {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("demo08_obj.txt"))) {



            Object o = ois.readObject();//1.从文件中读取包名" + "类名";2.到项目中找到那个包下的那个类;3.将这个类创建对象;4.参考类中的属性到文件中找对应的值,找到,就为成员属性赋值;
      

Student stu = (Student)o;
System.out.println(stu);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

13.第三章:序列化_关于版本号

1).任何一个被序列化的类,编译器都会隐式的添加一个变量:

   private static final long serialVersionUID = -6642906621147195767L;

2).序列化

3).修改Student类:

....

String address;//增加属性

4).编译器会自动的修改这个序列号:

      private static final long serialVersionUID = 8842906621147195767L;

5).反序列化:

1).比较两个序列号,发现不一致;抛出异常

----------------------------------------------------------------------------------------

建议:由程序员来维护这个序列号:

public class Student implements Serializable {
//自定义的序列号
private static final long serialVersionUID = 1L;

int stuAge;
String address;

public Student(int stuAge, String address) {
this.stuAge = stuAge;
this.address = address;
}

@Override
public String toString() {
return "Student{" +
"stuAge=" + stuAge +
", address='" + address + '\'' +
'}';
}
}

14.第三章:序列化_禁止属性被序列化transient关键字

1).如果某个属性不想被序列化,可以将这个成员属性修饰为:transient

public class Student implements Serializable {
String name;
transient int age;}

15.第三章:序列化_练习_序列化集合

1).不要在一个文件中同时序列化多个对象,如果要存储多个对象,可以将这个多个对象存储到一个集合中,

   然后将这个集合序列化到文件中。

ArrayList<Student> list = new ArrayList<>();

   要求

1).ArrayList必须实现Serializable接口;

2).Student必须实现Serializable接口;

3).Student中的引用类型的属性必须实现Serializable接口;

这样才可以成功的序列化一个ArrayList对象。

2).示例代码:

1).Student类:

public class Student implements Serializable{
private static final long serialVersionUID = 1;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void setAge(int age) {
this.age = age;
}
}

2).序列化测试类:

public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("成龙", 17);
Student stu2 = new Student("洪金宝", 19);
Student stu3 = new Student("甄子丹", 16);
ArrayList<Student> list = new ArrayList<>();
list.add(stu1);
list.add(stu2);
list.add(stu3);
try (ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("demo10.txt"))) {
out.writeObject(list);
System.out.println("序列化完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

3).反序列化测试类:

public class Demo02 {
public static void main(String[] args) {
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("demo10.txt"))) {
ArrayList<Student> stuList = (ArrayList<Student>)in.readObject();
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).Java提供了两个打印流:

1).字节打印流:PrintStream

2).字符打印流:PrintWriter

2).特点:

1).只有输出流,没有输入流;

2).可以向文件输出,也可以向控制台输出;

 

17.第四章:打印流_字节打印流PrintStream

public class Demo {
public static void main(String[] args) {
PrintStream out = System.out;
out.println("HelloWorld!");

//可以更改System.out对象为其它PrintWriter,使其向文件输出
try (PrintStream ps = new PrintStream("demo11.txt")) {

//将这个流赋值给System.out
System.setOut(ps);

//测试
System.out.println("呵呵,输出到文件了!");

//还原
System.setOut(out);
System.out.println("呵呵,我又回来了!");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

=============================================================