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; } }