JavaIO流(三)
6.转换流
不同编码读取出现乱码的问题:
- 如果代码编码和被读取的文本文件编码是一致的,使用字符流读取文本时不会出现乱码
- 如果代码编码和被读取的文本文件编码是不一致的,使用字符流读取文本时就会出现乱码
InputStreamReader(字符输入转换流)
是Reader抽象类下的实现类
- 解决不同编码时,字符流读取文本内容乱码的问题
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
package com.IO.transform_stream;
import java.io.*;
public class InputStreamReaderTest02 {
public static void main(String[] args) {
try (
//1.得到文件的原始字节流(GBK 的字节流形式)
InputStream is = new FileInputStream("basic-grammar\\src\\yehuan09.txt");
//2.把原始的字节输入流按照指定的字符集编码转换成字符输入流
Reader isr = new InputStreamReader(is,"GBK");
//3.把字符输入流包装成缓冲字符输入流
BufferedReader br = new BufferedReader(isr);
){
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
OutputStreamWriter(字符输出转换流)(了解)
需要控制写出去的字符使用什么字符集编码,该咋整?
- 调用String提供的getBytes方法解决
String data = "我爱你中国abc";
byte[] bytes = data.getBytes("GBK");
- 使用字符输出转换流实现
- 作用:可以控制写出去的字符使用什么字符集编码。
- 解决思路:先获取文件字节输出流,再按照指定的字符集编码将其转成字符输出流,以后写出去的字符就会用该字符集编码了。
package com.IO.transform_stream;
import java.io.*;
public class OutputStreamWriterTest03 {
public static void main(String[] args) {
try (
OutputStream os = new FileOutputStream("basic-grammar\\src\\yehuan09out.txt");
Writer osw = new OutputStreamWriter(os,"GBK");
BufferedWriter bw = new BufferedWriter(osw);
){
bw.write("我是中国人abc");
bw.newLine();
bw.write("我是中国人123");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
7.打印流
PrintStream/PrintWriter(打印流)
PrintStream是字节输出流抽象类下的实现类
PrintWriter是字符输出流抽象类下的实现类
- 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
package com.IO.printstream;
import java.io.*;
import java.nio.charset.Charset;
public class PrintStreamTest01 {
public static void main(String[] args) {
try (
//1.创建一个打印流管道
//PrintStream ps = new PrintStream("basic-grammar\\src\\yehuan10.txt",Charset.forName("GBK"));
//PrintStream ps = new PrintStream("basic-grammar\\src\\yehuan10.txt");
//追加数据
PrintWriter ps = new PrintWriter(new FileOutputStream("basic-grammar\\src\\yehuan10.txt",true));
){
ps.println(100);
ps.println('a');
ps.println("中国");
ps.println(true);
ps.println(9.5);
ps.write(97);//'a'
} catch (Exception e) {
e.printStackTrace();
}
}
}
PrintStream和PrintWriter的区别
- 打印数据功能上是一模一样的:都是使用方便,性能高效(核心优势)
- PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法
- PrintWriter继承自字节输出流Writer,因此支持写符数据出去
打印流的一种应用:输出语句的重定向
System.out.println("志在千里");
- 可以把输出语句的打印位置改到某个文件中去。
PrintStream ps = new PrintStream("文件地址");
System.setOut(ps);
package com.IO.printstream;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class PrintTest01 {
public static void main(String[] args) {
System.out.println("老骥伏枥");
System.out.println("志在千里");
try (
PrintStream ps = new PrintStream("basic-grammar\\src\\yehuan11.txt");
){
// 把系统默认的打印流对象改成自己设置的打印流
System.setOut(ps);
System.out.println("烈士暮年");
System.out.println("壮心不已");
} catch (Exception e) {
e.printStackTrace();
}
}
}
8.数据流
DataOutputStream(数据输出流)
- 允许把数据和其类型一并写出去
package com.IO.data_stream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class DataOutputStreamTest1 {
public static void main(String[] args) {
try (
//1.创建一个数据输出流包装低级的字节输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("basic-grammar\\src\\yehuan10out.txt"));
){
dos.writeInt(97);
dos.writeDouble(99.5);
dos.writeBoolean(true);
dos.writeUTF("夜欢");
} catch (Exception e) {
e.printStackTrace();
}
}
}
DataInputStream(数据输入流)
- 用于读取数据输出流写出去的数据
package com.IO.data_stream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
目标:使用数据输入流读取特定类型的数据。
*/
public class DataInputStreamTest2 {
public static void main(String[] args) {
try (
DataInputStream dis = new DataInputStream(new FileInputStream("basic-grammar\\src\\yehuan10out.txt"));
){
int i = dis.readInt();
System.out.println(i);
double d = dis.readDouble();
System.out.println(d);
boolean b = dis.readBoolean();
System.out.println(b);
String s = dis.readUTF();
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
9.序列化流
对象序列化:把Java对象写入到文件中去
对象反序列化:把文件里的Java对象读出来
ObjectOutputStream(对象字节输出流)
- 可以把Java对象进行序列化:把Java对象写入到文件中去
User类:
package com.IO.object_stream;
import java.io.Serializable;
//注意:对象如果需要序列化,必须实现序列化接口
public class User implements Serializable {
private String loginName;
private String userName;
private int age;
private String passWord;
public User() {
}
public User(String loginName, String userName, int age, String passWord) {
this.loginName = loginName;
this.userName = userName;
this.age = age;
this.passWord = passWord;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "User{" +
"loginName='" + loginName + '\'' +
", userName='" + userName + '\'' +
", age=" + age +
", passWord='" + passWord + '\'' +
'}';
}
}
package com.IO.object_stream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Test01ObjectOutputStream {
public static void main(String[] args) {
try (
//2.创建一个对象字节输出流包装原始的字节输出流。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("basic-grammar\\src\\yehuan11out.txt"));
){
//1.创建一个Java对象
User u = new User("admin","夜欢",25,"123456");
//3.序列化对象到文件中
oos.writeObject(u);
System.out.println("序列化对象成功!!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意:对象如果需要序列化,必须实现序列化接口(java.io.Serializable)
ObjectInputStream(对象字节输入流)
- 可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来
package com.IO.object_stream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Test02ObjectInputStream {
public static void main(String[] args) {
//1.创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通
try (
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("basic-grammar\\src\\yehuan11out.txt"));
){
User u = (User)ois.readObject();
System.out.println(u);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//transient 这个成员变量将不参加序列化
private transient String passWord;
如果要一次序列化多个对象,咋整?
用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可。
注意:ArrayList集合已经实现了序列化接口!
10.补充知识:IO框架
什么是框架?
- 解决,某类问题,编写的一套类、接口等,可以理解为一个半成品,大多框架都是第三方研发的
- 好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率
- 框架的形式:一般是把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。
什么是IO框架
- 封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
导入commons-io-2.18.0.jar框架到项目中去
- 在项目中创建一个文件夹:lib
- 将commons-io-2.18.0.jar文件复制到lib文件夹
- 在lib文件上点右键,选择ADD as Library -> 点击ok
- 在类中导包使用