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;}@Overridepublic 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
- 在类中导包使用