IO流的学习
|-- File对象(已学)
|-- IO流的基本概念(已学)
|-- IO流的分类(已学)
|-- 字节流的基本使用(已学)
|-- 使用字节流完成文件的拷贝(已学)
|-- 装饰流(过滤流)的使用(已学)
|-- 数据流的使用
|-- 字符流的使用
|-- 转换流的使用
|-- 对象流以及Java的对象序列化
数据流的使用:
我们之前讲解的流,如果要保存数字,只要将数字转换为字符串,也就是说
以字符流的形式保存数据,这样有时候并不是我们需要的,我们有时候就是
需要以字节保存数据,因此就可以使用数据流来包装文件流完成。
上代码:
package com.openlab.day21.dataio;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.crypto.Data;
import org.junit.jupiter.api.Test;
class TestDateIO {
@Test
void test01() {
int num = 10000;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("a.dat");
// 保存数字到文件中,第一件事就是将数字转换为字符串
String temp = Integer.valueOf(num).toString();
// 字符串存在getBytes方法,可以将字符串转换为字节数组
byte[] bs = temp.getBytes();
fos.write(bs);
int num2 = 10000000;
// 自动类型转换
String temp2 = num2 + "";
fos.write(temp2.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
void test02() {
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream("a.dat"));
int num = 10000;
dos.writeInt(num);//int类型的字节数是4
long num2 = 10;
dos.writeLong(num2);//long类型的字节数是8
//所以将以上内容写入文件后的大小为12个字节
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
void test03() {
DataInputStream dis = null;
try {
//从文件当中读取数据是输入流
dis = new DataInputStream(new FileInputStream("a.dat"));
int num = dis.readInt();
System.out.println(num);
long num2 = dis.readLong();
System.out.println(num2);//要按着顺序读取
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流:
字符流就是以字符的形式传递数据的IO流
电脑中,所有的数据都可以以字节的形式传递
不是所有的数据都可以转换字符的!!!
|-- InputStrean 输入字节流
|-- OutputStream 输出字节流
字符流
|-- Reader
|-- Writer
注意:字符流是存在编码的!!!!
上代码:
package com.openlab.day21.dataio;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import org.junit.jupiter.api.Test;
class TestCharIO {
@Test
void test01() {
FileWriter fw = null;
try {
fw = new FileWriter("a.txt");
String msg = "韩嘉馨是个大美女";
fw.write(msg.toCharArray());//存的写进文件的时候需要将字符串转换为字符数组
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
void test02() {
FileReader fr = null;
try {
fr = new FileReader("a.txt");
char[] buf = new char[1024];
int len = -1;
while((len = fr.read(buf)) != -1) {
// 字符数组转换为字符串?
// String temp = new String(buf, 0, len);
String temp = String.valueOf(buf, 0, len);//很重要的一点要学会用这两种方法将字符数组转换为字符串
System.out.println(temp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
void test03() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("a.txt"));
String temp = null;
while((temp = br.readLine()) != null) {//字符流的装饰流的优越性在于可以按行读取数据
System.out.println(temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
void test04() {
BufferedReader br = null;
try {
// 如果读取的数据,和代码的编码并不一致的情况下,需要指定对应的编码
br = new BufferedReader(new FileReader("G:\\a.txt",Charset.forName("gbk")));
String temp = null;
while((temp = br.readLine()) != null) {
System.out.println(temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
void test05() {
String msg = "邹海清是个大帅锅";
Writer out = null;
try {
out = new FileWriter(new File("aa.txt"));
out.write(msg);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void test06() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("aa.txt"));
String s = null;
while((s = br.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void test07() {
BufferedWriter bw = null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("I:\\java\\java_se\\2021\\day20\\src\\com\\openlab\\day20\\io\\TesFile02.java"));
bw = new BufferedWriter(new FileWriter("c:\\a.java"));
String s = null;
// br.readLine() 每遇到一个\n,就认为以一行
while((s = br.readLine()) != null) {
// bw.write(s + "\n");
bw.write(s);
bw.newLine();
}
System.out.println("文件拷贝成功!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void test08() {
PrintWriter out = null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("I:\\java\\java_se\\2021\\day20\\src\\com\\openlab\\day20\\io\\TesFile02.java"));
out = new PrintWriter("c:\\a.java");
String s = null;
while((s = br.readLine()) != null) {
out.println(s);
}
System.out.println("文件拷贝成功!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
}
}
}
转换流:
能够实现字节流和字符流之间的转换
字符串对象:能够转换为字节数组或者字符数组
|-- InputStreamReader:将字节流转换为字符流操作
一个字节流,如果可以转换为字符流,一般建议转换字符流操作,类似于BufferedReader
readLine()方法,非常方便操作字符流
但是需要注意两个问题:
1、字符流存在着编码问题!!!
2、有些字节是无法转换为字符流的(如图片、视频等流媒体文件)
|-- OutputStreamWriter:
将字符流转换为字节流输出,好处就是可以使用字符流的好用的方法来处理字节流
上代码:
package com.openlab.day21.dataio;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import org.junit.jupiter.api.Test;
public class TestChangeIO {
@Test
void test01() {
BufferedReader br = null;
try {
// 一个字节流,如果可以转换为字符流,一般建议转换字符流操作,类似于BufferedReader
// readLine()方法,非常方便操作字符流
br = new BufferedReader(new InputStreamReader(System.in, Charset.forName("utf-8")));
String s = null;
while((s = br.readLine()) != null) {
String ss = s.replaceAll("吗?", "!");
System.out.println(ss);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void test02() {
BufferedReader br = null;
OutputStreamWriter out = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
out = new OutputStreamWriter(new FileOutputStream("g:\\a.html"));
String s = null;
while((s = br.readLine()) != null) {
if (s.trim().equalsIgnoreCase("exit")) {
break;
}
out.write(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对象流:
|-- ObjectInputStream
对象输入流,从磁盘等保存介质中读取已经保存的对象数据
|-- ObjectOutputStream
将对象转换为数据,保存起来
发现了问题:
只能保存系统提供一些类的对象(如包装类、字符串等类)
原因:java中要保存对象,该对象的类必须实现序列化接口!!!!
在java中,如果要保存对象,必须序列化该对象!!!
上代码:
@Test
void test01() {
// String msg = "刘建宏是个大帅锅";
// int msg = 120215;
Long msg = 123456L;
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("g:\\a.dat"));
oos.writeObject(msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
void test02() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("g:\\a.dat"));
Object o = ois.readObject();
System.out.println(o);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对象序列化:
序列化(串行化):将程序中的对象这种逻辑概念通过特定方式做成字节(字符)数据,以方便与保存或者传输
@Test
void test03() {
User user = new User("张三", "123456", "法外狂徒", 23);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("g:\\user.dat"));
oos.writeObject(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
反序列化:将序列化后的数据重新还原为抽象的对象
@Test
void test04() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("g:\\user.dat"));
User user = (User) ois.readObject();
System.out.println(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对象持久化:
将对象放到文件里保存起来
transient关键字:
该关键字是用来修饰属性,一旦某个属性被这个关键字修饰,
则该属性不会进行持久化,也就是该值不会保存!!!