jd-gui是一个非常好的java反编译工具。但是有一点就是用它导出的java文件与源代码中的行号大部分是对应不上的。jd-gui采用将行号以注释的方式显示出来比如在某行开头有个这个”/* 100 */” 表示这行代码在源代码里的第100行。这样的话我们在没有源文件的时候又希望能够远程调试代码几乎是不可能的,并且对于有代码洁癖的人来说阅读带有这么多无用的注释内容更痛苦了。在这里写了个小工具,将行号尽可能的和源文件的行号对应上,同时删除jd-gui加上的注解。比如你的java文件在D:\test\source下那么会在D:\test\下创建一个”source+当前时间戳”的文件夹,格式化后的代码就在这里面。
package cn.wensiqun.utils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class RemoveContentUtil
{
private static String regex = "\\/\\*[\\p{ASCII}]*?\\*\\/\\s?";
//反编译后的java文件目录
private static String directory = "D:\\TEMP\\sources";
private static String newDirectory = "";
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException
{
start();
}
public static void start() throws IOException{
File folder = new File(directory);
directory = folder.getCanonicalPath();
File parentFolder = folder.getParentFile();
newDirectory = parentFolder.getCanonicalPath() + "\\" + folder.getName() + System.currentTimeMillis() + "\\";
File[] files = folder.listFiles();
loopFile(files);
}
public static void loopFile(File[] files) throws IOException{
if(files == null){
return;
}
for(File f : files){
if(f.isFile()){
if(f.getName().endsWith(".java")){
removeContent(directory, newDirectory, f, true);
}else{
removeContent(directory, newDirectory, f, false);
}
}else{
loopFile(f.listFiles());
}
}
}
public static void removeContent(String oldDir, String newDir, File file, boolean remove) throws IOException{
List<String> lines = FileUtils.readLines(file);
String relocationString = relocationLineNumber(lines);
String newContent = remove ? relocationString.replaceAll(regex, "") : relocationString;
File newFile = new File(file.getCanonicalPath().replace(oldDir, newDir));
FileUtils.write(newFile, newContent);
}
public static String relocationLineNumber(List<String> lines){
int currentLine = 0;
StringBuilder content = new StringBuilder();
for(String line : lines){
currentLine++;
int num = readLineNumber(line);
if(num != -1){
while(currentLine < num){
currentLine++;
content.append(IOUtils.LINE_SEPARATOR);
}
}
content.append(line).append(IOUtils.LINE_SEPARATOR);
}
//IOUtils.LINE_SEPARATOR;
return content.toString();
}
private static int readLineNumber(String line){
int start = line.indexOf("/*");
int end = line.indexOf("*/");
if(start > -1 && end > start){
//check is annotation
String left = line.substring(end + 2).trim();
if(left.startsWith("@")){
return -1;
}
String linNum = line.substring(start + 2, end).trim();
try{
return Integer.parseInt(linNum);
}catch(NumberFormatException e){
return -1;
}
}
return -1;
}
}