📄 packbook.java
字号:
import java.io.BufferedOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.util.*;/** * * @author jerry */public class PackBook { final static int STATIC_ONE = 1; final static int STATIC_TWO = 2; final static int STATIC_FOUR = 4; final static int STATIC_TWENTY=12; final static int STATIC_TWENTH=20; final static int STATIC_FOURTH = 40; ///有固定的2章:cover 封面和 catalog 目录 final static String SOURCE_DIR = "./datasource/"; final static String BACK_NAME="bak"; public static void main(String[] args){ try { List<String> allBuild=Tools.readFileByLines("./build.txt"); int totalChapter=10; new PackBook().buildData(allBuild,totalChapter); } catch (Exception e) { e.printStackTrace(); } } /** * 1. 文件头大小[curPos=60=资源大小(4)+书id(12)+是否小说(1)+是否连载(1)+总章节(2)+中文名称(40)] * 2. 构建书的基本属性(书id号,正文名称,是否小说,是否连载) * 3. 获取打包后的文件名 * 4. 获取打包文件数(allChapters)及打包的章节名(chapters) * 5. 构建两个对象: 文件对象 FileInfo 和图片对象 PictureInfo * 分别存放文件信息和图片信息 * 6. 计算封面文件的索引位置 (封面文件为:cover.html) * curPos+=60+封面数据索引(4)+目录数据索引(4)+打包的文件数 allChapters*4 + 4;(该4为第n+1章文件的索引占用章节,第n+1章为虚拟的) * 7. 加载封面文件数据,统计其长度,建立索引位置 * 8. 解析其包含的图片名称,并将其存放 List 对象 picList 中 * 9. 计算目录文件的索引位置 (目录文件为:index.html) * curPos+=封面文件长度 //封面长度占用字节(4)+封面文件长度 * 10. 加载目录文件数据,统计其长度,建立目录索引位置 * 11. 解析其包含的图片名称,并将其存放 List 对象 picList 中 * 12. 加载并计算打包的章节文件 * curPos+=目录长度占用字节(4)+目录文件长度 * 根据打包的文件数 allChapters 和打包的章节名,分别加载文件数据,统计其长度,建立目录索引位置 * 解析其包含的图片名称,并将其存放 List 对象 picList 中 * curPos+=章节文件长度 // 章节文件长度占用字节(4)+章节文件长度 * 13. 计算第一章图片索引 * curPos+=图片个数(2)+图片个数*图片名称(20)+图片个数*图片数据索引占用字节数(4) * 14. 根据 picList信息, 循环取打包的图片信息 * 构建图片索引: curPos+=图片数据长度 // 图片长度占用字节数(4)+图片数据长度 * 15. 构建 ByteBuffer 对象 bb,其大小为curPos. * 16. 向 ByteBuffer 对象 bb 中添加数据, 必须按以下的顺序添加 * 1. 资源大小 * 2. 书id号 * 3. 是否小说 * 4. 是否连载 * 5. 总章节 * 6. 中文书名 * 7. 封面索引 * 8. 目录索引 * 9. 循环添加打包章节文件的索引 * 10. 封面文件长度 * 11. 封面文件数据 * 12. 目录文件长度 * 13. 目录文件数据 * 14. 循环添加打包章节文件长度,文件数据 * 15. 图片张数 * 16. 循环添加打包图片名称 * 17. 循环添加图片索引 * 18. 循环添加图片大小,图片数据 * 17. 建立输入输出流, 输出打包的文件 * * @param allBuild 存放build.txt里所有书目属性数据 * @throws Exception */ private void buildData(List<String> allBuild,int totalChapter) throws Exception { int curPos = 0; ///当前位置 int allChapters = 0; ///总章节 List<FileInfo> cpList=new ArrayList<FileInfo>(); // 存放打包的文件信息 List<String> img = null; // 存放打包的图片信息 boolean bStory=true; // 小说的标记 String backName=""; // 打包后的文件名 //资源大小(4)+书目id(12)+是否小说(1)+是否连载(1)+书目总章节(4)+打包章节数(4)+书名(40) // +该包的中文名称(40)+打包起始章节(4)+打包结尾章节(4)+封面索引(4)+目录索引(4) curPos = STATIC_FOUR+STATIC_TWENTY+STATIC_ONE+STATIC_ONE+STATIC_FOUR+STATIC_FOUR+STATIC_FOURTH+ STATIC_FOURTH+STATIC_FOUR+STATIC_FOUR+STATIC_FOUR+STATIC_FOUR;//4+12+1+1+4+4+40+40+4+4+4+4;//60+40; // 文件头大小 String[] splitCh; int[] chapters=new int[0]; String str_chapters = (String)allBuild.get(0); // 第一行为打包的章节 //Tools.readFile(sourcePath+chapterTxt); splitCh=str_chapters.split(","); int chlen=splitCh.length; // 判断是否为两个以','分割的数字 if(chlen>2){ System.out.println("打包的章节参数不正确!"); System.exit(0); }else{ if(chlen==1){ chapters=new int[chlen]; chapters[0]=Integer.parseInt(splitCh[0]); }else{ int begch=Integer.parseInt(splitCh[0]); int endch=Integer.parseInt(splitCh[1]); chlen=endch-begch+1; // 判断结束章节是否大于起始章节 if(chlen>0){ chapters=new int[chlen]; for(int i=begch,j=0;i<=endch;i++,j++){ chapters[j]=i; } }else{ System.out.println("打包的章节参数不正确!"); System.exit(0); } } } // 构建书目基本属性 Book book = new Book().buildBooks(allBuild); String bookid=book.getId().substring(0, 8); String issueid=book.getId().substring(8); // 获取打包后的文件名 backName=bookid+"_"; if(chapters!=null&&chapters.length>1){ backName+=chapters[0]+"-"+chapters[chapters.length-1]; }else backName+=chapters[0]; backName=BACK_NAME; allChapters = chapters.length; System.out.println("55 lines curPos ==>"+curPos+", 封面文件:"+SOURCE_DIR + bookid +("M".equals(book.getType())?"_"+issueid:"")+ ".html"); List<PictureInfo> picList = new ArrayList<PictureInfo>(); List<PictureInfo> pic =new ArrayList<PictureInfo>(); String chapterContent=""; String path; FileInfo fi=new FileInfo(); // 封装文件数据 // 加载封面数据 chapterContent=Tools.readFile(SOURCE_DIR + "cover.html"); //Tools.readFile(SOURCE_DIR + bookid +("M".equals(book.getType())?"_"+issueid:"")+ ".html");///书的ID为12位,但后面4位杂志ID // 解析字符串,取图片信息 // 提取<img>标签 img = extraImg(chapterContent,new ArrayList<String>()); // 提取图片数据信息 picList=buildPictureInfo(img,SOURCE_DIR); fi.chapterNo=-1; // 封面的章节号临时定为-1 fi.data=chapterContent.getBytes(); fi.len=fi.data.length; //fi.indexPos=curPos; // 添加封面的索引 // curPos+=fi.len; // +4; cpList.add(fi); // 将文件数据信息添加到 List 集合 System.out.println("71 lines 封面索引 ==>"+fi.indexPos+", 数据长度 ==>"+fi.len+", curPos ==>"+curPos); /// 加载目录数据 path= SOURCE_DIR+bookid; if("M".equals(book.getType())){ path+="_"+book.getId().substring(8); bStory=false; } path+="_0"; System.out.println("78 lines curPos ==>"+curPos+", 目录文件:"+path + ".html, 新目录文件::"+SOURCE_DIR+"index.html"); chapterContent=Tools.readFile(SOURCE_DIR+"index.html"); //path+".html"); // 解析字符串,取图片信息 // 提取<img>标签 img = extraImg(chapterContent,new ArrayList<String>()); // 提取图片数据信息 pic = buildPictureInfo(img,SOURCE_DIR); if(pic!=null&&pic.size()>0) for(PictureInfo pi:pic) picList.add(pi); fi=new FileInfo(); fi.chapterNo=0; // 目录的章节号临时定为0 fi.data=chapterContent.getBytes(); fi.len=fi.data.length; cpList.add(fi); // 将文件数据信息添加到 List 集合 System.out.println("91 lines 目录索引 ==>"+fi.indexPos+", 数据长度 ==>"+fi.len+", curPos ==>"+curPos); /// 循环取打包的正文信息 for(int i=0;i<allChapters;i++){ String chap=chapters[i]+""; path= SOURCE_DIR+bookid; if(bStory){ path+="_"+chap; }else{ path+="_"+book.getId().substring(8)+"_"+chap; } path+=".html"; System.out.println("101 lines curPos ==>"+curPos+", 文件:"+SOURCE_DIR+chap+".html"); chapterContent=Tools.readFile(SOURCE_DIR+chap+".html");//path); // 解析字符串,取图片信息 // 提取<img>标签 img = extraImg(chapterContent,new ArrayList<String>()); // 提取图片数据信息 pic = buildPictureInfo(img,SOURCE_DIR); if(pic!=null&&pic.size()>0) for(PictureInfo pi:pic) picList.add(pi); fi=new FileInfo(); fi.chapterNo=Integer.parseInt(chap); fi.data=chapterContent.getBytes(); fi.len=fi.data.length;// fi.indexPos=curPos; // 添加章节chap正文的索引// curPos+=fi.len; //+4; // 正文的长度+存放正文长度所用的字节数(4) cpList.add(fi); // 将文件数据信息添加到 List 集合 } // 计算封面文件的索引: curPos += STATIC_FOUR * allChapters +STATIC_FOUR; // n+1章 // 添加图片数据长度 curPos +=2; if(picList!=null&&picList.size()>0){ curPos+=picList.size()*(STATIC_TWENTH+STATIC_FOUR)+STATIC_FOUR; // 图片名称(20)+图片索引(4)+最后一张图片长度 } // 构建索引: 封面索引,目录索引,正文索引,图片索引 if(cpList!=null&&cpList.size()>0) for(FileInfo ff:cpList) { System.out.println("章节号 ::"+ff.chapterNo); ff.indexPos=curPos; // 添加章节chap正文的索引 curPos+=ff.len; System.out.println("192 lines 正文"+ff.chapterNo+"索引 ==>"+ff.indexPos+", 数据长度 ==>"+ff.len+", curPos ==>"+curPos); } // 第n+1个正文的索引,(n+1章正文为虚拟的) Integer chapterN=curPos; if(picList!=null&&picList.size()>0) for(PictureInfo pi:picList){ pi.indexPos=curPos; // 添加图片的索引 curPos+=pi.size; System.out.println("123 lines 图片"+new String(pi.picName)+" 索引 ==>"+pi.indexPos+", 图片长度占用4字节, 图片数据大小 ==>"+pi.size+", curPos ==>"+curPos); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -