手机短信备份文件sms.vmsg文件解析(Java版)

这篇文章介绍了如何将sms.vmsg文件中的密文转换为可读消息,内容涉及深圳警方关于春节期间烟花爆竹管理的公告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sms.vmsg文件是可以直接用Windows记事本打开的,打开后看到的内容格式如下

BEGIN:VMSG
VERSION:1.1
BEGIN:VCARD
TEL:10010
END:VCARD
BEGIN:VBODY
X-BOX:INBOX
X-READ:READ
X-SEEN:1
X-SIMID:0
X-LOCKED:UNLOCKED
X-TYPE:SMS
Date:2019/02/04 09:48:24
Subject;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:=E6=B7=B1=E5=9C=B3=E8=AD=A6=E6=96=B9=E6=8F=90=E7=A4=BA=EF=BC=9A=E5=85=A8=E5=B8=82=E7=A6=81=E5=94=AE=E3=80=81=E7=A6=81=E7=87=83=E3=80=81=E7=A6=81=E6=94=BE=E7=83=9F=E8=8A=B1=E7=88=86=E7=AB=B9=E3=80=82=E4=B8=BA=E7=BB=B4=E6=8A=A4=E5=85=AC=E5=85=B1=E5=AE=89=E5=85=A8=EF=BC=8C=E8=90=A5=E9=80=A0=E5=AE=89=E5=85=A8=E8=88=92=E9=80=82=E7=9A=84=E5=9F=8E=E5=B8=82=E7=8E=AF=E5=A2=83=EF=BC=8C=E8=AF=B7=E5=B9=BF=E5=A4=A7=E5=B8=82=E6=B0=91=E4=B8=8D=E8=B4=AD=E4=B9=B0=E3=80=81=E4=B8=8D=E5=82=A8=E5=AD=98=E3=80=81=E4=B8=8D=E7=87=83=E6=94=BE=E7=83=9F=E8=8A=B1=E7=88=86=E7=AB=B9=EF=BC=8C=E5=85=B1=E5=88=9B=E6=96=B0=E6=98=A5=E4=BD=B3=E8=8A=82=E5=B9=B3=E5=AE=89=E7=A5=A5=E5=92=8C=E3=80=82
END:VBODY
END:VMSG

你可能不认识,所以要使用以下代码进行转换,输出可读文字

sms,deliver,    10010,,,2019.02.04 09:48,16,深圳警方提示:全市禁售、禁燃、禁放烟花爆竹。为维护公共安全,营造安全舒适的城市环境,请广大市民不购买、不储存、不燃放烟花爆竹,共创新春佳节平安祥和。

ConvertMain.java

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class ConvertMain {

    public static void main(String[] args) {
        StringBuilder convertedString = new StringBuilder();
        Map<String, Integer> map = new HashMap<String, Integer>();
        int count = 1;
        try {
            Scanner scanner = new Scanner(new File("e:\\sms.vmsg"));
            StringBuilder builder = new StringBuilder();
            String str = new String();
            Msg msg = new Msg();
            do {
                str = scanner.nextLine();
                if (str.equals("BEGIN:VMSG")) {
                    builder.append("sms,");
                } else if (str.startsWith("TEL")) {
                    // 加入TEL
                    msg.setTel(str.substring(4));
                    if (!map.keySet().contains(str.substring(4))) {
                        map.put(str.substring(4), count++);
                    }

                } else if (str.startsWith("X-BOX")) {
                    // 加入投送方式
                    if (str.endsWith("INBOX")) {
                        msg.setX_box(2);
                    } else if (str.endsWith("SENDBOX")) {
                        msg.setX_box(3);
                    }
                } else if (str.startsWith("Date")) {
                    // 加入日期
                    msg.setDate(str.substring(5).replaceAll("/", "\\.")
                            .substring(0, 16));
                } else if (str.startsWith("Subject")) {
                    // 加入内容
                    StringBuilder builder2 = new StringBuilder();
                    builder2.append(str.substring(48));
                    String str1 = scanner.nextLine();
                    while (!str1.startsWith("END")) {
                        builder2.append(str1);
                        str1 = scanner.nextLine();
                    }
                    String source = builder2.toString().replaceAll("==", "=");
                    byte[] array = getBytes(source.toCharArray());
                    msg.setContent(QuotedPrintable.decode(array, "UTF-8")
                            .replaceAll("\\s+", ""));
                }
                if (msg.getContent() != null && msg.getDate() != null
                        && msg.getTel() != null && msg.getX_box() != 0) {
                    if (msg.getX_box() == 2) {
                        // deliver + ",count"
                        builder.append("deliver,    " + msg.getTel() + ",,,"
                                + msg.getDate() + "," + map.get(msg.getTel())
                                + "," + msg.getContent() + "\r");
                    } else if ((msg.getX_box() == 3)) {
                        // send
                        builder.append("submit,,    " + msg.getTel() + ",,"
                                + msg.getDate() + "," + map.get(msg.getTel())
                                + "," + msg.getContent() + "\r");
                    }
                    convertedString.append(builder.toString());
                    System.out.println(builder.toString());
                    msg = new Msg();
                    builder = new StringBuilder();
                }
            } while (str != "" && str != null);

        } catch (Exception e) {
        }
        System.out.println(convertedString);
    }

    private static byte[] getBytes(char[] chars) {
        Charset cs = Charset.forName("UTF-8");
        CharBuffer cb = CharBuffer.allocate(chars.length);
        cb.put(chars);
        cb.flip();
        ByteBuffer bb = cs.encode(cb);

        return bb.array();

    }

    /*// byte转char
    private static char[] getChars(byte[] bytes) {
        Charset cs = Charset.forName("UTF-8");
        ByteBuffer bb = ByteBuffer.allocate(bytes.length);
        bb.put(bytes);
        bb.flip();
        CharBuffer cb = cs.decode(bb);

        return cb.array();
    }*/
}

Msg.java

public class Msg {

    private String tel;
    private int x_box;
    private String date;
    private String content;

    public String getTel() {
        return tel;
    }
    public void setTel(String tel) {
        this.tel = tel;
    }
    public int getX_box() {
        return x_box;
    }
    public void setX_box(int x_box) {
        this.x_box = x_box;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}

QuotedPrintable.java

import java.io.UnsupportedEncodingException;


public class QuotedPrintable {

    private final static byte TAB = 0x09; // /t
    private final static byte LF = 0x0A; // /n
    private final static byte CR = 0x0D; // /r
    //private final static byte SPACE = 0x20; // ' '
    private final static byte EQUALS = 0x3D; // '='

    private final static byte LIT_START = 0x21;
    private final static byte LIT_END = 0x7e;

    private final static int MAX_LINE_LENGTH = 76;

    private static int mCurrentLineLength = 0;

    /**
     * A method to decode quoted printable encoded data.
     * It overrides the same input byte array to save memory. Can be done
     * because the result is surely smaller than the input.
     *
     * @param qp
     * a byte array to decode.
     * @return the length of the decoded array.
     */
    public static int decode(byte [] qp) {
        int qplen = qp.length;
        int retlen = 0;

        for (int i=0; i < qplen; i++) {
            // Handle encoded chars
            if (qp[i] == '=') {
                if (qplen - i > 2) {
                    // The sequence can be complete, check it
                    if (qp[i+1] == CR && qp[i+2] == LF) {
                        // soft line break, ignore it
                        i += 2;
                        continue;

                    } else if (isHexDigit(qp[i+1]) && isHexDigit(qp[i+2]) ) {
                        // convert the number into an integer, taking
                        // the ascii digits stored in the array.
                        qp[retlen++]=(byte)(getHexValue(qp[i+1])*16
                                + getHexValue(qp[i+2]));

                        i += 2;
                        continue;

                    } else {
                        System.out.println("decode: Invalid sequence = " + qp[i+1] + qp[i+2]);
                    }
                }
                // In all wrong cases leave the original bytes
                // (see RFC 2045). They can be incomplete sequence,
                // or a '=' followed by non hex digit.
            }

            // RFC 2045 says to exclude control characters mistakenly
            // present (unencoded) in the encoded stream.
            // As an exception, we keep unencoded tabs (0x09)
            if( (qp[i] >= 0x20 && qp[i] <= 0x7f) ||
                    qp[i] == TAB || qp[i] == CR || qp[i] == LF) {
                qp[retlen++] = qp[i];
            }
        }

        return retlen;
    }

    private static boolean isHexDigit(byte b) {
        return ( (b>=0x30 && b<=0x39) || (b>=0x41&&b<=0x46) );
    }

    private static byte getHexValue(byte b) {
        return (byte)Character.digit((char)b, 16);
    }

    /**
     *
     * @param qp Byte array to decode
     * @param enc The character encoding of the returned string
     * @return The decoded string.
     */
    public static String decode(byte[] qp, String enc) {
        int len=decode(qp);
        try {
            return new String(qp, 0, len, enc);
        } catch (UnsupportedEncodingException e) {
            return new String(qp, 0, len);
        }
    }

    /**
     * A method to encode data in quoted printable
     *
     * @param content
     * The string to be encoded
     * @param enc
     * The character encoding of the content string
     * @return The encoded string. If the content is null, return null.
     */
    public static String encode(String content, String enc) {
        if (content == null)
            return null;

        byte[] str = null;
        try {
            str = content.getBytes(enc);
        } catch (UnsupportedEncodingException e) {
            str = content.getBytes();
        }
        return encode(str);
    }
    /**
     * A method to encode data in quoted printable
     *
     * @param content
     * The byte array of the string to be encoded
     * @return The encoded string. If the content is null, return null.
     */
    public static String encode(byte[] content) {
        if (content == null)
            return null;

        StringBuilder out = new StringBuilder();

        mCurrentLineLength = 0;
        int requiredLength = 0;

        for (int index = 0; index < content.length; index++) {
            byte c = content[index];

            if (c >= LIT_START && c <= LIT_END && c != EQUALS) {
                requiredLength = 1;
                checkLineLength(requiredLength, out);
                out.append((char)c);
            } else {
                requiredLength = 3;
                checkLineLength(requiredLength, out);
                out.append('=');
                out.append(String.format("%02X", c));
            }
        }
        return out.toString();
    }

    private static void checkLineLength(int required, StringBuilder out) {
        if (required + mCurrentLineLength > MAX_LINE_LENGTH - 1) {
            out.append("=/r/n");
            mCurrentLineLength = required;
        } else
            mCurrentLineLength += required;
    }

}

原文链接:http://blog.chinaunix.net/uid-29618857-id-4707171.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值