花了幾天時間 解釋UMD文件,文本內容的基本搞定 保存下來,免得又忘記
以後有時間把代碼整理整理
/** * */ package cn.leaves.umd.io; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.io.StringWriter; import java.util.zip.InflaterOutputStream; import cn.leaves.umd.Content; import cn.leaves.umd.Umd; /** * @author leaves * */ public class UmdReader { private String umdfilepath; private File umdfile; private RandomAccessFile in; public final int UMD = 0xde9a9b89; public int PICTURE = 0x02; public int TEXT = 0x01; private final Umd umd = new Umd(); private long contentOffset = 0; public UmdReader() { } public UmdReader(String umdfilepath) { init(umdfilepath, "r"); } public UmdReader(String umdfilepath, String mode) { init(umdfilepath, mode); } private void init(String umdfilepath, String mode) { byte[] buffer; this.umdfilepath = umdfilepath; umdfile = new File(this.umdfilepath); try { close(); in = new RandomAccessFile(umdfile, mode); buffer = new byte[4]; in.read(buffer); int type = bytes2Int(buffer); if (type == UMD) { umd.validate = true; } umd.title = this.baseInfoToString(12); umd.author = this.baseInfoToString(4); umd.year = this.baseInfoToString(4); umd.month = this.baseInfoToString(4); umd.day = this.baseInfoToString(4); umd.gender = this.baseInfoToString(4); umd.publisher = this.baseInfoToString(4); umd.vendor = this.baseInfoToString(4); umd.contentLength = this.baseInfo4ByteToInt(5); umd.chaperOffLength = (this.baseInfo4ByteToInt(14) - 9) / 4; int[] chaperOff = new int[umd.chaperOffLength]; for (int i = 0; i < chaperOff.length; i++) { chaperOff[i] = this.baseInfo4ByteToInt(0); } umd.chaperOff = chaperOff; String[] chaper = new String[umd.chaperOffLength]; int chaperLen = this.baseInfo4ByteToInt(14) - 10; for (int i = 0; i < chaper.length; i++) { int length = this.baseInfo1ByteToInt(0); chaper[i] = this.baseInfoToString(0, length); } umd.chaper = chaper; this.contentOffset = in.getFilePointer(); int no = 0; while (true) { int contentLength = this.baseInfo4ByteToInt(5) - 9; umd.content.put(no, new Content(in.getFilePointer(), contentLength, "", false)); in.skipBytes(contentLength); byte[] b = new byte[5]; in.read(b); if (this.readUnicodeByte2Hex(b).equals("23f1000015")) { in.skipBytes(16); contentOffset = in.getFilePointer(); } else if (this.readUnicodeByte2Hex(b).equals("230a000009")) { in.skipBytes(4); contentOffset = in.getFilePointer(); } else if (this.readUnicodeByte2Hex(b).equals("2381000109")) { contentOffset = in.getFilePointer(); break; } else { in.seek(in.getFilePointer() - 5); } no++; } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public String chaperContent(int _index) { try { int index = _index; in.seek(((Content) umd.content.get(index)).offset); String str = this.ZLIBDecoding(this.baseInfo2Bytes(0, ((Content) umd.content.get(index)).length)); return str; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; } public RandomAccessFile getInputStream() { return in; } public String getUmdfilepath() { return umdfilepath; } public void setUmdfilepath(String umdfilepath) { this.umdfilepath = umdfilepath; } public boolean isUmd() { return umd.validate; } public int umdType() { try { in.seek(9); byte[] buffer = new byte[1]; in.read(buffer); switch (byte2Int(buffer[0])) { case 0x02: return PICTURE; case 0x01: return TEXT; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return 0; } return 0; } public Umd getUmd() { return umd; } public void close() throws IOException { if (in != null) { in.close(); } } private int bytes2Int(byte[] bytes) { int num = bytes[0] & 0xFF; num |= ((bytes[1] << 8) & 0xFF00); num |= ((bytes[2] << 16) & 0xFF0000); num |= ((bytes[3] << 24) & 0xFF000000); return num; } private int bytes2Int2Byte(byte[] bytes) { int num = bytes[0] & 0xFF; num |= ((bytes[1] << 8) & 0xFF00); return num; } private int byte2Int(byte b) { int num = b & 0xff; return num; } private String readUnicodeByte2Hex(byte[] temp) throws IOException { StringWriter sw = new StringWriter(); for (int index = 0; index < temp.length; index++) { if (temp[index] > 0xf && temp[index] <= 0xff) { sw.write(Integer.toHexString(temp[index])); } else if (temp[index] >= 0x0 && temp[index] <= 0xf) {// 對於只有1位的16進制數前邊補“0” sw.write("0" + Integer.toHexString(temp[index])); } else { // 對於int<0的位轉化爲16進制的特殊處理,因爲Java沒有Unsigned // int,所以這個int可能爲負數 sw.write(Integer.toHexString(temp[index]).substring(6)); } } return sw.toString(); } private String decodeHexToChinese(String hex) { StringBuffer sb = new StringBuffer(""); for (int i = 0; i < hex.length(); i = i + 4) { String temp = hex.substring(i, i + 4); // if (temp.equalsIgnoreCase("0000")) // break; String temp2 = "" + temp.charAt(2) + temp.charAt(3) + temp.charAt(0) + temp.charAt(1); char t = (char) Integer.parseInt(temp2, 16); sb.append(t); } return sb.toString(); } private String baseInfoToString(int skipBytes) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[1]; in.read(b); int length = byte2Int(b[0]) - 5; b = new byte[length]; in.read(b); return this.decodeHexToChinese(this.readUnicodeByte2Hex(b)); } private String baseInfoToString(int skipBytes, int length) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[length]; in.read(b); return this.decodeHexToChinese(this.readUnicodeByte2Hex(b)); } private byte[] baseInfo2Bytes(int skipBytes, int length) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[length]; int i = 0; while (i != length) { int bl=204800; if(length-i<bl) { bl=length-i; } byte[] t = new byte[bl]; in.read(t); System.arraycopy(t, 0, b, i, bl); i += bl; } return b; } private int baseInfo4ByteToInt(int skipBytes) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[4]; in.read(b); return this.bytes2Int(b); } private int baseInfo2ByteToInt(int skipBytes) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[2]; in.read(b); return this.bytes2Int2Byte(b); } private int baseInfo1ByteToInt(int skipBytes) throws IOException { in.skipBytes(skipBytes); byte[] b = new byte[1]; in.read(b); return this.byte2Int(b[0]); } private void showHex(int length) { try { byte[] bytes = new byte[length]; in.read(bytes); System.out.println(); String s = this.readUnicodeByte2Hex(bytes); for (int i = 0; i < s.length(); i++) { System.out.print("0x" + s.charAt(i) + s.charAt(++i)); System.out.print(" "); } System.out.println(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public byte[] decompressData(byte[] bytes) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); InflaterOutputStream zos = new InflaterOutputStream(bos); zos.write(bytes); zos.close(); byte[] b = bos.toByteArray(); bos.close(); return b; } catch (Exception ex) { ex.printStackTrace(); return null; } } public String ZLIBDecoding(byte[] b) throws IOException { byte[] temp = this.decompressData(b); if (temp != null) { return this.decodeHexToChinese(this.readUnicodeByte2Hex(temp)) .replace("/u2029", "/r/n"); } return ""; } }
/** * */ package cn.leaves.umd; import java.util.Hashtable; /** * @author leaves * */ public class Umd { public static final int UMD = 0xde9a9b89; public static int PICTURE = 0x02; public static int TEXT = 0x01; public boolean validate = false; public String title; public String author; public String year; public String month; public String day; public String gender;// 類別 public String publisher; public String vendor; public int contentLength; public int chaperOffLength; public int[] chaperOff; public int chaperLength; public String[] chaper; public int lziplength; public Hashtable<Integer,Content> content=new Hashtable(0); }
package cn.leaves.umd; public class Content{ public Content(long offset,int length,String content,boolean buffered) { this.offset=offset; this.length=length; this.content=content; this.buffered=buffered; } public long offset; public int length; public String content; public boolean buffered=false; }
前言 今天大姚給大家分享一款基於C#、WPF、Prism、MaterialDesign、HandyControl開發的通訊調試工具(支持Modbus RTU、MQTT調試,界面色彩豐富):Wu.CommTool。 工具特點 工具界面色彩豐
Linux/Golang/glibC系統調用 本文主要通過分析Linux環境下Golang的系統調用,以此闡明整個流程 有時候涉略過多,反而遭到質疑~,寫點文章證明自己實力也好 Golang系統調用 找個函數來分析 https://pk
也就是算出絕對路徑傳進去. import os wenjian='/'.join(os.path.abspath(__file__).split('/')[:-2])+'/' with open(wenjian+"meddata.jso
本週刊由 Python貓 出品,精心篩選國內外的 250+ 信息源,爲你挑選最值得分享的文章、教程、開源項目、軟件工具、播客和視頻、熱門話題等內容。願景:幫助所有讀者精進 Python 技術,並增長職業和副業的收入。 本期週刊分享了 12
當程序需要引用尚未定義的變量或標號時,編譯器會如何處理呢,這就涉及到向前引用(Forward Reference)的概念。 一、Forward Reference的概念 程序引用到之前尚未定義的變量(Variable)、標號(L
Offset僞指令我一直都認爲只是獲取標識符在段中的偏移地址,但經研究,發現了部分違反直覺的細微區別: 1、在完整端聲明(Full segment definition)的模式下 如果offset mygroup:myvar或o
之前有實現Q-Learning走迷宮,本篇實現SARSA走迷宮。 Q-Learning是一種off-policy算法,當前步採取的決策action不直接作用於環境生成下一次state,而是選擇最優的獎勵來更新Q表。 更新公式: SARSA
A script is a small piece of program that can add interactivity to our websites. For example, a script could generate a
The HTML Layouts specifies the arrangement of components on an HTML web page. A good layout structure of the webpage i
What is a HTML Favicon? A favicon is a small image that represents your website and helps users identify it among mult
The Layout Elements of HTML In HTML, there are various semantic elements that are used to define different parts of a
Now we all have learned various techniques to design an HTML layout including tables and semantic elements. We are ver
cs01 CSS Syntax cs02 CSS Selectors cs03 CSS Inclusion cs04 CSS Measurement Units cs05 CSS Paddings Property REF http
Values and units, in CSS, are significant as they determine the size, proportions, and positioning of elements on a web
A CSS comprises of style rules that are interpreted by the browser and then applied to the corresponding elements in you