- 浏览: 3056568 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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 2286以前写过BattleMoonWars的 ... -
Quartett!文本插入程序
2008-06-21 20:38 1577年初写的Quartett!的文本 ... -
ケータイ少女 script.arc的解压缩程序 (Java)
2008-04-08 14:02 4661嗯,这个也是快一年前写的了。当时在澄空看到有人想要解手机少女的 ... -
桃華月憚体験版的解压缩程序 (Java)
2008-04-08 13:38 3120这是差不多一年前写的程序了……有人说想看于是发出来。 当时也是 ... -
Quartett!的文本提取程序
2008-03-05 23:31 1885诶,之前写了这个程序 ... -
Fortune Arterial Tools
2008-02-28 13:34 2450using System; using System.IO; ... -
さくらシュトラッセ literal record
2008-01-28 14:53 1819脚本在scenario.sc里。无 ... -
Borland的库的一个小特征?
2008-01-06 00:22 2512最近弄了下KAMIPANI相关 ... -
[脚本分析] 从Quartett!的脚本得到资源列表
2007-12-21 14:00 1780听汉公的说明,看来LittleWitch所使用的FFD Sys ... -
[脚本分析] Quartett!的二进制脚本分析
2007-12-20 22:17 3330我前两天在NetOA方面确 ...
相关推荐
"BattleMoonWars 归档解压/压缩程序(砍掉重炼版)"是一个专为游戏《BattleMoonWars》设计的文件压缩与解压缩工具。这个工具由开发者进行了优化和改良,以提供更高效、更稳定的文件管理服务。在源码层面进行了重构,...
MATLAB数字滤波器设计及其在语音信号去噪中的应用:源码详解与报告分享,MATLAB 数字滤波器设计 及其语音信号去噪应用。 (供学习交流)带源码,带注释。 有代码和报告。 ,核心关键词:MATLAB; 数字滤波器设计; 语音信号去噪应用; 源码; 注释; 代码与报告。,"MATLAB数字滤波器设计及其在语音信号去噪中的应用:带源码注释与报告"
COMSOL软件模拟三维电化学腐蚀过程的研究分析,comsol三维电化学腐蚀。 ,核心关键词:Comsol;三维电化学;腐蚀;模型模拟;电化学腐蚀过程。,"Comsol模拟:三维电化学腐蚀过程解析"
基于COMSOL的降雨入渗模型:边坡与渗流边界下的强度折减塑性形变研究,comsol降雨入渗模型,边坡降雨边界与渗流边界 强度折减塑性形变 ,comsol降雨入渗模型; 降雨边界; 渗流边界; 强度折减; 塑性形变,"COMSOL降雨入渗模型:边坡渗流与强度折减塑性形变分析"
2025员工安全意识培训试题及答案.docx
Python自动化办公源码-06在Word表格中将上下行相同内容的单元格自动合并
基于深度学习的神经网络技术在信息通信领域的应用研究.pdf
1.内容概要 通过KNN实现鸢尾花分类,即将新的数据点分配给已知类别中的某一类。该算法的核心思想是通过比较距离来确定最近邻的数据点,然后利用这些邻居的类别信息来决定待分类数据点的类别。 2.KNN算法的伪代码 对未知类别属性的数据集中的每个点依次执行以下操作: (1)计算已知类别数据集中的点与当前点之间的距离; (2)按照距离递增次序排序; (3)选取与当前点距离最小的k个点; (4)确定前k个点所在类别的出现频率; (5)返回前k个点出现频率最高的类别作为当前点的预测分类。 3.数据集说明 代码使用`pandas`库加载了一个名为`iris.arff.csv`的数据集 4.学习到的知识 通过鸢尾花分类学习了KNN算法,选择样本数据集中前k个最相似的数据,就是KNN算法中k的出处。k值过大,会出现分类结果模糊的情况;k值较小,那么预测的标签比较容易受到样本的影响。在实验过程中,不同的k值也会导致分类器的错误率不同。KNN算法精度高、无数据输入的假定,可以免去训练过程。但是对于数据量较多的训练样本,KNN必须保存全部数据集,可能会存在计算的时间复杂度、空间复杂度高的情况,存在维数灾难问
感应电机控制与矢量控制仿真:磁链闭环、转速闭环与电流闭环的综合应用研究,感应电机控制仿真,矢量控制,异步电机仿真,磁链闭环,转速闭环,电流闭环 ,核心关键词:感应电机控制仿真; 矢量控制; 异步电机仿真; 磁链闭环; 转速闭环; 电流闭环,"感应电机矢量控制仿真:磁链、转速、电流三闭环异步电机模拟"
威纶通TK6071IP触摸屏锁屏宏指令程序详解:注释清晰,便于理解与学习,威纶通触摸屏锁屏宏指令程序 ~ 威纶通触摸屏锁屏宏指令程序,TK6071IP触摸屏 利用宏指令程序来控制,宏指令注释清晰,方便理解程序。 具有很好的学习意义和借鉴价值。 ,关键词:威纶通触摸屏;锁屏宏指令程序;TK6071IP触摸屏;宏指令控制;注释清晰;学习借鉴。,威纶通触摸屏宏指令程序:清晰注释,学习借鉴之利器
2025输血相关法律法规试题考核试题及答案.docx
Python游戏编程源码-2048小游戏
2025最新康复医学概论考试题库(含答案).doc
Python自动化办公源码-09用Python批量往Word文档中指定位置添加图片
高品质车载充电器技术解决方案:含原理图、PCB图、C源代码及DSP控制器资料,附赠CDCDC模块资料,车载充电器 3Kw OBC 车载充电器 含原理图、PCB图、C源代码、变压器参数等生产资料。 附赠15kwdcdc模块资料 1、这款产品的方案采用的是dsp2803x系列。 2、原理图和Pcb采用AD绘制。 此方案仅供学习 ,车载充电器; 3Kw OBC; 原理图; PCB图; C源代码; 变压器参数; 生产资料; dsp2803x系列; AD绘制; 15kwdcdc模块资料,3Kw车载充电器方案:DSP2803x系列原理图、PCB图及C源学习包
2025最新康复医学考试题及答案.docx
内容概要:本文介绍了一种用于视频处理的新型卷积神经网络(CNN)加速器。主要创新点在于引入了混合精度计算、跨帧数据重用控制器及引擎,以及混合位宽差帧数据编码解码器。这些特性有效解决了视频帧间的时空相关性和稀疏性带来的挑战,提高了处理速度并降低了功耗和带宽需求。具体来说,通过对连续帧的数据相似度利用,可以在保持高精度的同时减少计算量和内存访问次数;通过多类型稀疏卷积聚类数组实现了对现代稀疏神经网络的支持;并通过混合位宽度编码减少了离芯片外的数据传输量,最高达到68%。 适用人群:从事深度学习硬件加速设计的研究人员和技术爱好者;关注AI边缘计算领域的从业者。 使用场景及目标:适用于自动驾驶汽车摄像头、监控系统等实时视频流应用场景。旨在为开发者提供高效的低能耗解决方案,在有限的时间和资源下完成大量的图像信号处理任务,如跟踪、分类等。 其他说明:文中还详细描述了芯片的设计细节,测试平台构建,以及不同模型(如MobileNet)在网络上的实际性能表现。
COMSOL电化学喷射腐蚀模拟与解析:技术原理及应用实践,comsol电化学喷射腐蚀 ,核心关键词:comsol; 电化学; 喷射腐蚀; 电化学腐蚀。,"电化学喷射腐蚀研究:comsol模拟与解析"
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat