- 浏览: 3056666 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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 1578年初写的Quartett!的文本 ... -
ケータイ少女 script.arc的解压缩程序 (Java)
2008-04-08 14:02 4663嗯,这个也是快一年前写的了。当时在澄空看到有人想要解手机少女的 ... -
桃華月憚体験版的解压缩程序 (Java)
2008-04-08 13:38 3121这是差不多一年前写的程序了……有人说想看于是发出来。 当时也是 ... -
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 1781听汉公的说明,看来LittleWitch所使用的FFD Sys ... -
[脚本分析] Quartett!的二进制脚本分析
2007-12-20 22:17 3331我前两天在NetOA方面确 ...
相关推荐
"BattleMoonWars 归档解压/压缩程序(砍掉重炼版)"是一个专为游戏《BattleMoonWars》设计的文件压缩与解压缩工具。这个工具由开发者进行了优化和改良,以提供更高效、更稳定的文件管理服务。在源码层面进行了重构,...
2025职业教育知识竞赛题库(含答案).pptx
"SOA海鸥算法优化下的KELM核极限学习机分类MATLAB代码详解:传感器故障诊断数据集应用与本地EXCEL数据读取功能",(SOA-KELM)海鸥算法SOA优化KELM核极限学习机分类MATLAB代码 代码注释清楚。 main为运行主程序,可以读取本地EXCEL数据。 很方便,容易上手。 (以传感器故障诊断数据集为例) ,核心关键词:SOA-KELM;海鸥算法优化;核极限学习机分类;MATLAB代码;代码注释清楚;main程序;读取本地EXCEL数据;传感器故障诊断数据集。,SOA-KELM分类算法MATLAB代码:海鸥优化核极限学习机,轻松上手,读取EXCEL数据集进行传感器故障诊断
内容概要:本文由世界经济论坛与Capgemini联合发布,主要阐述了AI代理从简单程序演变为复杂自主系统的进程,强调了它们在现代各行业如医疗保健、教育及金融服务等方面所发挥的作用,并讨论了其潜在收益以及伴随的风险和挑战。文中详细介绍了AI代理的发展历程、核心技术趋势(深度学习、强化学习)、多种类型的AI代理及其系统架构,同时对未来的发展方向——多智能体系统进行了展望,探讨了提高生产力、优化资源配置的新机会。 适合人群:对人工智能感兴趣的各界人士,尤其是关注技术创新对企业和社会长远影响的决策者和技术领导者,如商业领袖、政府官员及其他利益相关方。 使用场景及目标:①帮助政策制定者理解AI代理的功能和应用场景;②为企业管理者提供关于部署和管理AI系统的指导;③为研究者指明未来科研方向并探讨伦理和社会责任等问题;④为技术人员揭示当前最先进技术和最佳实践案例。 其他说明:文中还提到了随着更加先进的AI代理不断涌现,确保安全性和有效监管将是未来发展的重要议题之一。此外,跨行业的共识对于将AI代理顺利整合到各个部门至关重要。文章指出需要建立稳健治理机制来保障AI技术健康发展并服务于公共利益最大化的目标。
2025网络安全理论知识考试题(含答案).pptx
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
基于FATFS系统的STM32F407 SD卡升级Bootloader程序:自动检测与升级流程,stm32f407 SD卡升级 bootloader程序 基于sdio fatfs系统的stm32 bootloader程序 功能简介: 本程序使用fatfs系统读取bin文件。 开机后会自动检测sd卡,检测到sd卡后,再读取固定名称的bin文件,之后会对bin文件进行首包校验,判断该升级包的起始地址是否正确,正确的话,就循环读取bin文件并写入到flash中。 完成升级。 详细流程请看流程图 ,stm32f407; SD卡升级; bootloader程序; fatfs系统读取bin文件; 检测SD卡; 首包校验; 循环写入flash。,STM32F407 SD卡升级Bootloader程序:基于SDIO FATFS系统实现自动升级功能
2025网络与信息安全技术题库及答案.doc
C# WinForm通用软件开发框架源码,基于VS2019 .NET与DevExpress 21,WebApi连接SQLServer2014数据库,互联网化数据访问模式,C# 源码 WinForm?通用软件开发框架平台源码 基于:C#Winform+ WebApi +SQLServer2014数据库 基于:VS2019.NET? DevExpress 21.2.6控件 基于:SQLServer2014?数据库 客户端通过Http访问WebApi获得json数据的模式,本系统走互联网,只需要把WebApi发布在公网即可。 说明:此框架源码除系统管理功能外,其它无源码 ,C#源码; WinForm; WebApi; SQLServer2014; VS2019.NET; DevExpress控件; 互联网模式; 系统管理功能; 发布。,C# WinForm开发框架:基于DevExpress与WebApi的通用软件平台源码
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
基于SqueezeNet迁移学习算法的滚动轴承故障诊断方法研究——在MATLAB r2021b环境下的应用与拓展至多元信号领域的研究,MATLAB环境下一种基于sqeezenet网络迁移学习的滚动轴承故障诊断方法。 算法运行环境为MATLAB r2021b,该代码展示了如何使用深度学习(迁移学习)方法对滚动轴承进行故障诊断,演示了如何将一维轴承振动信号转为二维尺度图图像并使用预训练网络应用迁移学习对轴承故障进行分类。 迁移学习显著减少了传统轴承诊断方法特征提取和特征选择所花费的时间,并在小型数据集中获得了良好的准确性。 算法可迁移至金融时间序列,地震 微震信号,机械振动信号,声发射信号,电压 电流信号,语音信号,声信号,生理信号(ECG,EEG,EMG)等信号。 ,MATLAB环境; SqueezeNet网络; 迁移学习; 滚动轴承故障诊断; 算法运行环境; 一维轴承振动信号转换; 二维尺度图图像; 特征提取和选择; 信号分析;迁移至其他类型信号 (以分号隔开),基于SqueezeNet迁移学习在MATLAB的滚动轴承故障诊断算法优化
基于弱形式PDE建模的COMSOL不相溶两相流渗流水驱油模拟研究,comsol不相溶两相流渗流模拟,水驱油,基于弱形式PDE建模,模型已验证。 ,核心关键词:comsol; 不相溶两相流; 渗流模拟; 水驱油; 弱形式PDE建模; 模型验证。,"基于弱形式PDE建模的COMSOL两相流渗流模拟:验证水驱油模型"
Tiled for Mac是一款功能强大的开源地图编辑器,适用于macOS系统。它支持正交、等距和六边形地图类型,可创建无限大小的地图,并支持多图层编辑。用户可以通过直观的界面快速添加、修改地图元素,使用像素精度放置对象,并支持图块动画和碰撞编辑。Tiled的TMX格式易于理解,支持多种插件扩展,兼容多种游戏引擎,如RPG和平台游戏。它还提供撤销/重做功能,方便用户调整和优化地图。
太阳能光伏MPPT控制蓄电池三阶段充电模型仿真说明文档(附扰动观测法仿真模型,R2015b版),充电控制器,太阳能光伏MPPT控制蓄电池充电模型。 其中,光伏MPPT控制采用扰动观测法(P&O法),蓄电池充电采用三阶段充电控制。 仿真模型附加一份仿真说明文档,便于理解和修改参数。 版本: R2015b ,充电控制器; 光伏MPPT控制; 扰动观测法(P&O法); 蓄电池充电控制; 三阶段充电控制; 仿真模型; 仿真说明文档; 版本:R2015b,"R2015b版:太阳能光伏MPPT三阶段充电控制仿真模型及说明"
项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql8.0 部署环境:Tomcat(建议用 7.x 或者 8.x 版本),maven 数据库工具:navicat
2025医院收费员考试题题库(含答案).docx
"欧姆龙PLC编程新手宝典:标准程序案例集,包括CP1H脉冲编程与触摸屏实战应用",欧姆龙PLC程序欧姆龙案例欧姆龙标准程序 本产品适用于新手或者在校生 本程序包括有欧姆龙CP1H脉冲程序案例,威纶通触摸屏程序,电子版讲义 程序涉及方面广,适合新手入门学习,掌握了这些以后欧姆龙脉冲程序基本通吃,编程起来无压力 本程序设计到CP1H各个轴的程序编写具体用了ACC PLS2 INI等众多指令, 每个轴的程序都是单独的,包括触摸屏在内,您可以直接调用程序套到直接的程序上,只需要把地址稍微改动即可。 本程序适用于新手、自动化专业在校生学习和提高,另外额外赠送主流的CAD电气原理图纸,包含各种主流的PLC接线原理图,各种成功案例,是每个电气工程师学习和提高最必不可少的资料 ,欧姆龙PLC程序; 欧姆龙案例; 欧姆龙标准程序; 新手学习; 在校生; CP1H脉冲程序案例; 威纶通触摸屏程序; 电子版讲义; 编程指令; 程序设计; PLC接线原理图; 成功案例。,欧姆龙PLC入门宝典:从新手到专业工程师的实用指南
"基于Simulink的锂电池SOC估计模型研究:卡尔曼滤波算法的参数辨识与模型优化",锂电池SOC估计模型 simulink SOC估算卡尔曼滤波估算 SOC电池参数辨识模型10个; 卡尔曼滤波算法锂电池SOC估算估算模型15个; 卡尔曼滤波31个; ,锂电池SOC估计模型; Simulink; SOC估算; 卡尔曼滤波估算; 电池参数辨识模型; 锂电池SOC卡尔曼滤波估算模型; 卡尔曼滤波,基于Simulink的锂电池SOC估计与卡尔曼滤波算法研究
苍鹰算法优化BP神经网络参数:多输入单输出预测建模及效果展示 注:此程序为matlab编写,可直接运行出多种预测结果图与评价指标。效果图为测试数据展示,具体预测效果以个人数据为准。,苍鹰优化算法NGO优化BP神经网络的软值和阈值参数做多输入单输出的拟合预测建模。 程序内注释详细直接替数据就可以使用。 程序语言为matlab。 程序直接运行可以出拟合预测图,迭代优化图,线性拟合预测图,多个预测评价指标。 PS:以下效果图为测试数据的效果图,主要目的是为了显示程序运行可以出的结果图,具体预测效果以个人的具体数据为准。 2.由于每个人的数据都是独一无二的,因此无法做到可以任何人的数据直接替就可以得到自己满意的效果。 ,核心关键词: 苍鹰优化算法; NGO优化; BP神经网络; 软值和阈值参数; 多输入单输出拟合预测建模; 程序内注释; MATLAB程序语言; 拟合预测图; 迭代优化图; 线性拟合预测图; 预测评价指标。,基于苍鹰优化算法的NGO-BP神经网络模型:多输入单输出拟合预测建模与评估