java批量解析微信dat文件
1.WxChatImgRevert2.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JTextArea;
public class WxChatImgRevert2 {
public static void convert(String path, String targetPath, JTextArea area) {
File file = new File(path);
if (file.isFile())
parseFile(file, targetPath, new AtomicInteger(0), new AtomicReference<>(Integer.valueOf(1)), 1, area);
File[] files = file.listFiles();
if (files == null)
return;
int size = files.length;
System.out.println(\"总共\"+ size + \"个文件\");
AtomicReference<Integer> integer = new AtomicReference<>(Integer.valueOf(0));
AtomicInteger x = new AtomicInteger();
for (File file1 : files) {
if (file1.isFile()) {
Object[] xori = getXor(file1);
if (xori != null && xori[1] != null)
x.set(((Integer)xori[1]).intValue());
break;
}
}
File targetFile = new File(targetPath);
if (!targetFile.exists())
targetFile.mkdirs();
Arrays.<File>stream(files).parallel().forEach(file1 -> parseFile(file1, targetPath, x, integer, size, area));
area.append(\"\\n解析完毕\");
System.out.println(\"解析完毕\");
}
private static void parseFile(File file1, String targetPath, AtomicInteger x, AtomicReference<Integer> integer, int size, JTextArea area) {
if (file1.isDirectory()) {
String[] newTargetPath = file1.getPath().split(\"/|\\\\\\\\\");
File targetFile1 = new File(targetPath + File.separator + newTargetPath[newTargetPath.length - 1]);
if (!targetFile1.exists())
targetFile1.mkdirs();
convert(file1.getPath(), targetPath + File.separator + newTargetPath[newTargetPath.length - 1], area);
return;
}
Object[] xor = getXor(file1);
if (x.get() == 0 && xor[1] != null && ((Integer)xor[1]).intValue() != 0)
x.set(((Integer)xor[1]).intValue());
xor[1] = (xor[1] == null) ? Integer.valueOf(x.get()) : xor[1];
try(InputStream reader = new FileInputStream(file1);
OutputStream writer = new FileOutputStream(targetPath + File.separator + file1
.getName().split(\"\\\\.\")[0] + ((xor[0] != null) ? (\".\" + xor[0]) : \"\"))) {
byte[] bytes = new byte[10240];
int b;
while ((b = reader.read(bytes)) != -1) {
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte)(bytes[i] ^ ((Integer)xor[1]).intValue());
if (i == b - 1)
break;
}
writer.write(bytes, 0, b);
writer.flush();
}
integer.set(Integer.valueOf(((Integer)integer.get()).intValue() + 1));
area.append(\"\\n\" + file1.getName() + \"大小(\"+ (file1.length() / 1000.0D) + \"kb,异或值\"+ xor[1] + \"),进度\" + integer.get() + \"/\" + size);
System.out.println(file1.getName() + \"大小(\"+ (file1.length() / 1000.0D) + \"kb,异或值\"+ xor[1] + \"),进度\" + integer.get() + \"/\" + size);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Object[] getXor(File file) {
Object[] xor = null;
if (file != null) {
byte[] bytes = new byte[4];
try (InputStream reader = new FileInputStream(file)) {
reader.read(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
xor = getXor(bytes);
}
return xor;
}
private static Object[] getXor(byte[] bytes) {
Object[] xorType = new Object[2];
int[] xors = new int[3];
for (Map.Entry<String, String> type : FILE_TYPE_MAP.entrySet()) {
String[] hex = { String.valueOf(((String)type.getKey()).charAt(0)) + ((String)type.getKey()).charAt(1), String.valueOf(((String)type.getKey()).charAt(2)) + ((String)type.getKey()).charAt(3), String.valueOf(((String)type.getKey()).charAt(4)) + ((String)type.getKey()).charAt(5) };
xors[0] = bytes[0] & 0xFF ^ Integer.parseInt(hex[0], 16);
xors[1] = bytes[1] & 0xFF ^ Integer.parseInt(hex[1], 16);
xors[2] = bytes[2] & 0xFF ^ Integer.parseInt(hex[2], 16);
if (xors[0] == xors[1] && xors[1] == xors[2]) {
xorType[0] = type.getValue();
xorType[1] = Integer.valueOf(xors[0]);
break;
}
}
return xorType;
}
private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>();
static {
getAllFileType();
}
private static void getAllFileType() {
FILE_TYPE_MAP.put(\"ffd8ffe000104a464946\", \"jpg\");
FILE_TYPE_MAP.put(\"89504e470d0a1a0a0000\", \"png\");
FILE_TYPE_MAP.put(\"47494638396126026f01\", \"gif\");
FILE_TYPE_MAP.put(\"49492a00227105008037\", \"tif\");
FILE_TYPE_MAP.put(\"424d228c010000000000\", \"bmp\");
FILE_TYPE_MAP.put(\"424d8240090000000000\", \"bmp\");
FILE_TYPE_MAP.put(\"424d8e1b030000000000\", \"bmp\");
FILE_TYPE_MAP.put(\"41433130313500000000\", \"dwg\");
FILE_TYPE_MAP.put(\"3c21444f435459504520\", \"html\");
FILE_TYPE_MAP.put(\"3c21646f637479706520\", \"htm\");
FILE_TYPE_MAP.put(\"48544d4c207b0d0a0942\", \"css\");
FILE_TYPE_MAP.put(\"696b2e71623d696b2e71\", \"js\");
FILE_TYPE_MAP.put(\"7b5c727466315c616e73\", \"rtf\");
FILE_TYPE_MAP.put(\"38425053000100000000\", \"psd\");
FILE_TYPE_MAP.put(\"46726f6d3a203d3f6762\", \"eml\");
FILE_TYPE_MAP.put(\"d0cf11e0a1b11ae10000\", \"doc\");
FILE_TYPE_MAP.put(\"5374616E64617264204A\", \"mdb\");
FILE_TYPE_MAP.put(\"252150532D41646F6265\", \"ps\");
FILE_TYPE_MAP.put(\"255044462d312e360d25\", \"pdf\");
FILE_TYPE_MAP.put(\"2e524d46000000120001\", \"rmvb\");
FILE_TYPE_MAP.put(\"464c5601050000000900\", \"flv\");
FILE_TYPE_MAP.put(\"00000020667479706973\", \"mp4\");
FILE_TYPE_MAP.put(\"49443303000000000f76\", \"mp3\");
FILE_TYPE_MAP.put(\"000001ba210001000180\", \"mpg\");
FILE_TYPE_MAP.put(\"3026b2758e66cf11a6d9\", \"wmv\");
FILE_TYPE_MAP.put(\"524946464694c9015741\", \"wav\");
FILE_TYPE_MAP.put(\"52494646d07d60074156\", \"avi\");
FILE_TYPE_MAP.put(\"4d546864000000060001\", \"mid\");
FILE_TYPE_MAP.put(\"504b0304140000000800\", \"zip\");
FILE_TYPE_MAP.put(\"526172211a0700cf9073\", \"rar\");
FILE_TYPE_MAP.put(\"235468697320636f6e66\", \"ini\");
FILE_TYPE_MAP.put(\"504b03040a0000000000\", \"jar\");
FILE_TYPE_MAP.put(\"4d5a9000030000000400\", \"exe\");
FILE_TYPE_MAP.put(\"3c25402070616765206c\", \"jsp\");
FILE_TYPE_MAP.put(\"4d616e69666573742d56\", \"mf\");
FILE_TYPE_MAP.put(\"3c3f786d6c2076657273\", \"xml\");
FILE_TYPE_MAP.put(\"efbbbf2f2a0d0a53514c\", \"sql\");
FILE_TYPE_MAP.put(\"7061636b616765207765\", \"java\");
FILE_TYPE_MAP.put(\"406563686f206f66660d\", \"bat\");
FILE_TYPE_MAP.put(\"1f8b0800000000000000\", \"gz\");
FILE_TYPE_MAP.put(\"6c6f67346a2e726f6f74\", \"properties\");
FILE_TYPE_MAP.put(\"cafebabe0000002e0041\", \"class\");
FILE_TYPE_MAP.put(\"49545346030000006000\", \"chm\");
FILE_TYPE_MAP.put(\"04000000010000001300\", \"mxp\");
FILE_TYPE_MAP.put(\"504b0304140006000800\", \"docx\");
FILE_TYPE_MAP.put(\"6431303a637265617465\", \"torrent\");
FILE_TYPE_MAP.put(\"494d4b48010100000200\", \"264\");
FILE_TYPE_MAP.put(\"6D6F6F76\", \"mov\");
FILE_TYPE_MAP.put(\"FF575043\", \"wpd\");
FILE_TYPE_MAP.put(\"CFAD12FEC5FD746F\", \"dbx\");
FILE_TYPE_MAP.put(\"2142444E\", \"pst\");
FILE_TYPE_MAP.put(\"AC9EBD8F\", \"qdf\");
FILE_TYPE_MAP.put(\"E3828596\", \"pwl\");
FILE_TYPE_MAP.put(\"2E7261FD\", \"ram\");
}
}
2.window.java
import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.Point;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class window {
public static void main(String[] args) {
JFrame frame = new JFrame(\"微信加密图片\");
frame.setResizable(false);
frame.setSize(540, 525);
frame.setLocationRelativeTo((Component)null);
frame.setDefaultCloseOperation(3);
JPanel panel = new JPanel();
placeComponents(panel);
frame.add(panel);
frame.setVisible(true);
}
private static void placeComponents(JPanel panel) {
panel.setLayout((LayoutManager)null);
JLabel wxLabel = new JLabel(\"微信数据存储地址\");
wxLabel.setBounds(10, 20, 120, 25);
JTextField wxText = new JTextField(20);
wxText.setBounds(130, 20, 300, 25);
JButton wxButton = new JButton(\"浏览\");
wxButton.setBounds(440, 20, 80, 25);
wxButton.addActionListener(e -> openChoose(wxText));
JLabel outLabel = new JLabel(\"输出地址\");
outLabel.setBounds(10, 50, 120, 25);
panel.add(outLabel);
JTextField outText = new JTextField(20);
outText.setBounds(130, 50, 300, 25);
JLabel outlabel = new JLabel(\"输出日志\");
outlabel.setBounds(10, 120, 120, 25);
JButton outButton = new JButton(\"浏览\");
outButton.setBounds(440, 50, 80, 25);
outButton.addActionListener(e -> openChoose(outText));
JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setAutoscrolls(true);
textArea.setEditable(false);
JScrollPane jScrollPane = new JScrollPane(textArea);
jScrollPane.setHorizontalScrollBarPolicy(30);
jScrollPane.setVerticalScrollBarPolicy(20);
jScrollPane.setBounds(10, 150, 515, 300);
jScrollPane.setAutoscrolls(true);
int height = 10;
Point p = new Point();
p.setLocation(0, textArea.getLineCount() * height);
jScrollPane.getViewport().setViewPosition(p);
JButton convertButton = new JButton(\"转换\");
convertButton.setBounds(215, 90, 80, 25);
convertButton.addActionListener(e -> {
if (!(new File(wxText.getText())).exists()) {
JOptionPane.showMessageDialog(panel, \"微信存储地址不存在\", \"警告\", 2);
return;
}
WxChatImgRevert2.convert(wxText.getText(), outText.getText(), textArea);
JOptionPane.showMessageDialog(panel, \"转换完成\", \"完成提示\", -1);
});
JButton exitButton = new JButton(\"退出\");
exitButton.setBounds(215, 455, 80, 25);
exitButton.addActionListener(e -> System.exit(0));
panel.add(wxLabel);
panel.add(wxText);
panel.add(wxButton);
panel.add(outText);
panel.add(outlabel);
panel.add(outButton);
panel.add(jScrollPane);
panel.add(convertButton);
panel.add(exitButton);
}
private static void openChoose(JTextField textField) {
JFileChooser wxChooser = new JFileChooser(textField.getText());
wxChooser.setFileSelectionMode(2);
int status = wxChooser.showOpenDialog(null);
if (status != 1) {
File file = wxChooser.getSelectedFile();
textField.setText(file.getPath());
}
}
}
直接拷贝上面两个代码,在idea中粘贴就会创建对应文件,将两个java文件放到一起之后运行window.main之后就会打开程序
然后选择自己微信聊天记录的位置和要输出的位置点击转换就可以了
忘记之前是从哪找到的了,如有侵权请联系本人,看到消息后会尽快处理
评论区