- 浏览: 3052605 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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分享的概要
这是差不多一年前写的程序了……有人说想看于是发出来。
当时也是为了求快,代码结构乱七八糟的。不过现在也没什么时间把这代码重构一次,就这么原样发出来吧。嗯,好歹应该把LZSS、文件IO之类的方法扔到外面去的……后来在处理ケータイ少女啊之类的东西的时候就没这么乱了,不过文件一时找不到了 T T
如果没记错的话当时是直接从BlowfishJ里拿了BinConverter.java来,然后加了些方法进去。因此以下代码以LGPL许可证发布。
哦,对了。解图片出来的时候我偷懒了。32位的BMP图我就这么直接写到文件里了而没做处理——意味着图片是“正向BMP”,有些图片浏览程序打开的时候可能会不太正常……
Extract.java:
Header.java:
IndexEntry.java:
BinConverter.java:
当时也是为了求快,代码结构乱七八糟的。不过现在也没什么时间把这代码重构一次,就这么原样发出来吧。嗯,好歹应该把LZSS、文件IO之类的方法扔到外面去的……后来在处理ケータイ少女啊之类的东西的时候就没这么乱了,不过文件一时找不到了 T T
如果没记错的话当时是直接从BlowfishJ里拿了BinConverter.java来,然后加了些方法进去。因此以下代码以LGPL许可证发布。
哦,对了。解图片出来的时候我偷懒了。32位的BMP图我就这么直接写到文件里了而没做处理——意味着图片是“正向BMP”,有些图片浏览程序打开的时候可能会不太正常……
Extract.java:
import java.io.*; import java.util.*; class Extract { /////////////////////////// // Common constants /////////////////////////// private static final int WINDOW_LENGTH = 4096; /////////////////////////// // Signature constants /////////////////////////// //------------------------- // Scr.pak //------------------------- private static final byte[] scwSig = { (byte)'S', (byte)'c', (byte)'w', (byte)'5', (byte)'.', (byte)'x', (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 }; private static final byte[] unknownSig = { (byte)0, (byte)0, (byte)0, (byte)5, (byte)0x0FF, (byte)0x0FF, (byte)0x0FF, (byte)0x0FF }; //------------------------- // Graphic.pak //------------------------- private static final byte[] grpSig = { (byte)0, (byte)0, (byte)4, (byte)0 }; //------------------------- // BGM.pak, SE.pak //------------------------- private static final byte[] oggSig = { (byte)'O', (byte)'g', (byte)'g', (byte)'S' }; /////////////////////////// // Global variables /////////////////////////// private static RandomAccessFile raf = null; private static BufferedWriter writer = null; private static Header header = null; private static IndexEntry[] index = null; /////////////////////////// // Program entry point /////////////////////////// public static void main(String[] args) throws Exception { String srcFilename = args[0]; if (srcFilename == null || srcFilename.trim().length() == 0) warnAndExit("Usage: java Extract srcFile\nwhere srcFile is the filename of the file to be extracted."); // read archive header FileInputStream tempFis = new FileInputStream(srcFilename); byte[] headerBytes = new byte[Header.BUFFER_SIZE]; tempFis.read(headerBytes); tempFis.close(); tempFis = null; // dispose this input stream // parse archive header parseHeader(headerBytes); // open source archive file raf = new RandomAccessFile(srcFilename, "r"); // read file index raf.seek(header.getIndexBaseOffset()); byte[] indexBytes = new byte[header.getIndexCompSize()]; raf.read(indexBytes); // DEBUG ONLY! System.err.println("indexCompSize =0x" + Integer.toHexString(header.getIndexCompSize()).toUpperCase()); System.err.println("fileCount =0x" + Integer.toHexString(header.getFileCount()).toUpperCase()); System.err.println("indexOrigSize =0x" + Integer.toHexString(IndexEntry.LENGTH_IN_FILE * header.getFileCount()).toUpperCase()); System.err.println("dataBaseOffset =0x" + Long.toHexString(header.getDataBaseOffset()).toUpperCase()); System.err.println("indexBaseOffset =0x" + Long.toHexString(header.getIndexBaseOffset()).toUpperCase()); System.err.println(); // decompress file index indexBytes = lzssDecompress(indexBytes, header.getIndexCompSize(), null, IndexEntry.LENGTH_IN_FILE * header.getFileCount()); // parse file index parseIndex(indexBytes); // extract files from archive byte[] bytes16 = new byte[16]; for (IndexEntry entry : index) { System.err.print("Extracting file " + entry.getFilename() + " at 0x" + Long.toHexString(header.getDataBaseOffset() + entry.getOffset()).toUpperCase() + "..."); // set file pointer raf.seek(header.getDataBaseOffset() + entry.getOffset()); // read signature raf.read(bytes16); // reset file pointer raf.seek(header.getDataBaseOffset() + entry.getOffset()); // match known signatures if (match(bytes16, scwSig)) { // script file writeScriptFile(entry); } else if (BinConverter.byteArrayToInt(bytes16, 0) == 0x00000400) { // graphic file writeGraphicFile(entry); } else if (BinConverter.byteArrayToInt(bytes16, 0) == 0x4F676753) { // Ogg file writeOggFile(entry); } else { warnAndExit("Unsupported file format found in archive, 0x" + Long.toHexString( header.getDataBaseOffset() + entry.getOffset()).toUpperCase()); } System.err.println("done"); } raf.close(); } private static void parseHeader(byte[] buf) throws IOException { header = new Header(); byte[] temp = null; // check against archive signature temp = extractArray(buf, Header.ARCHIVE_SIG_OFS, Header.ARCHIVE_SIG_LEN); if (!match(temp, Header.dataPackSig)) warnAndExit("Unsupported archive type"); // check against archive subtype signature temp = extractArray(buf, Header.SUBTYPE_SIG_OFS, Header.SUBTYPE_SIG_LEN); if (!match(temp, Header.momoSig)) warnAndExit("Unsupported archive subtype"); // check against magic value temp = extractArray(buf, Header.MAGIC_OFS, Header.MAGIC_LEN); if (!match(temp, Header.magic)) warnAndExit("Unexpected magic value"); header.setIndexCompSize( BinConverter.byteArrayToIntLE(buf, Header.INDEX_COMPSIZE_OFS)); header.setFileCount( BinConverter.byteArrayToIntLE(buf, Header.FILE_COUNT_OFS)); header.setDataBaseOffset( BinConverter.byteArrayToIntLE(buf, Header.DATA_BASEOFFSET_OFS) & 0x0FFFFFFFFL); header.setIndexBaseOffset( BinConverter.byteArrayToIntLE(buf, Header.INDEX_BASEOFFSET_OFS) & 0x0FFFFFFFFL); } private static void parseIndex(byte[] buf) throws IOException { index = new IndexEntry[header.getFileCount()]; int baseOfs = 0; for (int i = 0; i < index.length; ++i) { index[i] = new IndexEntry(); IndexEntry current = index[i]; current.setFilename( readCString( new ByteArrayInputStream(buf, baseOfs + IndexEntry.FILENAME_OFS, IndexEntry.FILENAME_LEN))); current.setOffset(BinConverter.byteArrayToIntLE(buf, baseOfs + IndexEntry.OFFSET_OFS)); current.setSize(BinConverter.byteArrayToIntLE(buf, baseOfs + IndexEntry.SIZE_OFS)); baseOfs += IndexEntry.LENGTH_IN_FILE; } } private static byte[] extractArray(byte[] src, int srcPos, int len) { byte[] result = new byte[len]; Arrays.fill(result, (byte)0); System.arraycopy(src, srcPos, result, 0, len); return result; } private static boolean match(byte[] b1, byte[] b2) { return Arrays.equals(b1, b2); } private static void exit(int back) throws IOException { writer.write("Error at: 0x" + Long.toHexString(raf.getFilePointer() - back)); writer.newLine(); System.exit(1); } private static void warnAndExit(String mes) { System.err.println(mes); System.exit(1); } private static void xorDecode(byte[] b) { for (int offset = 0; offset < b.length; ++offset) { b[offset] = (byte)(b[offset] ^ offset); } } private static byte[] lzssDecompress(byte[] from, int compLen, byte[] to, int origLen) { return lzssDecompress(from, compLen, to, 0, origLen); } private static byte[] lzssDecompress(byte[] from, int compLen, byte[] to, int pos, int origLen) { if (to == null) to = new byte[origLen]; byte[] window = new byte[WINDOW_LENGTH]; int readOffset = 0; int writeOffset = pos; int marker = 0; // read marker, 8-bits, 1 for raw byte, 0 for back ref int windowWriteOffset = 0x0FEE; int windowReadOffset = 0; int backRefLength = 0; int current = 0; while (readOffset != from.length) { marker >>= 1; if ((marker & 0x0100) == 0) { current = from[readOffset++] & 0x0FF; marker = 0x0FF00 | current; } if(readOffset == from.length) break; if ((marker & 0x01) == 1) { // copy raw bytes current = from[readOffset++] & 0x0FF; to[writeOffset++] = (byte)current; window[windowWriteOffset++] = (byte)current; windowWriteOffset &= 0x0FFF; } else { // copy from slide window windowReadOffset = from[readOffset++] & 0x0FF; if(readOffset == from.length) break; current = from[readOffset++] & 0x0FF; windowReadOffset |= (current & 0x0F0) << 4; backRefLength = (current & 0x0F) + 2; if (backRefLength < 0) continue; int addOffset = 0; while (addOffset <= backRefLength) { int curOfs = (windowReadOffset + addOffset++) & 0x0FFF; current = window[curOfs] & 0x0FF; windowReadOffset &= 0x0FFF; to[writeOffset++] = (byte)current; window[windowWriteOffset++] = (byte)current; windowWriteOffset &= 0x0FFF; } // while } // if-else } // while return to; } private static String readCString(InputStream in) throws IOException { ArrayList<Byte> list = new ArrayList<Byte>(); int i = in.read(); while (i != 0) { list.add((byte)i); i = in.read(); } int size = list.size(); byte[] b = new byte[size]; for (i = 0; i < size; ++i) b[i] = list.get(i); return new String(b); } private static void writeGraphicFile(IndexEntry entry) throws IOException { // initialize some constants for Windows Bitmap header int bitmapDataOffset = 0x036; int bitmapHeaderSize = 0x028; int width = 0; // dummy value int height = 0; // dummy value int planes = 1; // locked value for a standard Windows Bitmap int depth = 0; // dummy value int compression = 0; // we're not gonna use compression here int dataSize = 0; // dummy value int hRes = 0; // 0x0B12; // 72? int vRes = 0; // 0x0B12; // 72? int colorsUsed = 0; // set to zero, indicating it's same as depth int colorsImportant = 0; // no palette used here // check against graphic file signature if (raf.readInt() != 0x00000400) exit(4); // get size info int compSize = BinConverter.reverseEndian(raf.readInt()); int origSize = BinConverter.reverseEndian(raf.readInt()); int headerLen = BinConverter.reverseEndian(raf.readInt()); if (raf.readInt() != 0) exit(4); // what's this? seems like it's always zero width = BinConverter.reverseEndian(raf.readInt()); height = BinConverter.reverseEndian(raf.readInt()); depth = BinConverter.reverseEndianShort(raf.readShort()); dataSize = origSize; // fine tune a few values colorsUsed = depth <= 8 ? (1 << depth) : 0; int actPaletteLen = depth <= 8 ? (1 << depth) * 4 : 0; // skip a few bytes... // raf.skip(); raf.seek(header.getDataBaseOffset() + entry.getOffset() + headerLen); // read the compressed data byte[] readBuffer = new byte[compSize]; raf.read(readBuffer); // build BMP header byte[] writeBuffer = new byte[origSize + 0x036]; writeBuffer[0] = (byte)'B'; writeBuffer[1] = (byte)'M'; BinConverter.intToByteArrayLE(origSize + bitmapDataOffset, writeBuffer, 0x02); BinConverter.intToByteArrayLE(0, writeBuffer, 0x06); BinConverter.intToByteArrayLE(bitmapDataOffset + actPaletteLen, writeBuffer, 0x0A); BinConverter.intToByteArrayLE(bitmapHeaderSize, writeBuffer, 0x0E); BinConverter.intToByteArrayLE(width, writeBuffer, 0x012); BinConverter.intToByteArrayLE(-height, writeBuffer, 0x016); // negative height value for "not-reversed" bitmap BinConverter.shortToByteArrayLE(planes, writeBuffer, 0x01A); BinConverter.shortToByteArrayLE(depth, writeBuffer, 0x01C); BinConverter.intToByteArrayLE(compression, writeBuffer, 0x01E); BinConverter.intToByteArrayLE(dataSize - actPaletteLen, writeBuffer, 0x022); BinConverter.intToByteArrayLE(hRes, writeBuffer, 0x026); BinConverter.intToByteArrayLE(vRes, writeBuffer, 0x02A); BinConverter.intToByteArrayLE(colorsUsed, writeBuffer, 0x02E); BinConverter.intToByteArrayLE(colorsImportant, writeBuffer, 0x032); // LZSS decompress lzssDecompress(readBuffer, compSize, writeBuffer, bitmapDataOffset, origSize); // write out the bitmap file writeFile(writeBuffer, entry.getFilename() + ".bmp"); } private static void writeOggFile(IndexEntry entry) throws IOException { // read the compressed and encrypted data byte[] readBuffer = new byte[entry.getSize()]; raf.read(readBuffer); writeFile(readBuffer, entry.getFilename() + ".ogg"); } private static void writeScriptFile(IndexEntry entry) throws IOException { final int headerLen = 456; // check against script file signature byte[] bytes16 = new byte[16]; raf.read(bytes16); if (!match(bytes16, scwSig)) exit(16); // check against script file magic value byte[] bytes8 = new byte[8]; raf.read(bytes8); if (!match(bytes8, unknownSig)) exit(8); // get size info int origSize = BinConverter.reverseEndian(raf.readInt()); int compSize = BinConverter.reverseEndian(raf.readInt()); // skip a few bytes... // raf.skipBytes(424); // do something about this... raf.seek(header.getDataBaseOffset() + entry.getOffset() + headerLen); // read the compressed and encrypted data byte[] readBuffer = new byte[compSize]; raf.read(readBuffer); // XOR decrypt xorDecode(readBuffer); // LZSS decompress byte[] writeBuffer = lzssDecompress(readBuffer, compSize, null, origSize); writeFile(writeBuffer, entry.getFilename() + ".scw"); } private static void writeFile(byte[] buf, String name) throws IOException { File dir = new File("./data/"); if (!dir.exists()) dir.mkdirs(); FileOutputStream fos = new FileOutputStream("./data/" + name); fos.write(buf); fos.flush(); fos.close(); } }
Header.java:
public class Header { public static final int BUFFER_SIZE = 4096; public static final int ARCHIVE_SIG_OFS = 0; public static final int ARCHIVE_SIG_LEN = 16; public static final int SUBTYPE_SIG_OFS = 16; public static final int SUBTYPE_SIG_LEN = 32; public static final int MAGIC_OFS = 48; public static final int MAGIC_LEN = 4; public static final int INDEX_COMPSIZE_OFS = 52; public static final int FILE_COUNT_OFS = 60; public static final int DATA_BASEOFFSET_OFS = 64; public static final int INDEX_BASEOFFSET_OFS = 68; public static final byte[] dataPackSig = { (byte)'D', (byte)'a', (byte)'t', (byte)'a', (byte)'P', (byte)'a', (byte)'c', (byte)'k', (byte)'5', (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 }; public static final byte[] momoSig = { (byte)'M', (byte)'O', (byte)'M', (byte)'O', (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 }; public static final byte[] magic = { (byte)1, (byte)0, (byte)5, (byte)0 }; private int indexCompSize; private int fileCount; private long dataBaseOffset; private long indexBaseOffset; public int getIndexCompSize() { return indexCompSize; } public void setIndexCompSize(int size) { this.indexCompSize = size; } public int getFileCount() { return fileCount; } public void setFileCount(int count) { this.fileCount = count; } public long getDataBaseOffset() { return dataBaseOffset; } public void setDataBaseOffset(long offset) { this.dataBaseOffset = offset; } public long getIndexBaseOffset() { return indexBaseOffset; } public void setIndexBaseOffset(long offset) { this.indexBaseOffset = offset; } }
IndexEntry.java:
public class IndexEntry { public static final int LENGTH_IN_FILE = 104; public static final int FILENAME_OFS = 0; public static final int FILENAME_LEN = 64; public static final int OFFSET_OFS = 64; public static final int SIZE_OFS = 68; private String filename; private int offset; // actual offset = base + offset private int size; public String getFilename() { return filename; } public void setFilename(String name) { this.filename = name; } public int getOffset() { return offset; } public void setOffset(int offset) { this.offset = offset; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
BinConverter.java:
/** * Some helper routines for data conversion, data is treated in network * byte order except the ones with LE postfix. */ public class BinConverter { /** * Gets bytes from an array into an integer. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 32bit integer */ public final static int byteArrayToInt( byte[] buf, int ofs) { return (buf[ofs ] << 24) | ((buf[ofs + 1] & 0x0ff) << 16) | ((buf[ofs + 2] & 0x0ff) << 8 ) | ( buf[ofs + 3] & 0x0ff); } // Little Endian 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, 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 intToByteArray( 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; } // Little endian 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; } public final static void shortToByteArrayLE( int value, byte[] buf, int ofs) { 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(); } /////////////////////////////////////////////////////////////////////////// /** * Reverses between endians for integers * @param i the integer to convert endian * @return integer of reversed endian */ public final static int reverseEndian(int i) { byte[] temp = new byte[4]; temp[0] = (byte)(i >> 24); temp[1] = (byte)(i >> 16); temp[2] = (byte)(i >> 8 ); temp[3] = (byte)i; return (temp[3] << 24) & 0xFF000000 | (temp[2] << 16) & 0x00FF0000 | (temp[1] << 8 ) & 0x0000FF00 | temp[0] & 0x000000FF; } /** * Reverses between endians for integers * @param i the integer to convert endian * @return integer of reversed endian */ public final static short reverseEndianShort(short s) { byte[] temp = new byte[2]; temp[0] = (byte)(s >> 8 ); temp[1] = (byte)s; return (short)((temp[1] << 8 ) & 0x0FF00 | temp[0] & 0x000FF); } }
发表评论
-
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 1572年初写的Quartett!的文本 ... -
BattleMoonWars 归档解压/压缩程序 (Java)
2008-04-08 16:44 2448呼,这个也是一年多之 ... -
ケータイ少女 script.arc的解压缩程序 (Java)
2008-04-08 14:02 4657嗯,这个也是快一年前写的了。当时在澄空看到有人想要解手机少女的 ... -
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方面确 ...
相关推荐
音频模块2.0。1.删除部分命令。2.优化部分命令。3.修复针对1.0版部分命令功能。4.修正部分命令无效功能。5.对命令重新整理分类。6.针对1.0版模块增加功能。媒体音量。媒体效果。媒体功能。...@易华月妆。
丹参酮ⅡA乳剂对NB4细胞的诱导分化与凋亡作用,李慧,石华月,目的 探讨丹参酮ⅡA乳剂对人早幼粒细胞白血病NB4细胞的诱导分化与凋亡作用。方法 将丹参酮ⅡA乳剂与NB4细胞在体外共同培养5天,观�
springMVC相关技术配置使用注解的HandlerMapping和HandlerAdapter使用<mvc:annotation-driver> 不过springBoot已经省略了这些配置 配置使用注解的Handler和Service...@RequestBody,@ResponseBody--json与java对象转换
总结来说,这是一个完整的嵌入式系统设计案例,涵盖了硬件设计(原理图和PCB)、软件编程(程序)、电路仿真和实际应用等多个环节,对于学习51单片机和数字温度计设计的初学者来说,是一份宝贵的参考资料。...
用户可以通过编写相应的控制程序,读取DS18B20输出的温度数据。由于其独特的单线通信方式,需要正确配置微控制器的输入输出引脚,以便正确识别和解析DS18B20发送的数据。 描述中提到的“DS18B20测温模块 温度传感器...
EDA(Electronic Design Automation)技术是电子设计自动化领域的核心技术,它涵盖了集成电路设计、系统级设计、硬件描述语言(HDL)、仿真验证、综合优化、布局布线等多方面的内容。在这个“EDA技术数字钟控制器...