You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Mail对象与String互转以存入YAML文件?

解决Mail对象无限制字符的序列化/反序列化问题

针对你不想限制邮件内容/主题字符的需求,给你几个可行的方案:

方案1:直接用YAML序列化Mail对象(最推荐)

既然你本来就用.yml文件存储,没必要自己转成String再存,直接用YAML库序列化整个List<Mail>对象更省心,原生支持任意字符,还不用自己处理拆分逻辑。

以常用的SnakeYAML库为例:

  1. 引入依赖(Maven):
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>2.2</version>
</dependency>
  1. 序列化(写入YAML):
List<Mail> mails = ...; // 你的邮件列表
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
try (FileWriter writer = new FileWriter("mails.yml")) {
    yaml.dump(mails, writer);
}
  1. 反序列化(读取YAML):
Yaml yaml = new Yaml(new Constructor(Mail.class));
try (FileReader reader = new FileReader("mails.yml")) {
    List<Mail> mails = yaml.load(reader);
}

注意:要确保Mail类有无参构造器,或者给SnakeYAML配置自定义构造器适配你现有的带String参数的构造器(如果不想加无参构造的话)。

方案2:分隔符转义法

如果坚持要自己转String,可以对字段中的分隔符做转义处理,比如用#作为分隔符,但提前把字段里的#替换成\#,同时把\替换成\\(避免转义字符冲突)。

修改Mail类的toString()和构造器:

@Override
public String toString() {
    // 转义字段中的\和#
    String escapedSender = _sender.replace("\\", "\\\\").replace("#", "\\#");
    String escapedDate = _date.replace("\\", "\\\\").replace("#", "\\#");
    String escapedTopic = _topic.replace("\\", "\\\\").replace("#", "\\#");
    String escapedContent = _content.replace("\\", "\\\\").replace("#", "\\#");
    return escapedSender + "#" + escapedDate + "#" + escapedTopic + "#" + escapedContent;
}

public Mail(String mailStr) {
    // 先按非转义的#拆分(用正则匹配未被转义的#)
    String[] parts = mailStr.split("(?<!\\\\)#");
    // 反转义每个字段
    _sender = parts[0].replace("\\#", "#").replace("\\\\", "\\");
    _date = parts[1].replace("\\#", "#").replace("\\\\", "\\");
    _topic = parts[2].replace("\\#", "#").replace("\\\\", "\\");
    _content = parts[3].replace("\\#", "#").replace("\\\\", "\\");
}

这个方法能支持任意字符,但需要处理转义逻辑,相对繁琐。

方案3:长度前缀法

给每个字段前面加上该字段的字符长度,拆分时先读取长度,再截取对应长度的内容,完全不受字段内字符影响。

修改Mail类的toString()和构造器:

@Override
public String toString() {
    // 用|作为长度和内容的分隔符(不会和长度数字冲突)
    return _sender.length() + "|" + _sender
            + "|" + _date.length() + "|" + _date
            + "|" + _topic.length() + "|" + _topic
            + "|" + _content.length() + "|" + _content;
}

public Mail(String mailStr) {
    int index = 0;
    // 读取sender
    int lenEnd = mailStr.indexOf("|", index);
    int senderLen = Integer.parseInt(mailStr.substring(index, lenEnd));
    index = lenEnd + 1;
    _sender = mailStr.substring(index, index + senderLen);
    index += senderLen + 1; // 跳过分隔符

    // 读取date
    lenEnd = mailStr.indexOf("|", index);
    int dateLen = Integer.parseInt(mailStr.substring(index, lenEnd));
    index = lenEnd + 1;
    _date = mailStr.substring(index, index + dateLen);
    index += dateLen + 1;

    // 读取topic
    lenEnd = mailStr.indexOf("|", index);
    int topicLen = Integer.parseInt(mailStr.substring(index, lenEnd));
    index = lenEnd + 1;
    _topic = mailStr.substring(index, index + topicLen);
    index += topicLen + 1;

    // 读取content(最后一段)
    lenEnd = mailStr.indexOf("|", index);
    int contentLen = Integer.parseInt(mailStr.substring(index, lenEnd));
    index = lenEnd + 1;
    _content = mailStr.substring(index, index + contentLen);
}

这个方法逻辑清晰,不会有字符冲突问题,实现起来也直观。

内容的提问来源于stack exchange,提问作者gegenphase

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:54:19