Welcome to Yumao′s Blog.
最開始先說下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;
}
}