- 浏览: 3052633 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
呼,这个也是一年多之前写的了……当时茶茶说起有没有办法处理BMW里的dat文件,然后我写了这程序,然后我们就真的开工了。真神奇,呵呵。
当时发给茶茶的聊天记录:
嘛,当时也没仔细考察。这BMW很明显用的不是YaneSDK.NET而是更早的版本,是YaneSDK2还是YaneSDK3来着,我又忘了。不管了。
然后这个程序的使用方法:
接下来是源代码。跟前面两帖(这里和这里)一样,因为用了BlowfishJ的BinConverter.java,所以以下代码以LGPL许可证发布。
不过说真的,这连续3帖里的代码都是当时太贪图写起来方便而弄得乱七八糟的……结构太糟糕了。或许还是应该把一些结构自己的IO给封装起来的。叹气。
Archiver.java:
IndexEntry.java:
BinConverter.java:
当时发给茶茶的聊天记录:
引用
http://www.ahcomic.com/bbs/thread-163398-1-1.html
这是前段时间正好写的关于Fatal/Fake的其中一个archive的解析.BMW的情况看起来跟Fatal/Fake差不多.可以参考下,拿里面的代码来修改.
http://yanesdkdotnet.sourceforge.jp/
如果我没猜错的话,BMW用的是这个引擎(或相关,yane2k1).但是这不重要,我们不一定需要知道原本的引擎是什么样的.
========================================================================================================================
头8个字节,地址0x00-0x07,属于file signature,读进来验证下是不是等于yanepkDx就可以了.
接着是一个DWORD(也就是32位整型,4个byte),那是文件个数,顺序是little-endian.0x2D意味着这个archive里有是45个文件.
然后后面接着的所谓的index.你会看到每个index的entry的长度都是固定的,长度为268(=0x10C).其中前面是留给"以\0结束的字符串"的空间,这里当然就是文件名啦.后面有3个little-endian的DWORD,分别是文件的地址/大小/大小.
提到index的每个entry里末尾的那3个DWORD,在我手上的这个文件里,后两个表示大小的值总是一样的.这意味着其中一个是原始大小而另一个是压缩后大小,只是现在我这文件的内容没有被压缩过而已.你或许会在另外几个dat文件里看到这两个表示大小的值会不一样.那么比较小的那个就是压缩后的大小.
index后就是文件内容了.把它们分离出来就行."分离"也就是把数据一个一个字节写到一个新文件里就可以了.反正我们也不追求什么速度啊空间啊效率什么的.你在index里得到了3个有用的值(这里我们只用到两个,因为不知道哪个"大小"是指压缩的.假设地址是offset,大小是origFileSize),那么Java就用RandomAccessFile设置文件指针到offset,然后读出origFileSize个字节,按照原本的文件名写出去就可以了...简单吧.
以后要打包回来的时候,只要反过来做一次事情就行...
这是前段时间正好写的关于Fatal/Fake的其中一个archive的解析.BMW的情况看起来跟Fatal/Fake差不多.可以参考下,拿里面的代码来修改.
http://yanesdkdotnet.sourceforge.jp/
如果我没猜错的话,BMW用的是这个引擎(或相关,yane2k1).但是这不重要,我们不一定需要知道原本的引擎是什么样的.
========================================================================================================================
头8个字节,地址0x00-0x07,属于file signature,读进来验证下是不是等于yanepkDx就可以了.
接着是一个DWORD(也就是32位整型,4个byte),那是文件个数,顺序是little-endian.0x2D意味着这个archive里有是45个文件.
然后后面接着的所谓的index.你会看到每个index的entry的长度都是固定的,长度为268(=0x10C).其中前面是留给"以\0结束的字符串"的空间,这里当然就是文件名啦.后面有3个little-endian的DWORD,分别是文件的地址/大小/大小.
提到index的每个entry里末尾的那3个DWORD,在我手上的这个文件里,后两个表示大小的值总是一样的.这意味着其中一个是原始大小而另一个是压缩后大小,只是现在我这文件的内容没有被压缩过而已.你或许会在另外几个dat文件里看到这两个表示大小的值会不一样.那么比较小的那个就是压缩后的大小.
index后就是文件内容了.把它们分离出来就行."分离"也就是把数据一个一个字节写到一个新文件里就可以了.反正我们也不追求什么速度啊空间啊效率什么的.你在index里得到了3个有用的值(这里我们只用到两个,因为不知道哪个"大小"是指压缩的.假设地址是offset,大小是origFileSize),那么Java就用RandomAccessFile设置文件指针到offset,然后读出origFileSize个字节,按照原本的文件名写出去就可以了...简单吧.
以后要打包回来的时候,只要反过来做一次事情就行...
嘛,当时也没仔细考察。这BMW很明显用的不是YaneSDK.NET而是更早的版本,是YaneSDK2还是YaneSDK3来着,我又忘了。不管了。
然后这个程序的使用方法:
引用
Usage: java Archiver [option] filename
options:
[e]xtract
[a]rchive
============================================
example:
Suppose data1.dat is in the same directory where this program is.
to extract files to current directory:
Suppose the files to be packed are in "data1" directory:
options:
[e]xtract
[a]rchive
============================================
example:
Suppose data1.dat is in the same directory where this program is.
to extract files to current directory:
java Archiver e data1.dat
Suppose the files to be packed are in "data1" directory:
java Archiver a data1\
接下来是源代码。跟前面两帖(这里和这里)一样,因为用了BlowfishJ的BinConverter.java,所以以下代码以LGPL许可证发布。
不过说真的,这连续3帖里的代码都是当时太贪图写起来方便而弄得乱七八糟的……结构太糟糕了。或许还是应该把一些结构自己的IO给封装起来的。叹气。
Archiver.java:
/* * @(#)Archiver.java 2007/03/23 * Written by rednaxela / FX */ import java.io.*; import java.util.*; /** * Demonstrating archive operations on *.dat files as seen in BattleMoonWars. */ public class Archiver { static final byte[] SIGNATURE = { (byte)'y', (byte)'a', (byte)'n', (byte)'e', (byte)'p', (byte)'k', (byte)'D', (byte)'x', }; static final int ENTRY_LENGTH = 268; static final int MAX_FILENAME_LENGTH = 256; static final int OFFSET_OFS = 256; static final int LENGTH_OFS = 260; static final int COMPRESSED_LENGTH_OFS = 264; // ?? static final String USAGE = "Usage: java Archiver [option] filename\n" + "options:\n" + "[e]xtract\n" + "[a]rchive"; /** * the application entry point * @param args (command line) parameters */ public static void main(String args[]) throws Exception { // check command line arguments if (args.length != 2) error(USAGE); if ("e".equals(args[0].trim())) { // extract files from archive String filename = args[1].trim(); if (filename.length() == 0) error("2nd argument not exist."); extractFiles(filename); } else if ("a".equals(args[0].trim())) { // pack files into archive String dirname = args[1].trim(); if (dirname.length() == 0) error("2nd argument not exist."); packFiles(dirname); } else error(USAGE); } private static void extractFiles(String filename) throws Exception { // open source archive File arc = new File(filename); if (!arc.exists()) error("Archive " + filename + " doesn't exist"); long contentOfs = 0L; IndexEntry[] indexEntries = null; FileInputStream fis = new FileInputStream(arc); DataInputStream dis = new DataInputStream(fis); // match archive SIGNATURE byte[] sig = new byte[8]; dis.read(sig); if (!Arrays.equals(SIGNATURE, sig)) error("Archive file not supported."); // get file count int fileCount = reverseEndian(dis.readInt()); System.out.println("Files in archive: " + fileCount); indexEntries = new IndexEntry[fileCount]; // read index entries byte[] entryBuffer = new byte[ENTRY_LENGTH]; for (int i = 0; i < fileCount; ++i) { IndexEntry entry = new IndexEntry(); dis.read(entryBuffer); ByteArrayInputStream bais = new ByteArrayInputStream(entryBuffer); String name = readCString(bais); entry.setFilename(name); System.err.print("File \"" + entry.getFilename() + "\" : "); int offset = BinConverter.byteArrayToIntLE(entryBuffer, OFFSET_OFS); entry.setOffset(offset); System.err.print(" at relative offset 0x" + Integer.toHexString(entry.getOffset()).toUpperCase()); int length = BinConverter.byteArrayToIntLE(entryBuffer, LENGTH_OFS); entry.setLength(length); System.err.print(" size: 0x" + Integer.toHexString(entry.getLength()).toUpperCase()); int compressedLength = BinConverter.byteArrayToIntLE(entryBuffer, COMPRESSED_LENGTH_OFS); entry.setCompressedLength(compressedLength); System.err.println(" csize: 0x" + Integer.toHexString(entry.getCompressedLength()).toUpperCase()); if (length > compressedLength) { System.err.println("possibly compressed"); System.exit(1); } else if (length < compressedLength) { System.err.println("possibly compressed, got length/compressedLength wrong..."); System.exit(1); } indexEntries[i] = entry; } // extract files for (IndexEntry entry : indexEntries) { // data correctness check - this support ordered file archive only. // to support out-of-order archives, use RandomAccessFile instead. if (fis.getChannel().position() != entry.getOffset()) error("Bad file content order at " + entry.getFilename() + " 0x" + Integer.toHexString((int)(fis.getChannel().position() - contentOfs))); File outfile = new File("./" + entry.getFilename()); File parentDir = outfile.getParentFile(); if (!parentDir.exists()) parentDir.mkdirs(); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outfile), 0x7FFFFF); int remainder = 0; // keep track of the amount of remaining bytes int length = entry.getLength(); while (fis.available() != 0 && remainder != length) { bos.write(fis.read()); ++remainder; } bos.flush(); bos.close(); } fis.close(); } private static void packFiles(String dirname) throws Exception { // open source directory File dir = new File(dirname); if (!dir.exists()) error("Directory " + dirname + " doesn't exist"); else if (!dir.isDirectory()) error(dirname + " is not a valid directory."); // use a ArrayList to store the index entries ArrayList<IndexEntry> indexEntries = new ArrayList<IndexEntry>(); // make up index data buildIndex(dir, indexEntries, ""); // calculate the offset values for each file record int runningOfs = SIGNATURE.length + 4 + ENTRY_LENGTH * indexEntries.size(); for (IndexEntry entry : indexEntries) { entry.setOffset(runningOfs); runningOfs += entry.getLength(); } // write out archive SIGNATURE and file count DataOutputStream dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(dir.getName() + ".dat"))); dos.write(SIGNATURE); dos.writeInt(reverseEndian(indexEntries.size())); // write out the file index for (IndexEntry entry : indexEntries) { System.err.println("Adding file " + entry.getFilename() + " size: 0x" + Integer.toHexString(entry.getLength()).toUpperCase() + " at relative offset: 0x" + Integer.toHexString(entry.getOffset()).toUpperCase()); int zeroCount = MAX_FILENAME_LENGTH - entry.getFilename().length(); dos.write(entry.getFilename().getBytes()); for (int i = 0; i < zeroCount; ++i) dos.write(0); dos.writeInt(reverseEndian(entry.getOffset())); dos.writeInt(reverseEndian(entry.getLength())); dos.writeInt(reverseEndian(entry.getLength())); // NOTE! Does NOT support compressed files at current time being } // write out each file's content for(IndexEntry entry : indexEntries) { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(dir.getAbsolutePath() + "\\" + entry.getFilename())); while (bis.available() != 0) dos.writeByte(bis.read()); bis.close(); } dos.flush(); dos.close(); } private static int reverseEndian(int i) { byte[] bytes = new byte[4]; bytes[0] = (byte)(i >>> 24); bytes[1] = (byte)(i >>> 16); bytes[2] = (byte)(i >>> 8 ); bytes[3] = (byte) i; i = bytes[3] << 24; i |= (bytes[2] << 16 ) & 0x0ff0000; i |= (bytes[1] << 8 ) & 0x000ff00; i |= bytes[0] & 0x00000ff; return i; } private static int reverseEndian(short s) { byte[] bytes = new byte[2]; bytes[0] = (byte)(s >>> 8 ); bytes[1] = (byte) s; int i = 0; i |= (bytes[1] << 8 ) & 0x000ff00; i |= bytes[0] & 0x00000ff; return i; } private static void error(String cause) { System.err.println("Error " + cause); System.exit(1); } private static String readCString(InputStream in) throws IOException { ArrayList<Byte> str = new ArrayList<Byte>(); byte current = (byte)in.read(); while (current != (byte)0x00) { str.add(current); current = (byte)in.read(); } byte[] temp = new byte[str.size()]; for (int i = 0; i < temp.length; ++i) { temp[i] = str.get(i); } return new String(temp); } private static void buildIndex(File dir, ArrayList<IndexEntry> index, String parent) { // list the designated directory File[] files = dir.listFiles(); // traverse dir for (int i = 0; i < files.length; ++i) { if (files[i].isDirectory()) { // current file is a directory // assumes that subdir depth doesn't exceed one buildIndex(files[i], index, parent+files[i].getName()+"\\"); } else { // current file is a normal file IndexEntry entry = new IndexEntry(); entry.setFilename(parent+files[i].getName()); entry.setLength((int)files[i].length()); index.add(entry); } } } }
IndexEntry.java:
/* * @(#)IndexEntry.java 2007/03/23 * Written by rednaxela / FX */ public class IndexEntry { private String filename; private int length; private int offset; private int compressedLength; // TODO not yet implemented - CHECK! /** * @return the filename */ public String getFilename() { return filename; } /** * @param filename the filename to set */ public void setFilename(String filename) { this.filename = filename; } /** * @return the length */ public int getLength() { return length; } /** * @param length the length to set */ public void setLength(int length) { this.length = length; } /** * @return the offset */ public int getOffset() { return offset; } /** * @param offset the offset to set */ public void setOffset(int offset) { this.offset = offset; } /** * @return the compressedLength */ public int getCompressedLength() { return compressedLength; } /** * @param offset the compressedLength to set */ public void setCompressedLength(int compressedLength) { this.compressedLength = compressedLength; } }
BinConverter.java:
/* * @(#)BinConverter.java */ /** * Some helper routines for data conversion, all data is treated in network * byte order. */ public class BinConverter { /** * Gets bytes from an array into an integer, in big-endian. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 32bit integer */ public final static int byteArrayToIntBE( byte[] buf, int ofs) { return (buf[ofs ] << 24) | ((buf[ofs + 1] & 0x0ff) << 16) | ((buf[ofs + 2] & 0x0ff) << 8 ) | ( buf[ofs + 3] & 0x0ff); } /** * Gets bytes from an array into an integer, in little-endian. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 32bit integer */ public final static int byteArrayToIntLE( byte[] buf, int ofs) { return (buf[ofs + 3] << 24) | ((buf[ofs + 2] & 0x0ff) << 16) | ((buf[ofs + 1] & 0x0ff) << 8 ) | ( buf[ofs ] & 0x0ff); } /////////////////////////////////////////////////////////////////////////// /** * Converts an integer to bytes in big-endian, which are put into an array. * @param value the 32bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void intToByteArrayBE( int value, byte[] buf, int ofs) { buf[ofs ] = (byte)((value >>> 24) & 0x0ff); buf[ofs + 1] = (byte)((value >>> 16) & 0x0ff); buf[ofs + 2] = (byte)((value >>> 8 ) & 0x0ff); buf[ofs + 3] = (byte) value; } /** * Converts an integer to bytes in little-endian, which are put into an array. * @param value the 32bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void intToByteArrayLE( int value, byte[] buf, int ofs) { buf[ofs + 3] = (byte)((value >>> 24) & 0x0ff); buf[ofs + 2] = (byte)((value >>> 16) & 0x0ff); buf[ofs + 1] = (byte)((value >>> 8 ) & 0x0ff); buf[ofs ] = (byte) value; } /////////////////////////////////////////////////////////////////////////// /** * Gets bytes from an array into a long. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 64bit integer */ public final static long byteArrayToLong( byte[] buf, int ofs) { // Looks more complex - but it is faster (at least on 32bit platforms). return ((long)(( buf[ofs ] << 24) | ((buf[ofs + 1] & 0x0ff) << 16) | ((buf[ofs + 2] & 0x0ff) << 8 ) | ( buf[ofs + 3] & 0x0ff )) << 32) | ((long)(( buf[ofs + 4] << 24) | ((buf[ofs + 5] & 0x0ff) << 16) | ((buf[ofs + 6] & 0x0ff) << 8 ) | ( buf[ofs + 7] & 0x0ff )) & 0x0ffffffffL); } /////////////////////////////////////////////////////////////////////////// /** * Converts a long to bytes, which are put into an array. * @param value the 64bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void longToByteArray( long value, byte[] buf, int ofs) { int tmp = (int)(value >>> 32); buf[ofs ] = (byte) (tmp >>> 24); buf[ofs + 1] = (byte)((tmp >>> 16) & 0x0ff); buf[ofs + 2] = (byte)((tmp >>> 8 ) & 0x0ff); buf[ofs + 3] = (byte) tmp; tmp = (int)value; buf[ofs + 4] = (byte) (tmp >>> 24); buf[ofs + 5] = (byte)((tmp >>> 16) & 0x0ff); buf[ofs + 6] = (byte)((tmp >>> 8 ) & 0x0ff); buf[ofs + 7] = (byte) tmp; } /////////////////////////////////////////////////////////////////////////// /** * Converts values from an integer array to a long. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 64bit integer */ public final static long intArrayToLong( int[] buf, int ofs) { return (((long) buf[ofs ]) << 32) | (((long) buf[ofs + 1]) & 0x0ffffffffL); } /////////////////////////////////////////////////////////////////////////// /** * Converts a long to integers which are put into an array. * @param value the 64bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void longToIntArray( long value, int[] buf, int ofs) { buf[ofs ] = (int)(value >>> 32); buf[ofs + 1] = (int) value; } /////////////////////////////////////////////////////////////////////////// /** * Makes a long from two integers (treated unsigned). * @param lo lower 32bits * @param hi higher 32bits * @return the built long */ public final static long makeLong( int lo, int hi) { return (((long) hi << 32) | ((long) lo & 0x00000000ffffffffL)); } /////////////////////////////////////////////////////////////////////////// /** * Gets the lower 32 bits of a long. * @param val the long integer * @return lower 32 bits */ public final static int longLo32( long val) { return (int)val; } /////////////////////////////////////////////////////////////////////////// /** * Gets the higher 32 bits of a long. * @param val the long integer * @return higher 32 bits */ public final static int longHi32( long val) { return (int)(val >>> 32); } /////////////////////////////////////////////////////////////////////////// // our table for hex conversion final static char[] HEXTAB = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Converts a byte array to a hex string. * @param data the byte array * @return the hex string */ public final static String bytesToHexStr( byte[] data) { return bytesToHexStr(data, 0, data.length); } /////////////////////////////////////////////////////////////////////////// /** * Converts a byte array to a hex string. * @param data the byte array * @param ofs start index where to get the bytes * @param len number of bytes to convert * @return the hex string */ public final static String bytesToHexStr( byte[] data, int ofs, int len) { int pos, c; StringBuffer sbuf; sbuf = new StringBuffer(); sbuf.setLength(len << 1); pos = 0; c = ofs + len; while (ofs < c) { sbuf.setCharAt(pos++, HEXTAB[(data[ofs ] >> 4) & 0x0f]); sbuf.setCharAt(pos++, HEXTAB[ data[ofs++] & 0x0f]); } return sbuf.toString(); } /////////////////////////////////////////////////////////////////////////// /** * Converts a hex string back into a byte array (invalid codes will be * skipped). * @param hex hex string * @param data the target array * @param srcofs from which character in the string the conversion should * begin, remember that (nSrcPos modulo 2) should equals 0 normally * @param dstofs to store the bytes from which position in the array * @param len number of bytes to extract * @return number of extracted bytes */ public final static int hexStrToBytes( String hex, byte[] data, int srcofs, int dstofs, int len) { int i, j, strlen, avail_bytes, dstofs_bak; byte abyte; boolean convertOK; // check for correct ranges strlen = hex.length(); avail_bytes = (strlen - srcofs) >> 1; if (avail_bytes < len) { len = avail_bytes; } int nOutputCapacity = data.length - dstofs; if (len > nOutputCapacity) { len = nOutputCapacity; } // convert now dstofs_bak = dstofs; for (i = 0; i < len; i++) { abyte = 0; convertOK = true; for (j = 0; j < 2; j++) { abyte <<= 4; char cActChar = hex.charAt(srcofs++); if ((cActChar >= 'a') && (cActChar <= 'f')) { abyte |= (byte) (cActChar - 'a') + 10; } else { if ((cActChar >= '0') && (cActChar <= '9')) { abyte |= (byte) (cActChar - '0'); } else { convertOK = false; } } } if (convertOK) { data[dstofs++] = abyte; } } return (dstofs - dstofs_bak); } /////////////////////////////////////////////////////////////////////////// /** * Converts a byte array into a Unicode string. * @param data the byte array * @param ofs where to begin the conversion * @param len number of bytes to handle * @return the string */ public final static String byteArrayToStr( byte[] data, int ofs, int len) { int avail_capacity, sbuf_pos; StringBuffer sbuf; // we need two bytes for every character len &= ~1; // enough bytes in the buf? avail_capacity = data.length - ofs; if (avail_capacity < len) { len = avail_capacity; } sbuf = new StringBuffer(); sbuf.setLength(len >> 1); sbuf_pos = 0; while (0 < len) { sbuf.setCharAt( sbuf_pos++, (char)((data[ofs ] << 8 ) | (data[ofs + 1] & 0x0ff))); ofs += 2; len -= 2; } return sbuf.toString(); } }
- BMW_Archiver_20080817.zip (27.2 KB)
- 下载次数: 3
评论
2 楼
RednaxelaFX
2008-04-08
嗯嗯,如果再有什么类似的东西需要写的话说不定会用Ruby。但是重构就算了……
这可是write-and-throwaway的代码啊……
这可是write-and-throwaway的代码啊……
1 楼
poweryoung
2008-04-08
今天帖好多...
来,用ruby重构吧...
来,用ruby重构吧...
发表评论
-
IDA Pro Free笔记
2013-05-19 08:59 0IDA把数据都存哪里了? Windows 7 D:\tem ... -
加密算法收集
2011-01-23 16:10 0加密算法,OTP http://en.wikipedia.or ... -
BattleMoonWars 归档解压/压缩程序(砍掉重炼版)
2010-05-03 21:40 2281以前写过BattleMoonWars的 ... -
Quartett!文本插入程序
2008-06-21 20:38 1573年初写的Quartett!的文本 ... -
ケータイ少女 script.arc的解压缩程序 (Java)
2008-04-08 14:02 4657嗯,这个也是快一年前写的了。当时在澄空看到有人想要解手机少女的 ... -
桃華月憚体験版的解压缩程序 (Java)
2008-04-08 13:38 3114这是差不多一年前写的程序了……有人说想看于是发出来。 当时也是 ... -
Quartett!的文本提取程序
2008-03-05 23:31 1878诶,之前写了这个程序 ... -
Fortune Arterial Tools
2008-02-28 13:34 2447using System; using System.IO; ... -
さくらシュトラッセ literal record
2008-01-28 14:53 1814脚本在scenario.sc里。无 ... -
Borland的库的一个小特征?
2008-01-06 00:22 2509最近弄了下KAMIPANI相关 ... -
[脚本分析] 从Quartett!的脚本得到资源列表
2007-12-21 14:00 1772听汉公的说明,看来LittleWitch所使用的FFD Sys ... -
[脚本分析] Quartett!的二进制脚本分析
2007-12-20 22:17 3326我前两天在NetOA方面确 ...
相关推荐
"BattleMoonWars 归档解压/压缩程序(砍掉重炼版)"是一个专为游戏《BattleMoonWars》设计的文件压缩与解压缩工具。这个工具由开发者进行了优化和改良,以提供更高效、更稳定的文件管理服务。在源码层面进行了重构,...
ysoserial是一个用于生成利用不安全的Java对象反序列化的有效负载的概念验证工具。它包含一系列在常见Java库中发现的"gadget chains",可以在特定条件下利用执行不安全的反序列化操作的Java应用程序。ysoserial项目最初在2015年AppSecCali会议上提出,包含针对Apache Commons Collections(3.x和4.x版本)、Spring Beans/Core(4.x版本)和Groovy(2.3.x版本)的利用链
1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
**Oracle 10g DBA学习手册:安装Oracle和构建数据库** **目的:** 本章节旨在指导您完成Oracle数据库软件的安装和数据库的创建。您将通过Oracle Universal Installer (OUI)了解软件安装过程,并学习如何利用Database Configuration Assistant (DBCA)创建附加数据库。 **主题概览:** 1. 利用Oracle Universal Installer (OUI)安装软件 2. 利用Database Configuration Assistant (DBCA)创建数据库 **第2章:Oracle软件的安装与数据库构建** **Oracle Universal Installer (OUI)的运用:** Oracle Universal Installer (OUI)是一个图形用户界面(GUI)工具,它允许您查看、安装和卸载机器上的Oracle软件。通过OUI,您可以轻松地管理Oracle软件的安装和维护。 **安装步骤:** 以下是使用OUI安装Oracle软件并创建数据库的具体步骤:
消防验收过程服务--现场记录表.doc
数据库管理\09-10年第1学期数据库期末考试试卷A(改卷参考).doc。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;
职业暴露后的处理流程.docx
Java Web开发短消息系统
项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7
这是一款可以配置过滤目录及过滤的文件后缀的工具,并且支持多个项目同时输出导出,并过滤指定不需要导出的目录及文件后缀。 导出后将会保留原有的路径,并在新的文件夹中体现。
Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
YOLO算法-挖掘机与火焰数据集-7735张图像带标签-挖掘机.zip
操作系统实验 Ucore lab5
IMG_5950.jpg
竞选报价评分表.docx
java系统,mysql、springboot等框架
1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。