⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decoder.java

📁 一个sms格式的PPC端短信备份的还原工具。原备份软件BkGenuis包含在rar文件内。 PPC上有个绿色的单独的短信备份还原工具
💻 JAVA
字号:
/**
 * 
 */
import java.io.*;
import java.io.BufferedReader;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Calendar;

/**
 * @author Slice
 * @email licesh@gmail.com
 */

public class Decoder {

	private long dl;

	private Calendar c;

	public Decoder() {
		c = Calendar.getInstance();
		c.set(1601, 0, 1, 8, 0, 0);// 取得1601-1-1
		// 8:00:00的millisec值。结果为负,因为Calendar计算millisec是
		// offset from the Epoch, January 1, 1970 00:00:00.000 GMT (Gregorian)
		dl = c.getTimeInMillis();
	}

	private long hexBytes2Long(byte[] hexBytes) {// big endian 低地址放低位
		int n = hexBytes.length;
		String hex;
		String s = "";
		for (int i = n - 1; i >= 0; i--) {// 转成little endian
			hex = Integer.toHexString(hexBytes[i] & 0XFF);// 在32位的电脑中数字都是以32格式存放的,如果是一个byte(8位)类型的数字,他的高24位里面都是随机数字,低8位
			// 才是实际的数据。java.lang.Integer.toHexString()
			// 方法的参数是int(32位)类型,如果输入一个byte(8位)类型的数字,这个
			// 方法会把这个数字的高24为也看作有效位,这就必然导致错误,使用&
			// 0XFF操作,可以把高24位置0以避免这样错误的发生。
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			s += hex;
		}
		return Long.parseLong(s, 16);
	}

	public void decodeSMSBak(File file) {

		String decStr = new String();
		byte[] b;
		byte[] byteTime = new byte[8];
		boolean type = true;// 标志信息类型 true为receive false 为send

		int i = 0, j = i;

		try {
			b = readFileToBytes(file);

			i = 4;// 前四个byte为文件头 暂且跳过
			j = i;

			while (i < b.length) {
				// 根据两byte信息头判断是接收还是发送
				if (b[j] == 11 && b[j + 1] == 1)// 0x0B 0x01
					type = true;// receive
				else if (b[j] == 22 && b[j + 1] == 33)// 0x16 0x21
					type = false;// send

				if (type) {// receive
					i = j + 5;// 跳到8byte时间信息
					// ////
					for (j = i; j < i + 8; j++) {
						byteTime[j - i] = b[j];
					}
					long oldl = hexBytes2Long(byteTime);// 万分之一毫秒数
					long nowl = oldl / 10000 + dl;// 计算当前的时刻相对Epoch的millisec
					c.setTimeInMillis(nowl);// 通过millisec设置Calendar,即可得到字符串表示
					decStr += c.get(Calendar.YEAR) + "-"
							+ (c.get(Calendar.MONTH) + 1) + "-"
							+ c.get(Calendar.DAY_OF_MONTH) + " "
							+ c.get(Calendar.HOUR_OF_DAY) + ":"
							+ c.get(Calendar.MINUTE) + ":"
							+ c.get(Calendar.SECOND) + " 周"
							+ c.get(Calendar.DAY_OF_WEEK);
					// /
					i += 16;
					for (j = i;; j += 2)
						if (b[j] == 0 && b[j + 1] == 0)// 定位至XX 00 00(j) 00
							break;
					j -= 2;// j移动至XX处 即号码后

					decStr += "\t发送人:";
					decStr += decodeString(b, i, j);// 解析name 和 号码
					j += 4;// j移动到XX 00 00 00后 即第二个name处
					i = j;
					for (;; j += 2)
						if (b[j] == 0 && b[j + 1] == 0)// 定位至第二处XX 00 00(j) 00
							break;
					j -= 2;// j移动至第二XX处 即第二name后
					// decStr += decodeString(b, i, j);// 解析第二name
					j += 4;// j移动到MSG头处
					i = j;
					for (;; j += 2)
						if (b[j] == 0 && b[j + 1] == 0 && b[j + 2] == 0
								&& b[j + 3] == 0)// j定位至00 00 00 00处,即一条信息尾部
							break;
					decStr += "\t内容:" + decodeString(b, i, j);// 解析信息内容
					decStr += "\r\n";
					j += 4;// j移动至下一条信息头 即信息类型标志位
					i = j;

				} else {// send
					i += 5;
					// ////
					for (j = i; j < i + 8; j++) {
						byteTime[j - i] = b[j];
					}
					long oldl = hexBytes2Long(byteTime);// 万分之一毫秒数
					long nowl = oldl / 10000 + dl;// 计算当前的时刻相对Epoch的millisec
					c.setTimeInMillis(nowl);// 通过millisec设置Calendar,即可得到字符串表示
					decStr += c.get(Calendar.YEAR) + "-"
							+ (c.get(Calendar.MONTH) + 1) + "-"
							+ c.get(Calendar.DAY_OF_MONTH) + " "
							+ c.get(Calendar.HOUR_OF_DAY) + ":"
							+ c.get(Calendar.MINUTE) + ":"
							+ c.get(Calendar.SECOND) + " 周"
							+ c.get(Calendar.DAY_OF_WEEK);
					// /
					i += 12;// 暂且跳过17byte时间等信息
					for (j = i;; j += 2)
						if (b[j] == 59 && b[j + 1] == 0)// 定位至0x3B(j) 00 00 00
							// 00 00 00 00 00 00 XX
							// 00 00 00处
							break;

					decStr += "\t接收人:";
					decStr += decodeString(b, i, j);// 解析name
					j += 14;// 跳过上述14未知类型的byte,至内容开头
					i = j;
					for (;; j += 2)
						if (b[j] == 0 && b[j + 1] == 0 && b[j + 2] == 0
								&& b[j + 3] == 0)// j定位至00 00 00 00处,即一条信息尾部
							break;
					decStr += "\t内容:" + decodeString(b, i, j);
					decStr += "\r\n";
					j += 4;// j移动至下一条信息头 即信息类型标志位
					i = j;
				}
			}
			// System.out.print(decStr);
			writeFile("msgs.txt", decStr);
		} catch (Exception e) {
			e.printStackTrace();
			// System.out.print(decStr);
			try {
				writeFile("msgs.txt", decStr);
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

	/**
	 * decode string from byte[]
	 * 
	 * @param i
	 *            start index
	 * @param j
	 *            end index
	 * @return decoded string
	 */

	private static String decodeString(byte[] b, int i, int j) {
		try {
			byte[] temp = new byte[j - i];
			for (int k = i, l = 0; k < j; k += 2, l += 2) {
				temp[l + 1] = b[k];
				temp[l] = b[k + 1];
			}
			return new String(temp, "Unicode");
		} catch (Exception e) {
			// e.printStackTrace();
			System.out.print(Integer.toString(i) + "," + Integer.toString(j)
					+ "\n");

			return null;
		}
	}

	public static void main(String[] args) {
		// try {
		// String s = new String(new byte[] { 0x01, 0x0b, 0x21, 0x16 },
		// "Unicode");
		// s += ";";
		// } catch (Exception e) {
		// e.printStackTrace();
		// }

		// System.out.println(c.getTime().toString());
		// Timestamp ts = Timestamp.valueOf("2009-1-21 17:48:2");
		Decoder de = new Decoder();
		de.decodeSMSBak(new File("input.sms"));
	}

	/**
	 * read content from input file
	 * 
	 * @param fileName
	 *            input file name
	 * @return String file content
	 */
	private static String readFile(String fileName) {
		try {
			BufferedReader fr = new BufferedReader(new FileReader(fileName));
			StringBuffer out = new StringBuffer();
			String thisLine = new String();

			while (thisLine != null) {
				thisLine = fr.readLine();

				if (thisLine != null) {
					out.append(thisLine);
				}
			}

			fr.close();

			return out.toString();
		} catch (Exception e) {
			System.out.print(e.toString());
			return null;
		}
	}

	/**
	 * write content to output file
	 * 
	 * @param fileName
	 *            output file name
	 * @param content
	 *            file content to write
	 */

	static boolean writeFile(String filePath, String content)
			throws IOException {
		File file = new File(filePath);
		if (file.exists()) {
			file.delete();
		}
		synchronized (file) {
			FileWriter fw = new FileWriter(filePath, true);
			fw.write(content);
			fw.close();

		}
		return true;
	}

	/**
	 * /** 读文件到字节数组
	 * 
	 * @param file
	 * @return
	 * @throws Exception
	 */
	static byte[] readFileToBytes(File file) throws Exception {
		if (file.exists() && file.isFile()) {
			long fileLength = file.length();
			if (fileLength > 0L) {
				BufferedInputStream fis = new BufferedInputStream(
						new FileInputStream(file));
				byte[] b = new byte[(int) fileLength];
				while (fis.read(b) != -1) {
				}
				fis.close();
				fis = null;

				return b;
			}
		} else {
			return null;
		}
		return null;
	}

	/**
	 * /** 将字节数组写入文件
	 * 
	 * @param filePath
	 * @param content
	 * @return
	 * @throws IOException
	 */
	static boolean writeBytesToFile(String filePath, byte[] content)
			throws IOException {
		File file = new File(filePath);
		synchronized (file) {
			BufferedOutputStream fos = new BufferedOutputStream(
					new FileOutputStream(filePath));
			fos.write(content);
			fos.flush();
			fos.close();
		}
		return true;

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -