IO顶级父类

输入流 输出流
字节流 字节输入流InputStream 字节输出流OutputStream
字符流 字符输入流Reader 字符输出流Writer

第一章 字节流

1.1 字节输出流

  • java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写道目的地。其基本共性方法:

1.2 文件字节输出流

  • java.io.FileOutputStream 文件字节输出流。将内存中的数据写入到硬盘的文件中

构造方法

FileOutputStream(String name):创建一个向指定名称的文件中写入数据的输出文件流

FileOutputStream(File file):创建一个向指定File对象文件中写入数据的输出文件流

写出字节数据

  • public void write(byte[] b):将字节数组的内容写入文件

  • public void write(byte[] b,int off,int len):将字节数组从off位置开始的长度为len的内容写入文件

  • FileOutputStream(String name,boolean append) :创建一个向指定name的文件中写入数据的输出文件流,append为true时创建对象不会覆盖原文件,而是继续追加

  • FileOutputStream(File file,boolean append) :创建一个向指定File的文件中写入数据的输出文件流。

  • 写换行符

    Windows:\r\n;Linux:/n;Mac:/r

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) throws IOException {
FileOutputStream file = new FileOutputStream("hxx.txt",true);
file.write("\r\n".getBytes());//换行
file.write(98);//b
byte []bytes = {65,66,67};
file.write(bytes);//ABC
byte[] bytes1 = "你好".getBytes();
file.write(bytes1);//你好
file.write(bytes,1,2);//BC
file.close();
}

1.3 字节输入流

  • java.io.InputStream抽象类表示字节输入流所有类的超类,可以读取字节信息到内存中。
    • public void close():关闭此输入流并释放相关资源
    • public int read():从输入流读取数据的一个字节
    • public int read(byte[] b):从输入流中读取一些字节,并将它们存储在字节数组b中

1.4 文件字节输入流

  • java.io.FileOutputStream 文件字节输出流。将硬盘中的数据读取到内存中

构造方法

  • FileInputStream(String name):创建一个向指定名称的文件中读取数据的输入文件流

  • FileInputStream(File file):创建一个向指定File对象文件中读取数据的输入文件流

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("捕获.PNG");
FileOutputStream fos = new FileOutputStream("xin.PNG");
int len = 0;
while((len = fis.read())!=-1){
fos.write(len);//文件复制
}
fos.close();
fis.close();
}

第二章 字符流

2.1 字符输入流

  • java.io.Reader抽象类是读取字符流的所有类的超类
  • public void close():关闭此输入流并释放相关资源
  • public int read():从输入流读取一个字符
  • public int read(char[] b):从输入流中读取一些字符

2.2 FileReader类

  • FileReader(String name) 创建一个新的FileReader,给定要读取的File对象

  • FileReader(File file)

1
2
3
4
5
6
7
8
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("hxx.txt");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read())!= -1){
System.out.print((char)len);
}
}

2.3 字符输出流Writer

2.4 FileWriter类

1
2
3
4
5
6
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("hxx.txt",true);
fw.write("helloWorld");
fw.flush();
fw.close();
}

第三章 IO异常处理

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) { 
try(FileInputStream fis = new FileInputStream("捕获.PNG");
FileOutputStream fos = new FileOutputStream("xin.PNG");){ //try执行完后fis fos自动释放
int len = 0;
while((len = fis.read())!=-1){
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
}

第四章 属性集

  • java.io.Properties继承于Hashtable,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。

4.1 Properties类

构造方法

  • public Properties():创建一个空的属性列表

基本的存储方法

  • public Object setProperty(String key,String value):保存一对属性
  • public String getProperty(String):使用此属性列表中指定的键搜索属性值
  • public Set< String > stringPropertyName():所有键名称的集合
1
2
3
4
5
6
7
8
public static void main(String[] args) {
Properties pro = new Properties();
pro.setProperty("hxx","qzy");
Set<String> set = pro.stringPropertyNames();
for (String s : set) {
System.out.println(pro.getProperty(s));
}
}

Store

  • 可以使用Properties集合中的方法store,把集合中的临时数据持久化写入到硬盘中存储
  • void store(OutputStream out,String comments):不能写中文,comment是注释,说明保存的文件作用,不能使用中文,会产生乱码。一般使用空字符串
  • void store(Writer writer,String comments):能写中文

load

  • void load(InputStream instream):不能含有中文键值对
  • void loadFileReader reader):不能含有中文键值对
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws IOException {
Properties pro = new Properties();
pro.setProperty("hxx","qzy");
//创建字节输出流/字符输出流对象
FileWriter fw = new FileWriter("hxx.txt");
//使用Properties集合中的方法store,把集合中的临时数据写入目的地
pro.store(fw,"Save Data");
fw.close();

//新建字符输入流
FileReader reader = new FileReader("hxx.txt");
Properties pro2 = new Properties();
pro2.load(reader);
reader.close();
System.out.println(pro2);
}

第五章 缓冲流

5.1 字节缓冲流

  • public BufferedOutputStream(OutputStream out)

  • public BufferedOutputStream(OutputStream out,int size) :指定缓冲流内部缓冲区的大小

  • BufferedInputStream(InputStream in)

  • BufferedInputStream(InputStream in,int size)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("hxx.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("hxxqzy".getBytes());
bos.flush();//刷新将缓冲区的内容刷新到文件中
bos.close();

FileInputStream fis = new FileInputStream("hxx.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// int len = 0;
// while((len = bis.read())!= -1){
// System.out.print((char) len);
// }
byte[] bytes = new byte[1024];
int len2 = 0;//记录每次读取的有效字节个数
while((len2 = bis.read(bytes))!= -1){
System.out.print(new String(bytes,0,len2));
}
bis.close();
}

4.2 字符缓冲流

  • BufferedReader(Reader in)

  • BufferedReader:public String readLine():读一行文字

  • BufferedWriter(Writer out)

  • BufferedWriter:public void newLine():写一行行分隔符,由系统属性定义符号

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("hxx.txt",true));
bw.newLine();
bw.write("韩晓璇");
bw.close();
BufferedReader br = new BufferedReader(new FileReader("hxx.txt"));
String line;
while((line = br.readLine())!= null){
System.out.println(line);
}
br.close();
}

第五章 转换流

5.1 字符编码和字符集

字符编码

按照某种规则将字符存储到计算机中称之为编码

将存储在计算机中的二进制数据按照某种规则解析显示出来叫做解码

  • 字符编码:Character Encoding

字符集

  • 字符集(编码表):Charset 是一个系统支持的所有字符的集合,包括国家文字、标点符号等

5.2 InputStreamReader

  • java.io.InputStreamReader继承了Reader,是字节流通向字符流的桥梁,可使用指定的charset读取字节将其解码为字符。
  • InputStreamReader(InputStream in):使用默认字符编码
  • InputStreamReader(InputStream in,String charSetName):指定字符编码名称不区分大小写。

5.2 OutputStreamWriter

  • java.io.OutputStreamWriter继承了Writer,是字符流通向字节流的桥梁,可使用指定的charset将要写入流中的字符编码成字节。
  • OutputStreamWriter(OutputStream out):使用默认字符编码
  • OutputStreamWriter(OutputStream out,String charSetName):指定字符编码名称不区分大小写。
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hxx.txt"),"GBK");
osw.write("你好");
osw.flush();
osw.close();

InputStreamReader isr = new InputStreamReader(new FileInputStream("hxx.txt"),"gbk");
int len = 0;
while((len = isr.read())!=-1){
System.out.print((char) len);
}
isr.close();
}

第六章 序列化

  • java提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、类型和存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
  • 反之,该字节序列可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、类型和存储的属性等信息都可以用来在内存中创建对象。

6.1 ObjectOutputStream类

java.io.ObjectOutputStream类,将java对象的原始数据类型写出到文件,实现对象的持久存储

构造方法

  • public ObjectOutputStream(OutputStream out):创建一个指定OutputStream 的ObjectOutputStream。

序列化操作

  1. 一个对象需要序列化必须满足两个条件
    • 该类必须实现java.io.Serializable接口,Serializable是一个标记接口,不实现此接口的类将不会使任何状态序列化或者反序列化,会抛出NoSerializableException
    • 该类的所有属性必须使可序列化的。如果有一个属性不需要可序列化,则该属性必须注明是瞬态的,使用trasient关键字修饰
  2. void writeObject(Object obj):将指定的对象写入ObjectOutputStream
1
2
3
4
5
6
7
8
public class Person implements Serializable {
private String name;
}
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hxx.txt"));
oos.writeObject(new Person("hxx"));
oos.close();
}

6.2 ObjectInputStream类

  • ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原属数据恢复为对象

构造方法

  • public ObjectInputStream(IntputStream In)

反序列化操作1

  • 如果找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

    public final Object readObject()

1
2
3
4
5
6
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hxx.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
  • 静态优先于非静态加载到内存中(静态优先于对象进入到内存中),被static修饰的成员变量不能被序列化,序列化的都是对象。
  • transient关键字:瞬态关键字,所修饰的变量不能被序列化

反序列化操作2

当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化时也会失败,抛出InvalidClassException异常,产生这个异常的原因如下:

  • 该类的序列版本号和从流中读取的类描述符的版本号不匹配
  • 该类包含位置数据类型
  • 该类没有可访问的无参构造方法

Serializable接口给需要序列化的类提供了一个序列版本号。serialVersionUID该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

1
2
3
4
public class Person implements Serializable {
public static final long serialVersionUID = 1;
private String name;
}

第七章 打印流

PrintStream类

继承OutputStream类。

  • PrintStream(String fileName):使用指定的文件名创建一个新的打印流
  • PrintStream(OutputStream out)
  • PrintStream(File file)
1
2
3
4
5
6
7
8
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("hxx.txt");
ps.write(97);
ps.print("hxx");
System.setOut(ps);//改变打印流
System.out.println("qzy");
ps.close();
}