JavaImprove--Lesson11--IO流-序列化流

一.序列化流

对象序列化:把Java对象写入到文件中去

对象反序列化:把文件里的Java对象读出来

ObjectOutputStream对象字节输出流

可以将Java对象序列化,然后向写到文件中去

构造器:

public ObjectOutputStream(OutputStream os);创建对象字节输出流,包装基础的字节输出流

方法:

public final void writeObject(object o) throws IOException  ;把对象写出去

public static void main(String[] args) {
    try (
            //创建序列化流
            FileOutputStream os = new FileOutputStream("static/text/t4.txt");
            ObjectOutputStream oos = new ObjectOutputStream(os);
            ){
        //创建一个学生类对象
        Student s = new Student("msf","boy",18);
        oos.writeObject(s);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

 

注意点:

序列化对象必须要实现Serializable接口,虽然这个接口什么内容都没有,但是也必须要实现它,因为它不是给我们看的,而是打上标记,由JVM虚拟机来执行

当JVM看到对象实现这个接口后,就会调用相关的序列化程序加工,如果不实现此接口就无法完成序列化,如下:

 实现此接口后,再次运行代码如下:

 由于序列化也存入对象类型,所以又看不清楚,这是正常的,只有反序列化后可以得到对象内容

重点:如果一个对象的属性不用参与序列化,可以使用transient关键字修饰,表示此成员变量不参与序列化

private transient int grade;

 

ObjectInputStream对象字节输入流

可以将Java对象反序列化,把存储到文件中的对象读取到内存

构造器:

public ObjectInputStream(InputStream is)创建对象字节输入流,包装基础的字节输入流

方法:

public final Object readObject()把存储在文件中的Java对象读取出来

public static void main(String[] args) {
    try (
            //创建反序列化流
            FileInputStream is = new FileInputStream("static/text/t4.txt");
            ObjectInputStream ois = new ObjectInputStream(is);
            ){
        Student s =(Student) ois.readObject();
        System.out.println(s);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

 

输出如下:

 一次序列化多个对象

如果要求一次序列化多个对象,一个一个写肯定不高效,所以可以把它放在一个list集合中,序列化这个集合,因为集合也实现了Serializable接口,所以是可以序列化的

当反序列化时,拿到的也是一个集合,可以方便的拿取这多个对象

 如上就是ArrayList类,在官方文档中可以看到,的确实现了Serializable接口

序列化多个对象代码如下:

public static void main(String[] args) {
    try (
            //申请一个序列化流
            FileOutputStream os = new FileOutputStream("static/text/t5.txt");
            ObjectOutputStream oos = new ObjectOutputStream(os);
            ){
        //申请集合装多个需要序列化的对象
        ArrayList<Student> list = new ArrayList<>();
        Collections.addAll(list,new Student("msf","boy",15),
                new Student("mam","girl",25),
                new Student("faw","boy",19));
        oos.writeObject(list);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

 

反序列化多个对象代码如下:

public static void main(String[] args) {
    try (
            //申请反序列化流
            FileInputStream is = new FileInputStream("static/text/t5.txt");
            ObjectInputStream ois = new ObjectInputStream(is);
            ){
        List<Student> list = (List<Student>)ois.readObject();
        System.out.println(list);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

 

输出结果如下:

 二.IO框架

 框架指的是在解决某一类问题时,编写的类或接口,可以理解为一个半成品,大多框架都是第三方研制的

好处:可以在已有的半成品基础上继续研发,可以基于优秀的软件框架开发,并提高开发效率

框架的形式:一般时把类,接口等编译成class形式,在压缩成.jar包供开发人员使用

什么是IO框架?

封装了Java对文件数据操作的代码,对外提供更简单的文件方式操作文件,对数据进行读写

Commons-io是apache开源基金组织提供的一组有关操作IO的小框架,目的是提高IO流开发的效率

FileUtils部分方法展示

public static void copyFile(File srcFile,File destFile);复制文件

public static void copyDirectory(File srcDir,File destFile);复制文件夹

public static void deleteDirectory(File directory);删除文件夹,可以删除非空文件夹,慎用

public static String readFileToString(File file,String encoding);读数据

public static void writeStringToFile(File file,String data,String charsert,boolean append);写数据

public static void main(String[] args) throws IOException {
    //简单复制文件
    FileUtils.copyFile(new File("static/text/t2.txt"),new File("static/text/t3.txt"));
    
    //简单读取文件
    String rs = FileUtils.readFileToString(new File("static/text/t3.txt"), "UTF-8");
    System.out.println(rs);
    /*
    我爱中国
    我爱中国
     */
    
    //简单写入文件
    FileUtils.write(new File("static/text/t3.txt"),"我很爱中国","UTF-8");
}

IOUtils提供的方法

public static int copy(InputStream is ,OutputStream os);复制文件

public static int copy(Reader r,Writer,w);复制文件

public static void writer(String data,OutputStream os ,String charset);写数据

public static void main(String[] args) throws Exception {
    //简单复制文件
    int copy = IOUtils.copy(new FileInputStream("static/text/t2.txt"), new FileOutputStream("static/text/t3.txt"));
    System.out.println(copy);
    //简单写数据
    IOUtils.write("世界和平",new FileOutputStream("static/text/t2.txt"),"UTF-8");
}

 

Java官方自带的Files也做了优化:

//Java官方自己提供的优化代码
//目的文件名要为空
Path copy1 = Files.copy(Path.of("D:\\其它\\Markdown\\Project\\JavaSeImprove\\static\\text\\t2.txt"),
        Path.of("D:\\其它\\Markdown\\Project\\JavaSeImprove\\static\\text\\t6.txt"));
System.out.println(copy1);

 

三.特殊文件类型

目前Java中常用的文件类型一共有三种,分别是:txt文本文件,properties属性文件,xml文件

其中properties文件是单行有效,也就是一行即代表一个属性,读取的时候需要注意这个特点

还有xml文件有人称之为双标签文件,因为其总是以成对的文件标识包括数据

 Properties文件

 properties文件在Java中也是一个类对象,它相当于一个Map集合,也就是以键值对的形式存在在,文件中可以看出来,键和值由“=”分割,它也是Map接口下的一个实现类

但是呢,一般我们不把properties文件当作集合使用,集合用hashmap就够了,更多的是使用它的文件形式,也就是持久化保存数据

核心作用:

Properties用来表达文件属性,通过Properties可以读写文件中的数据

读取键值对

构造器:

public Properties();用于构建一个Properties文件的空容器

public static void main(String[] args) {
    //申请一个空的Properties容器
    Properties pro = new Properties();
    
}

 

相关方法:

public void load(InputStream is);通过字节输入流,读取属性文件中的键值对数据

public void load(Reader reader);通过字符输入流,读取属性文件中的键值对数据

public String getProperties(String key);根据键获取值(其实就是get方法的效果)

public set<String> stringPropertyNmaes();获取全部的键集合(其实就是keySet方法)

public static void main(String[] args) throws Exception {
    //申请一个空的Properties容器
    Properties pro = new Properties();
    //加载一个properties文件
    pro.load(new FileReader("static/pro/user.properties"));
    //根据键拿取值
    String age = pro.getProperty("age");
    System.out.println(age);//18
    //获取全部集合
    Set<String> rs = pro.stringPropertyNames();
    rs.forEach((a) -> System.out.println(a+":"+pro.getProperty(a)));
}

 

写入键值对 

 方法:

public Object setProperties(String key,String value);保存键值对到properties键值对对象中

public void store(OutputStream os,String comments);把键值对通过字节流写入到文件中,可以附加上注释

public void store(Writer w,String comments);把键值对数据通过字符写入到文件中去,并附加上注释

public static void main(String[] args) throws Exception {
    //申请一个properties空容器
    Properties pro = new Properties();
    //先往容器中加数据,最后一次写入
    pro.setProperty("username","msf");
    pro.setProperty("age","18");
    pro.setProperty("sex","boy");
    //最后一起刷入到文件
    pro.store(new FileWriter("static/pro/user1.properties"),"I add a user");
}

 

案例

判断如下文件中,是否包含张三,如果有将张三的值改为100

 如上,虽然是一个txt文件,但是只要满足一行是一个键值对,且以“=”分割,都是properties文件

代码实现:

public static void main(String[] args) throws Exception{
    //申请一个Properties文件容器
    Properties p = new Properties();
    
    //装入文件字节流
    p.load(new FileReader("static/text/t2.txt"));
    
    //判断是否包含条件
    if (p.containsKey("张三")){
        p.setProperty("张三","100");
    }
    
    //保存文件
    p.store(new FileWriter("static/text/t2.txt"),"this a change");
}

结果如下:

 

 XML文件

 XML:本质上是一种数据格式,可以用来存储复杂的数据结构和数据关系

特点:

  • XML中的“标签名”称为一个标签或一个元素,一般是成对出现
  • XML的标签名可以自定义,但必须以嵌套的形式存在
  • XML只能有一个根标签
  • XML的标签可以有属性
  • 如果文件XML,则后缀名就一定要为xml

 在XML文件中可能存在一些符号是不能直接写入的,如:>,<等,则需要一些符号代替

&lt;  = <

&gt; = >

&amp; = &

&apos;  = '

&quot = "

另外,XML的一个CDATA区域是特殊区域,写在这个区域可以不用符号标识,直接写

<user><![CDATA[  > < & : ' " ]]></user>

 

读取XML文件内容 

 读取XML文件可以使用IO流来做,但是由于XML文件的标签没有特定的约束,所以自己写IO流来写就很麻烦

于是,我们就想到使用第三方库,如Dom4j,将其下载后装载idea的额lib中

 

 如上:是Dom4j对XML文件的解析,会将整个XML文件解析成为doucment文档,然后是元素及属性

构造器:

public SAXReader();构建Dom4j的解析器对象

public Document read(FileInputStream is);通过字节流解读XML

SAXReader read = new SAXReader();
Document document = read.read("static/pro/users.xml");

 

public Document read(String url);把xml解读成doucment文件

SAXReader saxReader = new SAXReader("static/pro/users.xml");

 

方法:

Elment getRootElement()获得根元素对象

Element element = document.getRootElement();

 

public String getName()得到元素名字

Element element = document.getRootElement();//获得根节点
System.out.println(element.getName());//得到根节点名字

 

public List<Element> elements()获得当前元素下所有子元素

Element element = document.getRootElement();//获得根节点
List<Element> list = element.elements();//获得所有下一级子元素
for (Element e : list) {
    System.out.println(e.getName());
}

 

public List<Element> elemnets(String name);获得指定名字的元素集合

Element element = document.getRootElement();//获得根节点
List<Element> list = element.elements("user");//获得指定名字的子元素节点
for (Element e : list) {
    System.out.println(e.element("name").getText());
}

 

public Element element(String name)得到当前元素下指定名字的子元素,如果有很多,返回第一个

Element element = document.getRootElement();//获得根节点
Element user = element.element("user");//获得指定名字的子元素节点(单个)
String sex = user.element("sex").getText();
System.out.println(sex);

 

public String attributeValue(String name)通过属性名直接得到属性值

Element element = document.getRootElement();//获得根节点
Element user = element.element("user");//获得指定名字的子元素节点(单个)
String s = user.attributeValue("id");//获得当前元素的属性值
System.out.println(s);

 

public String elementText(子元素名)得到指定名称的子元素文本

Element element = document.getRootElement();//获得根节点
Element user = element.element("user");//获得指定名字的子元素节点(单个)
String s = user.elementText("age");//获得指定子元素的子元素属性值
System.out.println(s);

 

public String getText()得到文本

Element element = document.getRootElement();//获得根节点
Element user = element.element("user");//获得指定名字的子元素节点(单个)
Element name = user.element("name");
String text = name.getText();//获得当前元素的文本内容
System.out.println(text);

 

同意义:

String textTrim = name.getTextTrim();//取出文本,去掉前后空格

 使用程序写入XML

 在开发中,很少使用程序去写入XML的情况,如果一定要写入,推荐使用字符流,直接拼接字符串写入

public static void main(String[] args) throws Exception {
    StringBuilder st = new StringBuilder();
    //拼接约束
    st.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
    //拼接根标签
    st.append("<users>\r\n");
    //拼接元素
    st.append("<user1>\r\n");
    //拼接子元素节点
    st.append("<username>").append("msf").append("</username>\r\n");
    st.append("<age>").append("20").append("</age>\r\n");
    st.append("<sex>").append("boy").append("</sex>\r\n");
    //补充完标签
    st.append("</user1>\r\n");
    st.append("</users>\r\n");
    //创建字节写出池
    BufferedWriter bw = new BufferedWriter(new FileWriter("static/pro/user1.xml"));
    //写出
    bw.write(st.toString());
    //关闭流
    bw.close();
}

 

XML约束:限制XML文件只能按照某种格式书写

利用DTD约束文档,约束一个XML文件的编写

  1. 编写的DTD文档,必须是.dtd结束
  2. 在需要约束的XML文件中导入该DTD文件
  3. 然后,XML文件就只能按照约定的格式书写,否则会报错 

 编写DTD文件:

 导入dtd文件,并按照约束写XML文件

 

 

 

XXXX

 

posted @ 2025-07-03 20:50  回忆也交给时间  阅读(8)  评论(0)    收藏  举报