有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Whatsapp将历史解析为对话框json

我有一个Whatsapp日志文件,看起来像这样:(时间戳不准确)

[15.11.16, 16:13:29] Person A: Hello
[15.11.16, 16:13:45] Person B: This is
a multiline
message
[15.11.16, 16:14:12] Person A: Wow, so cool 😂

我想将它们解析为json格式,如下所示:

{
  "msg": [
    {
      "sender": "Person A",
      "message": "Hello",
      "time": 1479205511000,
      "response": {
        "sender": "Person B",
        "message": "This is\na multiline\nmessage",
        "time": 1479205536000
      }
    },
    ...
  ]
}

首先,信息将分为三部分:

  • 时间(作为时间戳)
  • 姓名
  • 消息(如果是多行消息,则应转义换行符)

另一个正在发生的事情是响应事件,它选择了一个主要人物(在本例中是“人物A”)。然后,它从顶部开始查看每条消息,查找此人的第一条消息(称为“主消息”)。如果找到一条,它将查找另一个人的响应(下一条消息(称为“响应”))。如果下一条消息再次来自主要用户,它将选择该消息作为“主要消息”,并查找下一条消息

例如:

Person A: Hi
Person B: Hi
Person A: This is cool
Person A: I am cool
Person B: Ah ok

在本例中,我们将选择“Person A”作为主要人物。第一条信息是由我们的主要人物写的,所以它将是我们的主要信息。下一条信息来自另一个人,所以这将是我们的回应

{
    "sender":"Person A",
    "message":"Hi",
    "time":1479205511000,
    "response":{
        "sender":"Person B",
        "message":"Hi",
        "time":1479205536000
    }
}

下一条信息再次来自我们的主要人物,所以我们将把它作为我们的主要信息。但是后面的消息不是由另一个人发出的,所以我们将跳过前面的消息。之后的信息是我们的对手再次发出的,所以这将是我们的回应

{
    "sender":"Person A",
    "message":"I am cool",
    "time":1479205511000,
    "response":{
        "sender":"Person B",
        "message":"Ah ok",
        "time":1479205536000
    }
}

我们现在有了这样一个JSON:

{
    "msg":[
        {
            "sender":"Person A",
            "message":"Hi",
            "time":1479205511000,
            "response":{
                "sender":"Person B",
                "message":"Hi",
                "time":1479205536000
            }
        },
        {
            "sender":"Person A",
            "message":"I am cool",
            "time":1479205511000,
            "response":{
                "sender":"Person B",
                "message":"Ah ok",
                "time":1479205536000
            }
        }
    ]
}

有几个问题:

  • 多行消息
  • 非UTF-8字符,如'😂' 这一点应该避免->;文本编码
  • 巨大的原木(多达10万行)>;表现
  • 有时,行以控制字符开头,比如字符串。startsWith并不总是完美地工作

正如你可能已经猜到的,我使用的语言是Java

如果有任何问题或不清楚的信息,请随时提请我注意


共 (1) 个答案

  1. # 1 楼答案

    我只是自己做的。首先,我创建了一个名为“Message”的类:

    public class Message {
    
        public String sender;
    
        public String time;
    
        public String message;
    
        public String plainMessage;
    
        public Message(String line) {
            String[] array = line.split("]");
    
            time = clean(array[0].replace("[", ""));
    
            array = Main.removeElements(array, array[0]);
    
            line = Main.join("]", array);
    
            array = line.split(":");
    
            sender = clean(array[0]);
    
            array = Main.removeElements(array, array[0]);
    
            line = Main.join(":", array);
    
            plainMessage = line;
    
            line = StringEscapeUtils.escapeJava(line);
            line = escapeUmlaut(line);
    
            message = StringEscapeUtils.escapeJson(line);
        }
    
        private String escapeUmlaut(String input) {
            String output = input.replace("ü", "ue")
                    .replace("ö", "oe")
                    .replace("ä", "ae")
                    .replace("ß", "ss");
    
            output = output.replace("Ü(?=[a-zäöüß ])", "Ue")
                    .replace("Ö(?=[a-zäöüß ])", "Oe")
                    .replace("Ä(?=[a-zäöüß ])", "Ae");
    
            output = output.replace("Ü", "UE")
                    .replace("Ö", "OE")
                    .replace("Ä", "AE");
    
            return output;
        }
    
        public static String clean(String what) {
            char[] chars = what.toCharArray();
            what = "";
            char[] allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890[](){}=?!\\§$%&/'#*+;,:.-_<>|".toCharArray();
            for (char c : chars) {
                for (char cc : allowed) {
                    if (cc == c) {
                        what += c;
                    }
                }
            }
    
            return what;
        }
    
    }
    

    此类的任务是解析消息

    这是我们组合多行消息的方式:

    ArrayList <String> parsed = new ArrayList <String> ();
    
    for (int x = 0; x < size; x++) {
        String line = list.get(x);
    
        if (startsWith(line, '[')) {
            parsed.add(line);
        } else {
            int lastn = parsed.size() - 1;
            String last = parsed.get(lastn);
            last += "\\n" + line;
            parsed.set(lastn, last);
        }
    }
    

    下面是如何使用该类:

    Message MainMessage = null;
    
    String json = "";
    
    boolean firstWrite = false;
    
    final Pattern pattern = Pattern.compile("[a-zA-Z0-9]+", Pattern.MULTILINE);
    
    for (int x = 0; x < size; x++) {
        result = "";
        progressBar.setValue(x);
    
        String line = parsed.get(x);
    
        if (config.debug) {
            System.out.println(line);
        }
    
        Message message = new Message(line);
        final Matcher matcher = pattern.matcher(message.plainMessage);
    
        if (!matcher.find()) {
            continue;
        }
    
        if (x == 0 && mainSender == null) {
            mainSender = message.sender;
            MainMessage = message;
            continue;
        }
    
        if (mainSender.equals(message.sender)) {
            MainMessage = message;
        } else if (message.sender != mainSender && MainMessage != null) {
            json = "\n{\"sender\": \"" + MainMessage.sender + "\", \"message\": \"" + MainMessage.message + "\", \"response\": ";
            json += "{\"sender\": \"" + message.sender + "\", \"message\": \"" + message.message + "\"}}";
            if (firstWrite) {
                json = "," + json;
            }
    
            Files.write(Paths.get(
                export), json.getBytes(), StandardOpenOption.APPEND);
            json = "";
            MainMessage = null;
    
            firstWrite = true;
        }
    }