Java io流(三)

Java IO 流(三)

1. 学生对象到文件(排序版,使用字符流)

  • 学生类
package third;
public class Student {
private String name;
private int chinese;
private int math;
private int english;
public Student() {
}
public Student(String name, int chinese, int math, int english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getSum(){
return math+english+chinese;
}
}
  • 测试类
package third;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.TreeSet;
public class Test {
public static void main(String[] args) throws IOException {
// 1.对集合进行排序
// set集合,treeset的比较器
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 1.先比较总分
int num1= o1.getSum()-o2.getSum();
// 2.在比较语文成绩
int num2= num1==0? o1.getChinese()-o2.getChinese():num1;
// 3.比较数学成绩
int num3= num2==0? o1.getMath()-o2.getMath():num2;
// 4.比较英语成绩
int num4= num3==0? o1.getEnglish()-o2.getEnglish():num3;
// 5.比较姓名
int num5= num4==0? o1.getName().compareTo(o2.getName()):num4;
return -num5;
}
});
// 创建学生对象
Student s1 = new Student("heima001",100,90,80);
Student s2 = new Student("heima002",100,80,90);
Student s3 = new Student("heima003",100,90,80);
Student s4 = new Student("heima004",90,90,90);
// 添加对象到set集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
// 把对象写入文件
BufferedWriter bw = new BufferedWriter(new FileWriter("code\\8.txt"));
for(Student s:ts){
// 新建一个可变字符串
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",")
.append(s.getEnglish()).append(",").append(s.getSum());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
bw.close();
}
}
  • 效果图

在这里插入图片描述

2. 复制多级文件夹

package 复制单级目录;
import java.io.*;
public class Demo {
public static void main(String[] args) throws IOException {
// 源目录对象
File srcFile=new File("E:\\file");
// 获取单个目录对象的名称(file)
String srcFoldFile=srcFile.getName();
// 复制到哪里
File destFile = new File("E:\\myfile",srcFoldFile);
// 判断目录是否存在
if(!destFile.exists()){
// 没有则创建目录
destFile.mkdirs();
}
// 获取源目录下的文件对象
File[] files = srcFile.listFiles();
// 对于每个对象,如果是文件,直接复制,如果是目录,递归调用
// for(File s:files){
// System.out.println(s);
// }
for(File f:files){
fileSearch(f,destFile);
}
}
public static void copy(File srcFile,File destFile) throws IOException {
FileOutputStream fos = new FileOutputStream(destFile);
FileInputStream fis = new FileInputStream(srcFile);
int len;
byte[]bys=new byte[1024];
while((len=fis.read(bys))!=-1){
fos.write(bys,0,len);
}
}
public static void fileSearch(File f,File destFile) throws IOException {
File dFile=new File(destFile,f.getName());
if(f.isFile()){
// 是文件,直接复制
copy(f,dFile);
}else if(f.isDirectory()){
// 不是文件,创建目录
dFile.mkdir();
// 递归目录里面的文件
for(File f3:f.listFiles()) {
fileSearch(f3, dFile);
}
}
}
}
  • 效果图

在这里插入图片描述

3. IO特殊操作流

3.1 标准输入流

  • System类的两个静态的成员变量
    • public static final InputStream in:标准输入流,通常该流对应键盘输入或用户定义或主机环境指定的输入
    • public static final PrintStream out,标准输出流,通常该流对应显示输出或由主机环境和用户指定
package 标准输入流;
import java.io.IOException;
import java.io.InputStream;
public class Demo1 {
public static void main(String[] args) throws IOException {
// 1.定义一个标准输入流变量
// 数据来源键盘输入
InputStream is=System.in;
int len;
while((len=is.read())!=-1){
System.out.println((char)len);
}
}
}
  • 效果图

在这里插入图片描述

标准输入流转字符流

package 标准输入流;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Demo1 {
public static void main(String[] args) throws IOException {
// 1.定义一个标准输入流变量
// 数据来源键盘输入
InputStream is=System.in;
// int len;
// while((len=is.read())!=-1){
// System.out.println((char)len);
// }
// 字节流到字符流的转换
InputStreamReader isr = new InputStreamReader(is);
// 字符流到字符缓冲流,实现一次读取一行数据
BufferedReader br = new BufferedReader(isr);
String str;
while((str=br.readLine())!=null){
System.out.println(str);
}
isr.close();
br.close();
}
}
  • 效果图

在这里插入图片描述

3.2 标准输出流

  • public static final PrintStream out
package 标准输入流;
import java.io.PrintStream;
public class Demo2 {
public static void main(String[] args) {
// 1.创建标准输出流
PrintStream ps=System.out;
ps.println("666");
// 等价于
System.out.println("666");
}
}
  • 效果图

在这里插入图片描述

3.3 字节打印流

  • 字节打印流:PrintStream

  • 字符打印流:PrintWriter

  • 打印流的特点

    • 只负责输出,只写数据
    • 写数据有特有方法:print,println

字节打印流示例

package 字节打印流;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
public class Demo1 {
public static void main(String[] args) throws IOException {
// 1.创建字节打印流对象
PrintStream ps = new PrintStream("code\\9.txt");
// 1.标准写法,其他字节流也有的方法
// 打印的是acall码对应的字符
ps.write(97);
String str="2222\r\n";
ps.write(str.getBytes());
// 2.特有方法,打什么是什么
ps.println(111);
ps.print(99);
ps.close();
}
}
  • 效果图

在这里插入图片描述

3.4 字符打印流

  • 构造方法(这些方法可以在jdk文档中查看,学习时多看这些文档)
方法名说明
PrintWriter(String fileName)根据文件名创建pw,不执行自动flush
PrintWriter(String fileName,boolean autoFlush)第二个参数代表是否自动刷新

示例

package 字节打印流;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Demo2 {
public static void main(String[] args) throws IOException {
PrintWriter pw = new PrintWriter(new FileWriter("code\\10.txt"),true);
pw.println(1111);
pw.println(111);
pw.write(97);
pw.flush();
pw.close();
}
}
  • 效果图

在这里插入图片描述

字符打印流复制文件

package 字节打印流;
import java.io.*;
public class Demo3 {
public static void main(String[] args) throws IOException {
// 1.使用字符打印流复制文件
// 创建字符打印流
PrintWriter pw = new PrintWriter(new FileWriter("code\\11.txt"));
// 创建字符缓冲流
BufferedReader br = new BufferedReader(new FileReader("code\\9.txt"));
String len;
while((len=br.readLine())!=null){
pw.println(len);
}
br.close();
pw.close();
}
}
  • 效果图

在这里插入图片描述

4. 对象序列流化

  • 对象序列化:将对象保存在磁盘中,或在网络中传输对象

  • 一个字节序列表示一个对象,该字节序列包括:对象的类型,对象的数据,对象的属性等信息

  • 构造方法

方法名说明
ObjectOutputStream创建一个写入指定的Output Stream的oos
  • 序列化对象的方法
方法名说明
void writeObject(Object obj)将指定对象写入oos

示例

  • 学生类
package 对象序列化;
import java.io.Serializable;
// 对象序列化,前提需要这个类实现了Ser.....接口
public class Student implements Serializable {
private String name;
private int chinese;
private int math;
private int english;
public Student() {
}
public Student(String name, int chinese, int math, int english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getSum(){
return math+english+chinese;
}
}
  • 测试类
package 对象序列化;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class Demo {
public static void main(String[] args) throws IOException {
// 1.创建序列化oos对象
FileOutputStream fos = new FileOutputStream("code\\12.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 2.创建一个学生对象
Student s1 = new Student("bob",100,100,100);
// 3.对象序列化写入文件
oos.writeObject(s1);
oos.close();
}
}
  • 效果图

在这里插入图片描述

注意点

  • 要序列化的对象需要实现Serializable接口
  • 实现该接口不需要重写任何方法

5. 对象反序列化

  • 构造方法
方法名说明
ObjectInputStream(InputStream in)创建从InputStream读取的ois
  • 读取方法
方法名说明
Object readObject()从ois读取一个对象,返回值object类型

示例

package 对象序列化;
import java.io.*;
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 1.创建序列化oos对象
FileOutputStream fos = new FileOutputStream("code\\12.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 2.创建一个学生对象
Student s1 = new Student("bob",100,100,100);
// 3.对象序列化写入文件
oos.writeObject(s1);
// 4.反序列化对象
FileInputStream fis = new FileInputStream("code\\12.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// 读取数据
Student s= (Student) ois.readObject();
System.out.println(s.getName());
System.out.println(s.getMath());
oos.close();
}
}
  • 效果图

在这里插入图片描述

5.1 serialVersionUID 和 transient

  • 用对象序列化一个对象后,假如我们修改了对象所属的类(类中的内容发生了改变),读取数据会出问题

    1. 抛出InvaildClassException异常
  • 解决

    • 重新序列化
    • 给对象所属的类加一个serialVersionUID(常量,不在变化)
  • 如果一个对象的某个成员变量不想被序列化,给该变量添加transient关键字修饰

  • 序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID,它在反序列化过程中使用,以验证序列化对象的发送者和接收者是否加载了与序列化兼容的对象的类。 如果接收者已经为具有与对应发件人类别不同的serialVersionUID的对象加载了一个类,则反序列化将导致一个InvalidClassException 。 一个可序列化的类可以通过声明一个名为"serialVersionUID"的字段来显式地声明它自己的serialVersionUID,该字段必须是static,final和long类型:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类没有显式声明serialVersionUID,则序列化运行时将根据Java(TM)对象序列化规范中所述的类的各个方面计算该类的默认serialVersionUID值。然而, 强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节非常敏感,这些细节可能因编译器实现而异,因此可能会在反序列化期间导致意外的InvalidClassException 。因此,为了保证不同Java编译器实现之间的一致的serialVersionUID值,一个可序列化的类必须声明一个显式的serialVersionUID值。还强烈建议,显式的serialVersionUID声明在可能的情况下使用private修饰符,因为这种声明仅适用于立即声明的类 - serialVersionUID字段作为继承成员无效。

package 对象序列化;
import java.io.*;
public class Demo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = new FileOutputStream("code\\12.txt");
FileInputStream fis = new FileInputStream("code\\12.txt");
// 对象序列化
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s=new Student("judy",100,100,100);
oos.writeObject(s);
ObjectInputStream ois = new ObjectInputStream(fis);
// 反序列化
Object o = ois.readObject();
Student s2=(Student) o;
// second.Student s3=(second.Student) o;
System.out.println(s2.getName());
// System.out.println(s3.getName());
}
}
  • 效果图

在这里插入图片描述

  • uid使用与否对比图

在这里插入图片描述

在这里插入图片描述

6.Properties 集合的使用

6.1 作为Map(双列集合)的使用

  • 简介
    • 是一个Map体系的集合类
    • Properties可以保存到流或从流中加载
    • 键和值都是字符串

示例

package Properties集合的使用;
import java.util.Properties;
import java.util.Set;
public class demo {
public static void main(String[] args) {
Properties pt = new Properties();
pt.put("bob","15");
pt.put("judy","19");
pt.put("kate","25");
// 和Map集合一样的操作方法
Set<Object> sets = pt.keySet();
for(Object o:sets){
// 获取值
System.out.println(o);
System.out.println(pt.get(o));
}
}
}
  • 效果图

在这里插入图片描述

6.2 作为Map集合的特有方法

  • 特有方法
方法名说明
Object setProperty(String key,String value)设置集合的键和值,底层调用Hash Map的put方法
String getProperty(String key)根据键搜索值
Set stringPropeytyNames()返回一个键的集合,键与值都是字符串

示例

package Properties集合的使用;
import java.util.Properties;
import java.util.Set;
public class demo2 {
public static void main(String[] args) {
Properties pt = new Properties();
// 1.设置集合的键与值
pt.setProperty("bob","13");
pt.setProperty("kob","13");
pt.setProperty("lob","13");
// 2.根据键获取值
pt.getProperty("bob");
// 3.获取键的集合
Set<String> strings = pt.stringPropertyNames();
for(String s:strings){
System.out.println(s);
System.out.println(pt.getProperty(s));
}
}
}
  • 效果图

在这里插入图片描述

6.3 Properties 和 IO流相结合的方法

  • 与IO流相结合

    方法名说明
    void load(InputStream inStream)从输入字节流读取属性列表(键值对)
    void load(Reader reader)从输入字符流读取属性列表
    void store(OutputStream,String comments)写入输出字节流
    void store(Writer writer,String comments)写入输出字符流

示例

package Properties集合的使用;
import java.io.*;
import java.util.Properties;
import java.util.Set;
public class Demo3 {
public static void main(String[] args) throws IOException {
// 1.创建字节输入流
FileInputStream fis = new FileInputStream("code\\13.txt");
// 2.创建字节输出流
FileOutputStream fos = new FileOutputStream("code\\13.txt");
// 3.创建字符输入流
// FileReader fr = new FileReader("code\\13.txt");
// FileWriter fw = new FileWriter("code\\13.txt");
Properties pt = new Properties();
pt.setProperty("bob","13");
pt.setProperty("judy","13");
pt.setProperty("kate","13");
pt.store(fos,null);
Properties pt2=new Properties();
pt2.load(fis);
// 获取键
Set<String> keys = pt2.stringPropertyNames();
for(String s:keys){
System.out.println(s+","+pt2.get(s));
}
}
}
  • 效果图

在这里插入图片描述

posted @   凌歆  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示