Java的文件IO

首先在写这篇文章之前,我需要大家来想个问题,既然已经有了数据库管理系统,为什么还需要文件管理系统呢?

相信这个问题的答案大家已经想到了,主要就是有下面4条理由:

1.结构和灵活性: 首先数据库管理系统由于其提供有强大的数据模型、查询语言(SQL)和事务管理等功能主要是适用于处理复杂查询、数据完整性和并发控制的应用。而文件管理系统则可以存储各种类型的数据。如非结构化的数据(图片、音频、视频等等)。

2.性能: 文件管理系统提供了可以更直接的文件访问,并且对于大量小文件的存储和访问会更加高效。

3.兼容性和历史原因: 由于文件管理系统的历史更长,因此许多应用已经依赖于文件管理系统。

4.成本和复杂性: 文件系统的维护和管理通常比数据库管理系统更简单。

因此,尽管数据库系统在许多方面都很强大,但文件管理系统仍然有其存在的价值和应用场景。在实际应用中,数据库系统和文件管理系统常常结合使用,以满足各种复杂的需求。如对于不用使用复杂查询和事务管理的的应用来使用文件管理系统更好。

1.文件的读取和输入

由于Java的文件API太有点复杂,因此我们提供了Apache commons-io库来简化JavaIO操作。所以我们需要先配置依赖:

xml 复制代码
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.10.0</version>
</dependency>

添加完依赖后呢,我又往Main包下创建了一个name.txt文件,如图所示:

如果我们想获取里面的内容,就需要调用依赖里面的工具类FileUtils,代码如下所示:

java 复制代码
package com.example.main;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        File file = new File("./name.txt");
        String content = null;
        try {
            //这里的readFileToString()方法就是将文件全部读取。
            content = FileUtils.readFileToString(file,"utf-8");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println(content);
        //lijinxuan
        //xiyan
    }
}

现在我们增加一点难度,将name.txt文件更改一下为:

我们就假设上面是用户名+密码的组合。想要将他们获取并打印则可以写出代码:

下面是User类的代码:

typescript 复制代码
package com.example.main;

import java.time.LocalDateTime;

public class User{
    private String name;
    private String password;
    private LocalDateTime createdTime;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public LocalDateTime getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(LocalDateTime createdTime) {
        this.createdTime = createdTime;
    }
}

下面的创建User对象相信大家也看到了,我们是在每次添加新元素时都创建了一个新的User对象,但是我们为什么不直接创建一个公共的User对象然后依次调用不就行了吗?其实啊,集合中的每个元素都是一个指向堆上实际对象的指针或引用。即每次向集合中添加元素调用的都是对象的引用,而不是对象本身的副本。

java 复制代码
package com.example.main;

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args){
        //获取文件对象
        File file = new File("./name.txt");
        //创建字符串列表
        List<String> list = null;
        //创建User泛型的列表来存储对象数据
        List<User> users = new ArrayList<>();
        try {
            //readLines方法就是将文件按行读取
            list = FileUtils.readLines(file,"utf-8");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println(list);
        for (String line: list) {
            //创建User类对象
            User user = new User();
            //创建一个字符数组,里面来存放字符串。
            //String类里面的split方法可以将字符串分割成数组。
            //这里split里面的参数是将空格作为了分隔符
            String[] strings = line.split(" ");
            user.setName(strings[0]);
            user.setPassword(strings[1]);
            user.setCreatedTime(LocalDateTime.now());
            users.add(user);
        }
        //打印每个用户的用户名
        for (User use: users) {
            System.out.println(use.getName());
            System.out.println(use.getPassword());
        }
    }
}

运行结果如下:

如果我想再改变一下,将name.txt文件更改为:

注意哈,上面我写的日期格式是标准的LocalDateTime类型的格式。

java 复制代码
package com.example.main;

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args){
        //获取文件对象
        File file = new File("./name.txt");
        //创建字符串列表
        List<String> list = null;
        //创建User泛型的列表来存储对象数据
        List<User> users = new ArrayList<>();
        try {
            //readLines方法就是将文件按行读取
            list = FileUtils.readLines(file,"utf-8");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println(list);
        for (String line: list) {
            //创建User类对象
            User user = new User();
            //创建一个字符数组,里面来存放字符串。
            //String类里面的split方法可以将字符串分割成数组。
            //这里split里面的参数是将空格作为了分隔符
            String[] strings = line.split(" ");
            user.setName(strings[0]);
            user.setPassword(strings[1]);
            //这里我们调用parse()的方法,里面的参数就是字符串类型,这个将其转化为LocalDateTime类型。
            user.setCreatedTime(LocalDateTime.parse(strings[2]));
            users.add(user);
        }
        //打印每个用户的用户名
        for (User use: users) {
            System.out.println(use.getName());
            System.out.println(use.getPassword() + " " + use.getCreatedTime());
        }
    }
}

结果如下所示:

那么我想将文件写入到文件里面该如何操作呢?直接看代码吧:

java 复制代码
package com.example.main;

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        try {
            String content = FileUtils.readFileToString(new File("./name.txt"),"utf-8");
            //如果下面的文件路径都不存在,那么系统会直接创建一个新的文件。
            FileUtils.write(new File("./bag.txt"),content,"utf-8");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2. JSON数据的序列化和反序列化的转换

我们首先要知道ObjectMapperJackSon库中的一个核心类,它提供了将Java对象序列化为Json字符串以及将Json字符串反序列化为Java对象的功能。具体的调用肯定是要先添加依赖:

xml 复制代码
<dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-databind</artifactId>  
    <version>2.16.1</version> <!-- 使用时请检查最新版本 -->  
</dependency>

下面是User测试类的具体代码,如下:

之所以添加注解是因为jackSon默认是不支持Java8引入的新日期和时间类,比如LocalDateTime类。

typescript 复制代码
package com.example.main;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;

public class User{
    private String name;
    private String password;
    //LocalDateTime的默认格式和json的时间戳格式不匹配会导致报错,如要避免这种情况,就需要添加JsonDeserialize注解和JsonSerialize注解。里面的参数则是使用的类。
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    //第一个shape参数是指定该字段是被序列化为一个字符串类型,而第二个参数则是该字符串应该遵循的格式。
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy年MM月dd HH:mm:ss")
    private LocalDateTime createdTime;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public LocalDateTime getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(LocalDateTime createdTime) {
        this.createdTime = createdTime;
    }
}

1.这里的序列化说白了就是将Java对象转化为Json数据,即将Java文件内容写入到Json文件中。

下面则是序列化主方法的运行。

下面主方法想要调用ObjectMapper类则需要添加依赖,依赖就是:

xml 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.15.3</version>
</dependency>
java 复制代码
package com.example.main;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("jinxuan");
        list.add("xiyan");
        System.out.println(list);
        System.out.println("上面打印出来的是集合,而下面打印的是对象");
        User user = new User();
        user.setName("xiYan");
        user.setPassword("123456");
        user.setCreatedTime(LocalDateTime.now());
        //将实例赋值给变量mapper。
        ObjectMapper mapper = new ObjectMapper();
        try {
            String str = mapper.writeValueAsString(user);
            System.out.println(str);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        //我们得到刚创建的文件对象。
        File file = new File("./user.json");
        try {
            mapper.writeValue(file,user);
            System.out.println("数据已经成功插入到了user.json文件中");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

打印结果如下图所示:

2.接下来就该反序列化了,反序列化说白了就是读取Json文件里面的内容。

直接看代码:

java 复制代码
package com.example.main;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        ObjectMapper mapper = new ObjectMapper();
        User user = null;
        try {
            user = mapper.readValue(new File("user.json"), User.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println(user.getName() + " " + user.getPassword() + " " + user.getCreatedTime());
    }
}

打印的结果如下所示:

那么接下来我将user.json文件进行修改一下,如下:

css 复制代码
[  {"name":"xiYan",    "password":"123456",    "createdTime":"2024年02月19 15:44:49"  },  {"name":"lijinxuan",    "password":"123456",    "createdTime":"2022年07月15 15:45:35"  }]

那么我们还想要将其反序列化就应该:

java 复制代码
package com.example.main;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class Main {
    public static void main(String[] args){
        ObjectMapper mapper = new ObjectMapper();
        try {
            List<User> users = mapper.readValue(new File("user.json"), new TypeReference<List<User>>() {
            });
            for (User u : users) {
                System.out.println(u.getName() + " " + u.getPassword() + " " + u.getCreatedTime());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果如下所示:

相关推荐
qq_4419960521 分钟前
Mybatis官方生成器使用示例
java·mybatis
巨大八爪鱼27 分钟前
XP系统下用mod_jk 1.2.40整合apache2.2.16和tomcat 6.0.29,让apache可以同时访问php和jsp页面
java·tomcat·apache·mod_jk
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
wclass-zhengge4 小时前
SpringCloud篇(配置中心 - Nacos)
java·spring·spring cloud
路在脚下@4 小时前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet
黑马师兄4 小时前
SpringBoot
java·spring