FFxiv Log日志抽取格式化工具
最开始先说下log的生成规则好了 ffxiv在登入游戏之后 会在内存保存视窗内的log 需要在游戏内勾选选项才会有相关方面log生成 在内存中累计到1000条记录之后 会将其以特殊的方式 转存至个人资料夹中的壹系列log文档中 以达到释放内存效用 此工具只针对于已生…
最开始先说下log的生成规则好了
ffxiv在登入游戏之后
会在内存保存视窗内的log
需要在游戏内勾选选项才会有相关方面log生成
在内存中累计到1000条记录之后
会将其以特殊的方式
转存至个人资料夹中的壹系列log文档中
以达到释放内存效用
此工具只针对于已生成的log文档
对于即时生成的文档无效
(因为根本没读他
以下是code
package name.yumao.sqlog;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class test {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String logPatch="C:\\Users\\soc\\Desktop\\log";
File file = new File(logPatch);
String[] filelist = file.list();
int newerFile = 0;
long newerModified = new File(logPatch + File.separator + filelist[newerFile]).lastModified();
for (int i = 0; i < filelist.length; i++) {
File tmpFile = new File(logPatch + File.separator + filelist[i]);
if(tmpFile.lastModified()>newerModified){
newerModified = tmpFile.lastModified();
newerFile = i;
}
}
File outLog = new File("C:\\Users\\soc\\Documents\\ffxivlog.log");
OutputStream fis=new FileOutputStream(outLog);
OutputStreamWriter fw=new OutputStreamWriter(fis,"UTF-8");
// System.out.println("命中即时日志:" + filelist[newerFile]);
for (int filecount = 0; filecount < filelist.length; filecount++) {
// System.out.println("命中日志:" + filelist[filecount]);
RandomAccessFile randomAccessFile = new RandomAccessFile(logPatch + File.separator + filelist[filecount], "r");
// randomAccessFile.seek(0xfa8);
byte[] lengthBytes = new byte[4];
//读取文件头长度
randomAccessFile.seek(0x0);
int headerlen ;
lengthBytes[0] = randomAccessFile.readByte();
lengthBytes[1] = randomAccessFile.readByte();
lengthBytes[2] = randomAccessFile.readByte();
lengthBytes[3] = randomAccessFile.readByte();
int sleng = (int) ((lengthBytes[0] & 0xFF)
| ((lengthBytes[1] & 0xFF)<<8)
| ((lengthBytes[2] & 0xFF)<<16)
| ((lengthBytes[3] & 0xFF)<<24));
lengthBytes[0] = randomAccessFile.readByte();
lengthBytes[1] = randomAccessFile.readByte();
lengthBytes[2] = randomAccessFile.readByte();
lengthBytes[3] = randomAccessFile.readByte();
int eleng = (int) ((lengthBytes[0] & 0xFF)
| ((lengthBytes[1] & 0xFF)<<8)
| ((lengthBytes[2] & 0xFF)<<16)
| ((lengthBytes[3] & 0xFF)<<24));
headerlen = eleng - sleng;
// System.out.println(headerlen);
//读取转存文件长度 从0x008开始 到headerlen*4+8结束
randomAccessFile.seek(0x8);
List<Integer> strLength = new ArrayList<Integer>();
int value;
while(randomAccessFile.getFilePointer()<(headerlen*4+8)){
lengthBytes[0] = randomAccessFile.readByte();
lengthBytes[1] = randomAccessFile.readByte();
lengthBytes[2] = randomAccessFile.readByte();
lengthBytes[3] = randomAccessFile.readByte();
value = (int) ((lengthBytes[0] & 0xFF)
| ((lengthBytes[1] & 0xFF)<<8)
| ((lengthBytes[2] & 0xFF)<<16)
| ((lengthBytes[3] & 0xFF)<<24));
strLength.add(value);
}
// System.out.println(strLength.size());
byte[] tmp;
String logStr = "";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for(int i=0;i<strLength.size();i++){
if(i == 0){
tmp = new byte[strLength.get(i)];
for(int j=0;j<strLength.get(i);j++){
tmp[j]=randomAccessFile.readByte();
}
}else{
tmp = new byte[strLength.get(i)-strLength.get(i-1)];
for(int j=0;j<strLength.get(i)-strLength.get(i-1);j++){
tmp[j]=randomAccessFile.readByte();
}
}
logStr = new String(tmp,"UTF-8");
// logStr = df.format(Long.parseLong(logStr.substring(0,8),16)*1000) +" "+ logStr.substring(8);
// logStr = logStr.replaceAll("\n", "").replaceAll("\r", "").replaceAll("\r\n", "");
if(logStr.contains("")){
// System.out.println(logStr);
fw.write(formatLogStr(tmp).replaceAll("\n", "").replaceAll("\r", "").replaceAll("\r\n", "")+"\r\n");
fw.flush();}
}
}fw.close();
}
public static String formatLogStr(byte[] byteStr) throws Exception{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// System.out.println(new String(HexUtils.HexString2Bytes("E381AEE694BBE69283"),"UTF-8"));
String hexStr = HexUtils.Bytes2HexString(byteStr).replaceAll(" ", "");
// System.out.println(hexStr);
if(hexStr.contains(HexUtils.Bytes2HexString("12A9".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("1130".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("12AB".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("492E".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("112D".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("492D".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("292F".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("1329".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("292D".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("1131".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("133A".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("12AA".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("103A".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("112E".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("112F".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("312F".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("12BA".getBytes()).replace(" ", ""))
||hexStr.contains(HexUtils.Bytes2HexString("14AB".getBytes()).replace(" ", ""))){
if(hexStr.contains("01010101")&&hexStr.contains("010101")){
String headerStr = hexStr.substring(0,28);
String nickName = hexStr.substring(hexStr.indexOf("01010101")+12);
nickName = nickName.substring(0,nickName.indexOf("03"));
String bodyStr = "";
bodyStr = hexStr.substring(hexStr.indexOf("E381"));
hexStr = headerStr + nickName + bodyStr;
}
}
else if(hexStr.contains("32393239")){
if(hexStr.contains("01010101")&&hexStr.contains("010101")){
if(hexStr.substring(28).startsWith("E38")){
String headerStr = hexStr.substring(0,hexStr.indexOf("E381AEE694BBE69283")+"E381AEE694BBE69283".length());
hexStr = hexStr.substring(hexStr.indexOf("E381AEE694BBE69283")+"E381AEE694BBE69283".length());
String nickName = hexStr.substring(hexStr.indexOf("01010101")+12);
nickName = nickName.substring(0,nickName.indexOf("03"));
String bodyStr = "";
bodyStr = hexStr.substring(hexStr.indexOf("E381"));
hexStr = headerStr+"20"+ nickName + bodyStr;
}else{
String headerStr = hexStr.substring(0,28);
String nickName = hexStr.substring(hexStr.indexOf("01010101")+12);
nickName = nickName.substring(0,nickName.indexOf("03"));
String bodyStr = "";
bodyStr = hexStr.substring(hexStr.indexOf("E381"));
hexStr = headerStr + nickName + bodyStr;
}
}
}else{
}
hexStr = hexStr.replaceAll("EE81AF", "E28692");
String str = new String(HexUtils.HexString2Bytes(hexStr),"UTF-8");
//替换时间头
str = df.format(Long.parseLong(str.substring(0,8),16)*1000) +" "+ str.substring(8);
System.out.println(str);
return str;
}
}