Welcome to Yumao′s Blog.
最開始先說下log的生成規則好了
ffxiv在登入遊戲之後
會在內存保存視窗內的log
需要在遊戲內勾選選項才會有相關方面log生成
在內存中累計到1000條記錄之後
會將其以特殊的方式
轉存至個人資料夾中的壹系列log文檔中
以達到釋放內存效用
此工具只針對于已生成的log文檔
對于即時生成的文檔無效
(因爲根本沒讀他
以下是code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | 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; } } |