在某A项目中,需要使用第三方系统socket接口,但第三系统无法提供接口定义。

过程中,采用方法:使用抓包工具Wireshark抓tcp包,分析抓取报文;通过报文分析接口逆向分析接口定义。(项目风险很大)

抓包工具抓取的都是16进制、2进制字节报文,由此引发我对字节与字符串互转方式的实验。

示例,源码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;

public class TestUtf8 {

	public static void main(String[] args) throws Exception {
		final String ENCODING = \"GBK\";

		System.out.println(\"运行jdk环境的编码   =   \" +  System.getProperty(\"file.encoding\") );
		System.out.println(\"字符串<->字节byte 编码   =   \" +  ENCODING );

		/** 测试1,字符串 转 字节**/
		String testString = \"Hello汉字\";
		String byteHexStr = testStringToBytes(testString, ENCODING);

		/** 测试2,字节(16进制) 转 字符串 **/
		testBytesHexToString(byteHexStr, ENCODING);
	}

	public static String testStringToBytes(final String str, final String ENCODING) throws Exception {
		System.out.println(\"//==========================================================\");
		System.out.println(\"// 测试1,字符串 转 字节,字符集 = \" + ENCODING);
		System.out.println(\"//       字符串 = \" + str);
		System.out.println(\"//       字符集编码 = \" + ENCODING);
		System.out.println(\"//==========================================================\");

		byte[] bytes = str.getBytes(ENCODING);
		StringBuilder byteHexSB = new StringBuilder(); 

		MyTable table = new MyTable();
		table.addRow(\"byte.index\", \"10.value\", \"16.value\", \"2.value\");
		for (int i = 0; i < bytes.length; i++) {
			byte b = bytes[i];

			int byteVal = b & 0xFF; // 一个byte占1个字节,0xFF是16进制也代表8位==1个字节,位于操作可以防止出现负数。
			
			String byteHexString = Integer.toHexString(byteVal); // byte整数值得16进制表达,不够2位前面补0
			byteHexString = flushLeft(\'0\', 2, byteHexString);
			String byteBinaryString = Integer.toBinaryString(byteVal);
			byteBinaryString = flushLeft(\'0\', 16, byteBinaryString);
			
			byteHexSB.append(byteHexString);

			table.addRow(\"\"+i, \"\"+byteVal, byteHexString, byteBinaryString);
		}
		table.printTable();

		// 字符串的字节数组,16进制表示。字符串中2位代表一个字节byte
		return byteHexSB.toString();
	}

	public static void testBytesHexToString(final String byteHexStr, final String ENCODING) throws Exception {
		System.out.println(\"//==========================================================\");
		System.out.println(\"// 测试2,字节(16进制) 转 字符串,字符集 = \" + ENCODING);
		System.out.println(\"//       16进制byte = \" + byteHexStr);
		System.out.println(\"//       字符集编码 = \" + ENCODING);
		System.out.println(\"//==========================================================\");
		byte[] convertByte= convertByteFromHex(byteHexStr);
		String newString = new String(convertByte, ENCODING);
		System.out.println(\"	转换为字符串:\" + newString);
	}

	/**
	 * @param byteHexString
	 * @return 将16进制记录下的byte流,翻译成byte[]数组
	 */
	public static byte[] convertByteFromHex(String byteHexString) {
		List<Byte> list = new ArrayList<>(); 
		int index = 0;
		while(index < byteHexString.length() - 1) {
			byte b = Integer.valueOf(byteHexString.substring(index, index + 2 ), 16).byteValue();
			list.add(b);

			index += 2;
		}

		byte[] ret = new byte[list.size()];
		IntStream.range(0, list.size()).forEach(i -> {
			ret[i] = list.get(i);
		});
		return ret;
	}

	private static String flushLeft(char c, int length, String content) {
		int contentLengh = content.length();

		if(contentLengh >= length) {
			return content;
		}
		StringBuilder sb = new StringBuilder();
		IntStream.range(0, length - contentLengh).forEach(i -> {
			sb.append(c);
		});
		sb.append(content);
		return sb.toString();
	}


	static class MyTable {
		private int columnSize;
		private List<List<String>> rows = new ArrayList<>();
		private List<Integer> columnSizeList = new ArrayList<>();
		
		public void addRow(String... column) {
			if (columnSize == 0) {
				columnSize = column.length;
			}

			if(columnSize != column.length) {
				throw new RuntimeException(String.format(\"列数不一致%d != %d \", columnSize, column.length));
			}
			
			List<String> row = Arrays.asList(column);
			rows.add(row);

			if(columnSizeList.isEmpty()) {
				IntStream.range(0, columnSize).forEach(i -> {
					int curSize = column[i].length();
					columnSizeList.add(curSize);
				});
			}else if(!columnSizeList.isEmpty()) { // 更新每列的宽度
				IntStream.range(0, columnSize).forEach(i -> {
					int curSize = column[i].length();
					
					if(columnSizeList.get(i) < curSize) {
						columnSizeList.set(i, curSize);
					}
				});
			}
		}
		public void printTable() {
			rows.stream().forEach( row -> {
				System.out.println(rendderRow(row));
			});
		}
		private String rendderRow(List<String> row) {
			int addSize = 2;
			StringBuilder sb = new StringBuilder();
			
			sb.append(\"	|\");

			IntStream.range(0, columnSize).forEach(i -> {
				String column = row.get(i);
				String newColumnContent = flushLeft(\' \', addSize + columnSizeList.get(i), column);
				sb.append(newColumnContent)
					.append(\" |\" );
			});
			
			return sb.toString();
		}
	}
}

 

 

 

收藏 打印