IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)

简介: IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)

Java对象的序列化和反序列化



序列化和反序列化是什么


当两个进程远程通信时,彼此可以发送各种类型的数据。 无论是何 种类型的数据,都会以二进制序列的形式在网络上传送。比如,我 们可以通过http协议发送字符串信息;我们也可以在网络上直接发 送Java对象。发送方需要把这个Java对象转换为字节序列,才能在 网络上传送;接收方则需要把字节序列再恢复为Java对象才能正常 读取。 把Java对象转换为字节序列的过程称为对象的序列化。把字节序列 恢复为Java对象的过程称为对象的反序列化。


序列化涉及的类和接口


ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写 到一个目标输出流中。


ObjectInputStream代表对象输入流,它的readObject()方法从一个 源输入流中读取字节序列,再把它们反序列化为一个对象,并将其 返回。 只有实现了Serializable接口的类的对象才能被序列化。 Serializable接口是一个空接口,只起到标记作用。


将对象序列化到文件


ObjectOutputStream可以将一个内存中的Java对象通过序列化的方 式写入到磁盘的文件中。被序列化的对象必须要实现Serializable序 列化接口,否则会抛出异常。


创建对象

public class Users implements Serializable {
    private int userid;
    private String username;
    private String userage;
    public Users(int userid, String username, String userage) {
        this.userid = userid;
        this.username = username;
        this.userage = userage;
    }
    public Users() { }
    public int getUserid() {
        return userid;
   }
    public void setUserid(int userid) {
        this.userid = userid;
   }
    public String getUsername() {
        return username;
   }
    public void setUsername(String username)
   {
        this.username = username;
   }
    public String getUserage() {
        return userage;
   }
    public void setUserage(String userage) {
        this.userage = userage;
   }
    @Override
    public String toString() {
 return "Users{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", userage='" + userage + '\'' +
                '}';
   }


序列化对象

public class TestObjectOutputStream {
    public static void main(String[] args) {
        //创建对象输出字节流与文件输出字节流对象
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/data3"))){
            //创建Users对象
            Users users = new Users(1,"Oldlu","18");
            //将对象序列化到文件中
            oos.writeObject(users);
            //刷新
            oos.flush();
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


将对象反序列化到内存中


public class TestObjectInputStream {
    public static void main(String[] args) {
        //创建对象输入字节流与文件字节输入流对象
        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/data3"))) 
       {
            //将对象反序列化到内存中
            Users users = (Users) ois.readObject();
            System.out.println(users);
       }catch(Exception e){
            e.printStackTrace();
       }
   }
}


File类在IO中的作用



当以文件作为数据源或目标时,除了可以使用字符串作为文件以及 位置的指定以外,我们也可以使用File类指定。

public class TestFile {
    public static void main(String[] args) {
        //创建字符缓冲流与文件字符输入流对象
        try(BufferedReader br =  new BufferedReader(new FileReader(new File("d:/sxt.txt")));
            //创建字符输出流对象
            PrintWriter pw = new PrintWriter(new File("d:/sxt8.txt"))){
            //操作流
            String temp = "";
            int i=1;
            while((temp = br.readLine()) != null){
                pw.println(i+","+temp);
                i++;
}
            pw.flush();
       }catch(IOException e){
            e.printStackTrace();
       }
   }
}


装饰器模式构建IO流体系


装饰器模式简介


装饰器模式是GOF23种设计模式中较为常用的一种模式。它可以实 现对原有类的包装和装饰,使新的类具有更强的功能。


装饰器模式

class Iphone {
 private String name;
 public Iphone(String name) {
     this.name = name;
}
 public void show() {
    System.out.println("我是" + name + ",可以在屏幕上显示");
  }
}
class TouyingPhone {
    public Iphone phone;
    public TouyingPhone(Iphone p) {
        this.phone = p;
 }
 // 功能更强的方法
 public void show() {
     phone.show();
     System.out.println("还可以投影,在墙壁上显示");
 }
}
public class TestDecoration {
 public static void main(String[] args) {
     Iphone phone = new Iphone("iphone30");
     phone.show();
     System.out.println("===============装饰后");
     TouyingPhone typhone = newTouyingPhone(phone);
     typhone.show();
 }
}


IO流体系中的装饰器模式


IO流体系中大量使用了装饰器模式,让流具有更强的功能、更强的 灵活性。比如:

FileInputStream  fis = new FileInputStream(src);
BufferedInputStream  bis = new BufferedInputStream(fis);


显然BufferedInputStream装饰了原有的FileInputStream,让普通 的FileInputStream也具备了缓存功能,提高了效率。


Apache commons-io工具包的使用



Apache基金会介绍


Apache软件基金会(也就是Apache Software Foundation,简称 为ASF),是专门为支持开源软件项目而办的一个非盈利性组织。 在它所支持的Apache项目与子项目中,所发行的软件产品都遵循 Apache许可证(Apache License)。 官方网址为: www.apache.org 。 很多著名的Java开源项目都来源于这个组织。比如:commons、 kafka、lucene、maven、shiro、struts等技术,以及大数据技术 中的:hadoop(大数据第一技术)、hbase、spark、storm、 mahout等。


commons-io工具包


Apache的commons-io工具包中提供了IOUtils/FileUtils,为我们 提供了更加简单、功能更加强大的文件操作和IO流操作功能。非常 值得大家学习和使用。


下载与添加commons-io包

 下载地址 https://commons.apache.org/proper/commons-io/download_i o.cgi

 添加jar包


FileUtils类中常用方法的介绍


打开FileUtils的api文档,我们抽出一些工作中比较常用的方法,进 行总结和讲解。总结如下:


读取文件内容,并输出到控制台上(只需一行代码!)

import java.io.File;
import org.apache.commons.io.FileUtils;
public class TestUtils1 {
 public static void main(String[] args) throws Exception {
 String content = FileUtils.readFileToString(new File("d:/a.txt"), "gbk");
 System.out.println(content);
 }
}


使用FileUtils工具类实现目录拷贝


我们可以使用FileUtils完成目录拷贝,在拷贝过程中可以通过文件过 滤器(FileFilter)选择拷贝内容。

import java.io.File;
import java.io.FileFilter;
import org.apache.commons.io.FileUtils;
public class TestFileUtilsDemo2 {
      public static void main(String[] args) throws Exception {
      FileUtils.copyDirectory(new File("d:/aaa"), new File("d:/bbb"), new FileFilter() {
 @Override
 public boolean accept(File pathname) {// 使用FileFilter过滤目录和以html结尾的文件
 if (pathname.isDirectory() || pathname.getName().endsWith("html")) {
      return true;
 } else {
      return false;
      }
     }
   });
  }
}


IOUtils的妙用


打开IOUtils的api文档,我们发现它的方法大部分都是重载的。所 以,我们理解它的方法并不是难事。因此,对于方法的用法总结如 下:


我们没有必要对每个方法做测试,只是演示一下读入d:/sxt.txt文件 内容到程序中,并转成String对象,打印出来。


IOUtils的使用

import java.io.*;
import org.apache.commons.io.IOUtils;
public class TestIOUtilsDemo {
    public static void main(String[] args) throws Exception {
        String content = IOUtils.toString(new FileInputStream("d:/sxt.txt"),"utf-8");
        System.out.println(content);
   }
}


本章总结


按流的方向分类:


     输入流:数据源到程序(InputStream、Reader读进来)。

     输出流:程序到目的地(OutputStream、Writer写出去)。


按流的处理数据单元分类:


    字节流:按照字节读取数据(InputStream、 OutputStream)。

    字符流:按照字符读取数据(Reader、Writer)。


按流的功能分类:


    节点流:可以直接从数据源或目的地读写数据。

    处理流:不直接连接到数据源或目的地,是处理流的流。通 过对其他流的处理提高程序的性能。


IO的四个基本抽象类:InputStream、OutputStream、 Reader、Writer


InputStream的实现类:


    FileInputStream

    BufferedInputStream

    DataInputStream

    ObjectInputStream


OutputStream的实现类:


    FileOutputStream

    BufferedOutputStream

    DataOutputStream

    ObjectOutputStream


Reader的实现类


    FileReader

    BufferedReader

    InputStreamReader


Writer的实现类


    FileWriter

    BufferedWriter

    OutputStreamWriter

    PrintWriter


把Java对象转换为字节序列的过程称为对象的序列化。


把字节序列恢复为Java对象的过程称为对象的反序列化。


目录
相关文章
|
4天前
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
24 0
|
10天前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:输入与输出:Scanner与System类
你是否也经历过这些崩溃瞬间?三天教程连`i++`和`++i`都说不清,面试时`a==b`与`equals()`区别大脑空白,代码总是莫名报NPE。这个系列就是为你打造的Java「速效救心丸」!每天1分钟,地铁通勤、午休间隙即可学习。直击高频考点和实际开发中的“坑位”,拒绝冗长概念,每篇都有可运行代码示例。涵盖输入输出基础、猜数字游戏、企业编码规范、性能优化技巧、隐藏技能等。助你快速掌握Java核心知识,提升编程能力。点赞、收藏、转发,助力更多小伙伴一起成长!
39 19
|
4天前
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
25 5
|
4天前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
17 1
|
2天前
|
Java
java常见的集合类有哪些
Map接口和Collection接口是所有集合框架的父接口: 1. Collection接口的子接口包括:Set接口和List接口 2. Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及 Properties等 3. Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等 4. List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
|
4月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
230 58
|
7月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
83 7
|
5月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
79 3
|
5月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
92 2
|
5月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
92 1

推荐镜像

更多