-
-
Save alsritter/3314a1e4038404b27992cd3e4b5de3db to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.alsritter.util; | |
import io.netty.util.internal.MathUtil; | |
import io.netty.util.internal.StringUtil; | |
import java.nio.ByteBuffer; | |
public class ByteBufferUtil { | |
private static final char[] BYTE2CHAR = new char[256]; | |
private static final char[] HEXDUMP_TABLE = new char[256 * 4]; | |
private static final String[] HEXPADDING = new String[16]; | |
private static final String[] HEXDUMP_ROWPREFIXES = new String[65536 >>> 4]; | |
private static final String[] BYTE2HEX = new String[256]; | |
private static final String[] BYTEPADDING = new String[16]; | |
static { | |
final char[] DIGITS = "0123456789abcdef".toCharArray(); | |
for (int i = 0; i < 256; i++) { | |
HEXDUMP_TABLE[i << 1] = DIGITS[i >>> 4 & 0x0F]; | |
HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F]; | |
} | |
int i; | |
// Generate the lookup table for hex dump paddings | |
for (i = 0; i < HEXPADDING.length; i++) { | |
int padding = HEXPADDING.length - i; | |
StringBuilder buf = new StringBuilder(padding * 3); | |
for (int j = 0; j < padding; j++) { | |
buf.append(" "); | |
} | |
HEXPADDING[i] = buf.toString(); | |
} | |
// Generate the lookup table for the start-offset header in each row (up to 64KiB). | |
for (i = 0; i < HEXDUMP_ROWPREFIXES.length; i++) { | |
StringBuilder buf = new StringBuilder(12); | |
buf.append(StringUtil.NEWLINE); | |
buf.append(Long.toHexString(i << 4 & 0xFFFFFFFFL | 0x100000000L)); | |
buf.setCharAt(buf.length() - 9, '|'); | |
buf.append('|'); | |
HEXDUMP_ROWPREFIXES[i] = buf.toString(); | |
} | |
// Generate the lookup table for byte-to-hex-dump conversion | |
for (i = 0; i < BYTE2HEX.length; i++) { | |
BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i); | |
} | |
// Generate the lookup table for byte dump paddings | |
for (i = 0; i < BYTEPADDING.length; i++) { | |
int padding = BYTEPADDING.length - i; | |
StringBuilder buf = new StringBuilder(padding); | |
for (int j = 0; j < padding; j++) { | |
buf.append(' '); | |
} | |
BYTEPADDING[i] = buf.toString(); | |
} | |
// Generate the lookup table for byte-to-char conversion | |
for (i = 0; i < BYTE2CHAR.length; i++) { | |
if (i <= 0x1f || i >= 0x7f) { | |
BYTE2CHAR[i] = '.'; | |
} else { | |
BYTE2CHAR[i] = (char) i; | |
} | |
} | |
} | |
/** | |
* 打印所有内容 | |
* | |
* @param buffer | |
*/ | |
public static void debugAll(ByteBuffer buffer) { | |
int oldlimit = buffer.limit(); | |
buffer.limit(buffer.capacity()); | |
StringBuilder origin = new StringBuilder(256); | |
appendPrettyHexDump(origin, buffer, 0, buffer.capacity()); | |
System.out.println("+--------+-------------------- all ------------------------+----------------+"); | |
System.out.printf("position: [%d], limit: [%d]\n", buffer.position(), oldlimit); | |
System.out.println(origin); | |
buffer.limit(oldlimit); | |
} | |
/** | |
* 打印可读取内容 | |
* | |
* @param buffer | |
*/ | |
public static void debugRead(ByteBuffer buffer) { | |
StringBuilder builder = new StringBuilder(256); | |
appendPrettyHexDump(builder, buffer, buffer.position(), buffer.limit() - buffer.position()); | |
System.out.println("+--------+-------------------- read -----------------------+----------------+"); | |
System.out.printf("position: [%d], limit: [%d]\n", buffer.position(), buffer.limit()); | |
System.out.println(builder); | |
} | |
private static void appendPrettyHexDump(StringBuilder dump, ByteBuffer buf, int offset, int length) { | |
if (MathUtil.isOutOfBounds(offset, length, buf.capacity())) { | |
throw new IndexOutOfBoundsException( | |
"expected: " + "0 <= offset(" + offset + ") <= offset + length(" + length | |
+ ") <= " + "buf.capacity(" + buf.capacity() + ')'); | |
} | |
if (length == 0) { | |
return; | |
} | |
dump.append( | |
" +-------------------------------------------------+" + | |
StringUtil.NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" + | |
StringUtil.NEWLINE + "+--------+-------------------------------------------------+----------------+"); | |
final int startIndex = offset; | |
final int fullRows = length >>> 4; | |
final int remainder = length & 0xF; | |
// Dump the rows which have 16 bytes. | |
for (int row = 0; row < fullRows; row++) { | |
int rowStartIndex = (row << 4) + startIndex; | |
// Per-row prefix. | |
appendHexDumpRowPrefix(dump, row, rowStartIndex); | |
// Hex dump | |
int rowEndIndex = rowStartIndex + 16; | |
for (int j = rowStartIndex; j < rowEndIndex; j++) { | |
dump.append(BYTE2HEX[getUnsignedByte(buf, j)]); | |
} | |
dump.append(" |"); | |
// ASCII dump | |
for (int j = rowStartIndex; j < rowEndIndex; j++) { | |
dump.append(BYTE2CHAR[getUnsignedByte(buf, j)]); | |
} | |
dump.append('|'); | |
} | |
// Dump the last row which has less than 16 bytes. | |
if (remainder != 0) { | |
int rowStartIndex = (fullRows << 4) + startIndex; | |
appendHexDumpRowPrefix(dump, fullRows, rowStartIndex); | |
// Hex dump | |
int rowEndIndex = rowStartIndex + remainder; | |
for (int j = rowStartIndex; j < rowEndIndex; j++) { | |
dump.append(BYTE2HEX[getUnsignedByte(buf, j)]); | |
} | |
dump.append(HEXPADDING[remainder]); | |
dump.append(" |"); | |
// Ascii dump | |
for (int j = rowStartIndex; j < rowEndIndex; j++) { | |
dump.append(BYTE2CHAR[getUnsignedByte(buf, j)]); | |
} | |
dump.append(BYTEPADDING[remainder]); | |
dump.append('|'); | |
} | |
dump.append(StringUtil.NEWLINE + | |
"+--------+-------------------------------------------------+----------------+"); | |
} | |
private static void appendHexDumpRowPrefix(StringBuilder dump, int row, int rowStartIndex) { | |
if (row < HEXDUMP_ROWPREFIXES.length) { | |
dump.append(HEXDUMP_ROWPREFIXES[row]); | |
} else { | |
dump.append(StringUtil.NEWLINE); | |
dump.append(Long.toHexString(rowStartIndex & 0xFFFFFFFFL | 0x100000000L)); | |
dump.setCharAt(dump.length() - 9, '|'); | |
dump.append('|'); | |
} | |
} | |
public static short getUnsignedByte(ByteBuffer buffer, int index) { | |
return (short) (buffer.get(index) & 0xFF); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment