花了幾天時間 解釋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; }
前言 2015年,國務院提出了中國製造2025製造強國“三步走”規劃,旨在推動中國製造業成爲全球製造強國: 第一個十年規劃,2015-2025:中國製造業邁入製造強國行列,實現技術創新和產業升級。 第二個十年規劃,2025-2035:中國
概述 surging是一款開源的微服務引擎,包含了rpc服務治理,中間件,以及多種外部協議來解決各個行業的業務問題,在日益發展的今天,業務的需求也更加複雜,單一語言也未必能抗下所有,所以在多語言行業解決方案優勢情況下,那麼就需
from ftplib import FTP # 連接到FTP服務器 ftp = FTP('10.129.250.27') ftp.login(user='用戶名', passwd='密碼') # 列出FTP服務器上的文件和目錄 ft
本章介紹金融領域大模型智能體,並梳理金融LLM的相關資源。金融領域的大模型智能體當前集中在個股交易決策這個相對簡單的場景,不需要考慮多資產組合的複雜場景。交易決策被簡化成市場上各個信息,包括技術面,消息面,基本面等等在不同市場情況下,對資產
前言 現如今人工智能(AI)技術的發展可謂是如火如荼,它們在各個領域都展現出了巨大的潛力和影響力。今天大姚給大家分享4個.NET開源的AI和LLM相關的項目框架,希望能爲大家提供一些參考。如果你有更好的推薦,歡迎RP投稿或文末留言。 ht
作者:avengerEug 鏈接:https://juejin.cn/post/6984574787511123999 前言 經過前面對Spring AOP、事務的總結,我們已經對它們有了一個比較感性的認知了。 今天,我繼續安利一個獨門絕
做產品肯定要做電子郵件營銷,特別是面向海外的產品,電子郵件營銷已成爲企業與客戶溝通、建立品牌忠誠度和推動銷售的重要工具,可以直接接觸到目標受衆,提供個性化內容,並以相對較低的成本獲得可觀的投資回報。你看,MEAP 又來提醒我買電子書了!
前言 jquery時代更新視圖是直接對DOM進行操作,缺點是頻繁操作真實 DOM,性能差。react和vue時代引入了虛擬DOM,更新視圖是對新舊虛擬DOM樹進行一層層的遍歷比較,然後找出需要更新的DOM節點進行更新。這樣做的缺點就是如果D
之前碰到一個問題,需要處理一個超大型目錄,目錄有多大呢,有200G大小,大部分人的思路如下, 用日常的遞歸,基本上讀取到的路徑數組非常大,會導致超出內存,特此研究了一番: 一般常見的方法如下: function recursiveScan(
一、基礎 不依賴第三方軟件,對系統合理的設置來提高效率 休眠 注意不是睡眠,休眠後電源是斷開的,多用休眠方式去關機,這樣開機後還能保持所有的會話狀態,不用再去重新打開軟件 默認關機按鈕裏是沒有休眠選項的,需要到控制面板-電源裏去開啓
如何用費曼技巧快速學習任何東西 爲什麼教學是理解的關鍵 理查德·費曼是一位諾貝爾物理學獎得主,在量子力學、粒子物理等領域做出了重大貢獻。他還開創了量子計算,引入了納米技術的概念。他是康奈爾大學和加州理工學院的著名講師。 儘管取得了這些成就,
9大關於生產力的錯誤認知 以及你應該做的9個有用的替代方法 生產力 大量文章不斷提供新的方法來提高生產力,或者以新的方式重新包裝相同的建議。然而,無論我們讀了多少文章,我們大多數人仍然對自己的壞習慣感到無助。部分挑戰在於,養成提高生產力的習
如何高效使用 Todoist — 完整指南 無論你是在完成一個大型的團隊項目、策劃一個比預期工作量更大的活動,還是跟蹤你的賬單到期時間,你都有目標要實現。 但問題是,僅有目標還不夠。你需要一個系統來真正完成任務。 這就是 Todoist 的
在Spring中,CompletableFuture通常用於異步編程,可以方便地處理異步任務的執行和結果處理,CompletableFuture 是 Java 8 引入的一個類,用於支持異步編程和併發操作。它基於 Future 和 Comp
X-Frame-Options 是一個HTTP響應頭,用於控制網頁是否可以嵌套在 <frame>, <iframe>, <embed> 或者 <applet> 中。通過設置 X-Frame-Options 頭部,網站管理員可以防止網頁被嵌套