关于lua反编译文件中文字符显示为10进制字符的处理
之前遇到了lua文件反编译后,中文显示的是10进制字符的问题,网上搜了下,没看到什么批量处理的方法,就自己研究用Java写了一个批量处理工具。
原理很简单,就是先把10进制的数字转换成16进制,然后再用URLDecoder解码就行了。
注:代码仅供参考,如有bug或者更优的方法,烦请留言指出。大家一起学习进步!
代码如下
package com.zzb;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author zhengzhibiao
* @date 2019-12-09 14:01
*/
public class Test {
/**
* 匹配10进制字符的正则表达式
*/
private static final Pattern PATTERN = Pattern.compile("(\\\\\\d{3}){3}");
/**
* 日期格式化
*/
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.ms");
/**
* 读取文件的目录路径
*/
private static final String READ_DIRECTORY_PATH = "D:\\path1";
/**
* 写入文件的目录路径
*/
private static final String WRITE_DIRECTORY_PATH = "D:\\path2";
/**
* 统计解析的文件总数
*/
private static int COUNT = 0;
/**
* 解析成功的文件数量
*/
private static int SUCCESS = 0;
/**
* 解析失败的文件数量
*/
private static int FAIL = 0;
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
Date startDate = new Date(startTime);
System.out.println("解析文件-开始,当前时间:" + DATE_FORMAT.format(startDate));
start();
long endTime = System.currentTimeMillis();
Date endDate = new Date(endTime);
long second = (endTime - startTime) / 1000;
System.out.println("文件总数:" + COUNT + ",成功:" + SUCCESS + ",失败:" + FAIL);
System.out.println("解析文件-结束,当前时间:" + DATE_FORMAT.format(endDate) + ",共耗时:" + second + "秒。");
}
/**
* 开始解析
*/
private static void start() {
File fileDirectory = new File(READ_DIRECTORY_PATH);
if (!fileDirectory.exists()) {
System.out.println("[" + READ_DIRECTORY_PATH + "]目录不存在!");
return;
}
if (!fileDirectory.isDirectory()) {
System.out.println("[" + READ_DIRECTORY_PATH + "]不是一个目录!");
return;
}
readDirectory(fileDirectory);
}
/**
* 读取目录
* @param fileDirectory 目录文件对象
*/
private static void readDirectory(File fileDirectory) {
File[] files = fileDirectory.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File file : files) {
if (file.isFile()) {
COUNT++;
List<String> readList = readFile(file);
writeFile(file.getName(), readList);
continue;
}
if (file.isDirectory()) {
readDirectory(file);
}
}
}
/**
* 一行一行读取文件
* @param file 读取的文件对象
* @return 读取到的字符串集合
*/
private static List<String> readFile(File file) {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
List<String> readList = new ArrayList<>();
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis, "UTF-8");
br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null) {
readList.add(line);
}
System.out.println("读取文件[" + file.getPath() + "]-成功!");
} catch (Exception e) {
System.out.println("读取文件[" + file.getPath() + "]-失败:" + e.getMessage());
} finally {
// 注意关闭的先后顺序,先打开的后关闭,后打开的先关闭
try {
if (br != null) {
br.close();
}
} catch (Exception e) {
}
try {
if (isr != null) {
isr.close();
}
} catch (Exception e) {
}
try {
if (fis != null) {
fis.close();
}
} catch (Exception e) {
}
}
return readList;
}
/**
* 一行一行写入文件
* @param fileName 文件名(带后缀)
* @param list 需要写入的字符串集合
*/
private static void writeFile(String fileName, List<String> list) {
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter bw = null;
String newFilePath = WRITE_DIRECTORY_PATH + "\\" + fileName;
try {
File writeDirectory = new File(WRITE_DIRECTORY_PATH);
if (!writeDirectory.exists()) {
writeDirectory.mkdirs();
}
File writeFile = new File(newFilePath);
if (!writeFile.exists()) {
writeFile.createNewFile();
}
//写入中文字符时解决中文乱码问题
fos = new FileOutputStream(writeFile);
osw = new OutputStreamWriter(fos, "UTF-8");
bw = new BufferedWriter(osw);
for (String str : list) {
String newStr = strConvert(str);
bw.write(newStr + "\t\n");
}
SUCCESS++;
System.out.println("解析文件[" + newFilePath + "]-成功!");
} catch (Exception e) {
FAIL++;
System.out.println("解析文件[" + newFilePath + "]-失败:" + e.getMessage());
} finally {
// 注意关闭的先后顺序,先打开的后关闭,后打开的先关闭
try {
if (bw != null) {
bw.close();
}
} catch (Exception e) {
}
try {
if (osw != null) {
osw.close();
}
} catch (Exception e) {
}
try {
if (fos != null) {
fos.close();
}
} catch (Exception e) {
}
}
}
/**
* 解析字符串
* @param oldStr 需要解析的字符串
* @return
*/
private static String strConvert(String oldStr) {
// 现在创建 matcher 对象
Matcher matcher = PATTERN.matcher(oldStr);
while (matcher.find()) {
try {
//每一个符合正则的字符串
String str = matcher.group();
String[] array = str.split("\\\\");
StringBuilder sb = new StringBuilder();
for (String s : array) {
if (s == null || "".equals(s)) {
continue;
}
s = Integer.toHexString(Integer.parseInt(s));
sb.append("%").append(s);
}
String newStr = URLDecoder.decode(sb.toString(), "UTF-8");
str = str.replaceAll("\\\\", "\\\\\\\\");
oldStr = oldStr.replaceAll(str, newStr);
} catch (Exception e) {
e.printStackTrace();
}
}
return oldStr;
}
}