package me.ag2s.umdlib.umd; import androidx.annotation.NonNull; import java.io.IOException; import java.io.InputStream; import me.ag2s.umdlib.domain.UmdBook; import me.ag2s.umdlib.domain.UmdCover; import me.ag2s.umdlib.domain.UmdHeader; import me.ag2s.umdlib.tool.StreamReader; import me.ag2s.umdlib.tool.UmdUtils; /** * UMD格式的电子书解析 * 格式规范参考: * http://blog.sina.com.cn/s/blog_7c8dc2d501018o5d.html * http://blog.sina.com.cn/s/blog_7c8dc2d501018o5l.html * */ public class UmdReader { UmdBook book; InputStream inputStream; int _AdditionalCheckNumber; int _TotalContentLen; boolean end = false; public synchronized UmdBook read(InputStream inputStream) throws Exception { book = new UmdBook(); this.inputStream=inputStream; StreamReader reader = new StreamReader(inputStream); UmdHeader umdHeader = new UmdHeader(); book.setHeader(umdHeader); if (reader.readIntLe() != 0xde9a9b89) { throw new IOException("Wrong header"); } short num1 = -1; byte ch = reader.readByte(); while (ch == 35) { //int num2=reader.readByte(); short segType = reader.readShortLe(); byte segFlag = reader.readByte(); short len = (short) (reader.readUint8() - 5); System.out.println("块标识:" + segType); //short length1 = reader.readByte(); readSection(segType, segFlag, len, reader, umdHeader); if ((int) segType == 241 || (int) segType == 10) { segType = num1; } for (ch = reader.readByte(); ch == 36; ch = reader.readByte()) { //int num3 = reader.readByte(); System.out.println(ch); int additionalCheckNumber = reader.readIntLe(); int length2 = (reader.readIntLe() - 9); readAdditionalSection(segType, additionalCheckNumber, length2, reader); } num1 = segType; } System.out.println(book.getHeader().toString()); return book; } private void readAdditionalSection(short segType, int additionalCheckNumber, int length, StreamReader reader) throws Exception { switch (segType) { case 14: //this._TotalImageList.Add((object) Image.FromStream((Stream) new MemoryStream(reader.ReadBytes((int) length)))); break; case 15: //this._TotalImageList.Add((object) Image.FromStream((Stream) new MemoryStream(reader.ReadBytes((int) length)))); break; case 129: reader.readBytes(length); break; case 130: //byte[] covers = reader.readBytes(length); book.setCover(new UmdCover(reader.readBytes(length))); //this._Book.Cover = BitmapImage.FromStream((Stream) new MemoryStream(reader.ReadBytes((int) length))); break; case 131: System.out.println(length / 4); book.setNum(length / 4); for (int i = 0; i < length / 4; ++i) { book.getChapters().addContentLength(reader.readIntLe()); } break; case 132: //System.out.println(length/4); System.out.println(_AdditionalCheckNumber); System.out.println(additionalCheckNumber); if (this._AdditionalCheckNumber != additionalCheckNumber) { System.out.println(length); book.getChapters().contents.write(UmdUtils.decompress(reader.readBytes(length))); book.getChapters().contents.flush(); break; } else { for (int i = 0; i < book.getNum(); i++) { short len = reader.readUint8(); byte[] title = reader.readBytes(len); //System.out.println(UmdUtils.unicodeBytesToString(title)); book.getChapters().addTitle(title); } } break; default: /*Console.WriteLine("未知内容"); Console.WriteLine("Seg Type = " + (object) segType); Console.WriteLine("Seg Len = " + (object) length); Console.WriteLine("content = " + (object) reader.ReadBytes((int) length));*/ break; } } public void readSection(short segType, byte segFlag, short length, StreamReader reader, UmdHeader header) throws IOException { switch (segType) { case 1://umd文件头 DCTS_CMD_ID_VERSION header.setUmdType(reader.readByte()); reader.readBytes(2);//Random 2 System.out.println("UMD文件类型:" + header.getUmdType()); break; case 2://文件标题 DCTS_CMD_ID_TITLE header.setTitle(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("文件标题:" + header.getTitle()); break; case 3://作者 header.setAuthor(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("作者:" + header.getAuthor()); break; case 4://年 header.setYear(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("年:" + header.getYear()); break; case 5://月 header.setMonth(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("月:" + header.getMonth()); break; case 6://日 header.setDay(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("日:" + header.getDay()); break; case 7://小说类型 header.setBookType(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("小说类型:" + header.getBookType()); break; case 8://出版商 header.setBookMan(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("出版商:" + header.getBookMan()); break; case 9:// 零售商 header.setShopKeeper(UmdUtils.unicodeBytesToString(reader.readBytes(length))); System.out.println("零售商:" + header.getShopKeeper()); break; case 10://CONTENT ID System.out.println("CONTENT ID:" + reader.readHex(length)); break; case 11: //内容长度 DCTS_CMD_ID_FILE_LENGTH _TotalContentLen = reader.readIntLe(); book.getChapters().setTotalContentLen(_TotalContentLen); System.out.println("内容长度:" + _TotalContentLen); break; case 12://UMD文件结束 end = true; int num2 = reader.readIntLe(); System.out.println("整个文件长度" + num2); break; case 13: break; case 14: int num3 = (int) reader.readByte(); break; case 15: reader.readBytes(length); break; case 129://正文 case 131://章节偏移 _AdditionalCheckNumber = reader.readIntLe(); System.out.println("章节偏移:" + _AdditionalCheckNumber); break; case 132://章节标题,正文 _AdditionalCheckNumber = reader.readIntLe(); System.out.println("章节标题,正文:" + _AdditionalCheckNumber); break; case 130://封面(jpg) int num4 = (int) reader.readByte(); _AdditionalCheckNumber = reader.readIntLe(); break; case 135://页面偏移(Page Offset) reader.readUint8();//fontSize 一字节 字体大小 reader.readUint8();//screenWidth 屏幕宽度 reader.readBytes(4);//BlockRandom 指向一个页面偏移数据块 break; case 240://CDS KEY break; case 241://许可证(LICENCE KEY) //System.out.println("整个文件长度" + length); System.out.println("许可证(LICENCE KEY):" + reader.readHex(16)); break; default: if (length > 0) { byte[] numArray = reader.readBytes(length); } } } @Override @NonNull public String toString() { return "UmdReader{" + "book=" + book + '}'; } }