代码地址见本文最后。

因为特殊原因,更换了通讯工具,需要将原聊天消息进行备份,并能进行浏览或者查询。

发现QQ消息可以导出mht格式的消息,这种文件格式内部其实就是讲html、css、图片(图片是经过base64转换)按照一定规律全部写入到mht文件中的,只要按照规律解析即可。

在解析的过程中,如果是文件体积比较大,就需要考虑进行分页,否则生成的html文件很大,我遇到解析后最大的单html文件达到了500M(导出全部消息),浏览起来很不方便,因此增加了分页功能。

首先上效果:

1.将程序放到mht文件所在文件夹。

程序会自动查询当前文件夹的mht文件,并进行转换,最后将文件保存到mht同名的文件夹中。

2.双击运行run.bat文件,可选分页。

注意:在mht文件小于100M的情况下,即使选择了分页,程序不会也不会进行分页。

3.预览效果

部分代码解析:

1.生成单文件html

/*** 创建单文件html* @param inputFile* @param outputFilePath*/public static void readAndCreateFile(String inputFile, String outputFilePath) {String htmlFileName = parseHtmlFileName(inputFile);File file = new File(inputFile);BufferedInputStream fis = null;BufferedReader reader = null;try {fis = new BufferedInputStream(new FileInputStream(file));reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),5*1024*1024);boolean isCreatedHtml = false, isHtmlContent = false;String line = "";StringBuilder sb = null;//String [] resType = null;String resName = null;//boolean isGetResType = false;boolean isGetResName = false;StringBuilder resSb = new StringBuilder();while((line = reader.readLine()) != null){if(!isCreatedHtml) {if (isHtmlStartTag(line)) {isHtmlContent = true;sb = new StringBuilder(line).append("\n");}else{if(isHtmlContent) {if (isHtmlEndTag(line)) {sb.append(line).append("\n");createHtmlFile(outputFilePath, htmlFileName, sb.toString(), 0, true);sb.delete(0, sb.length());isCreatedHtml = true;} else {sb.append(line).append("\n");}}}}/*** 开始解析资源文件*/if(isCreatedHtml) {/*if(!isGetResType) {resType = parseResourceType(line);if (resType != null) {isGetResType = true;continue;}}*/if(!isGetResName) {resName = parseResourceName(line);if (resName != null) {isGetResName = true;resSb.delete(0, resSb.length());continue;}}if(isGetResName) {if(line.length() > 0) {if(line.contains("------=_NextPart_")) {//isGetResType = false;isGetResName = false;generateImage(resSb.toString(), (outputFilePath + File.separator + htmlFileName), resName);}else{resSb.append(line).append("\n");}}}}}} catch (FileNotFoundException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if(reader != null) {reader.close();}if(fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}

2.生成分页html

/*** 创建分页html* @param inputFile* @param outputFilePath*/public static void readAndCreateMultFile(String inputFile, String outputFilePath) {String htmlFileName = parseHtmlFileName(inputFile);File file = new File(inputFile);BufferedInputStream fis = null;BufferedReader reader = null;try {fis = new BufferedInputStream(new FileInputStream(file));reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),5*1024*1024);boolean isCreatedHtml = false, isTableContent = false;String line = "";StringBuilder sb = null;int trLine = 1;int htmlNo = 1;//String [] resType = null;String resName = null;//boolean isGetResType = false;boolean isGetResName = false;StringBuilder resSb = new StringBuilder();while((line = reader.readLine()) != null){if(!isCreatedHtml) {Matcher startMatcher = tableStartPattern.matcher(line);if (startMatcher.find()) {isTableContent = true;/*** 将table后面的内容拼接起来*/sb = new StringBuilder(line.substring(startMatcher.end())).append("\n");}else{if(isTableContent) {trLine++;Matcher endMacher = tableEndPattern.matcher(line);if (endMacher.find()) {sb.append(line.substring(0, endMacher.start()));createHtmlFile(outputFilePath, htmlFileName, sb.toString(), htmlNo, true);isCreatedHtml = true;} else {sb.append(line).append("\n");if(trLine % 1000 == 0) {createHtmlFile(outputFilePath, htmlFileName, sb.toString(), htmlNo, false);htmlNo ++;sb.delete(0, sb.length());}}}}}/*** 开始解析资源文件*/if(isCreatedHtml) {/*if(!isGetResType) {resType = parseResourceType(line);if (resType != null) {isGetResType = true;continue;}}*/if(!isGetResName) {resName = parseResourceName(line);if (resName != null) {isGetResName = true;resSb.delete(0, resSb.length());continue;}}if(isGetResName) {if(line.length() > 0) {if(line.contains("------=_NextPart_")) {//isGetResType = false;isGetResName = false;generateImage(resSb.toString(), (outputFilePath + File.separator + htmlFileName), resName);}else{resSb.append(line).append("\n");}}}}}} catch (FileNotFoundException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if(reader != null) {reader.close();}if(fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}

注意:

1.考虑到性能问题,分页生成的时候,只做了上一页、下一页,因为个人已经觉得这个够用了,并没有开发页码的功能,读者可对这个进行扩展,思路大概是:将mht中的html部分读取到,主要是table中的tr部分,然后将这些逐条读取到并放入list,然后根据list进行分页。

2.读者在转换之后,还是请保留您的原始mht文件,虽然功能经过测试,也对数据进行了一定量的验证,但是不保证在转换的过程中可能因bug或未知因素导致数据丢失,因此,请保留原始mht文件,请保留原始mht文件,请保留原始mht文件!

3.花了一点时间开发的,并未对代码进行优化,可能有些地方有部分重复代码,读者请自行优化。

4.测试过6G和10G左右的文件,更大的文件暂时未测试。

后续:

后续如果有空闲时间,可能会做一定的改进,使用Lucene相关技术,对生成的html进行索引并支持搜索,方便搜索消息。

代码地址:

https://github.com/itriders/mht2html

用Java将QQ、企业QQ导出的消息(mht格式)(支持大文件)解析为html格式,包含解析图片内容相关推荐

  1. Java中利用企业QQ邮箱发送邮件

    package test; import java.util.Date; import java.util.Properties; import javax.mail.internet.Interne ...

  2. java nio 按行读取_JAVA之NIO按行读写大文件,完美解决中文乱码问题

    packagecom.chillax.imp; importjava.io.File; importjava.io.IOException; importjava.io.RandomAccessFil ...

  3. java录制pcm文件_AudioRecord录制PCM格式的语音示例

    AudioRecord可以将手机或麦克风的声音录制成pcm格式的语音文件,本案例将再service中实现pcm声音的录制,并提供将pcm格式语音转化为mp3格式的方法,先来看看AudioRecord如 ...

  4. java EE 5配置邮件发送 qq企业邮箱

    为什么80%的码农都做不了架构师?>>>    java EE 5配置QQ企业邮件发送 1.在项目的WebRoot/META-INF/新建context.xml 具体内容如下: &l ...

  5. 【开源】java做游戏之QQ连连看java单机高仿版(算是目前最高仿的了)

    QQ连连看JAVA高仿单机版V1.0 前言 为什么说是目前最高仿的呢,因为想做这个的一般是新手,要实现的跟我一样有点难度,至少我在网上没搜到(java版本).还有就是高手对这个没兴趣,不会做这个玩意儿 ...

  6. QQ好友列表导出用JTree树实现

    最近学习了一下JTree的使用方法:QQ好友列表导出用JTree树实现 先来看一下树的实例: 构建一个树, DefaultMutableTreeNode root = new DefaultMutab ...

  7. Java TCP实现高仿版QQ聊天(二)

    前言 ​ 这是在上一篇博客基础上开展的,第一部分我们只实现了本机的聊天,无法将程序放置另外机器上和本机进行聊天.这篇博客我将介绍如何实现不同机器之间实现聊天,达到真正意义上的聊天.不过这篇博客在其他机 ...

  8. java 判断qq_Java检测QQ是否在线状态

    腾讯QQ在线状态 WEB 服务Endpoint:http://www.webxml.com.cn/webservices/qqOnlineWebService.asmxDisco:http://www ...

  9. jenkins之qq企业邮箱配置

    一.配置qq企业邮箱 1.登录jenkins后台管理,选择 系统管理 ☞  系统设置 2.SMTP server配置 3.邮件通知配置 配置ssl等参数  点击 高级 4.发送邮件测试 总结:邮箱配置 ...

最新文章

  1. 分享Kali Linux 2016.2第46周虚拟机
  2. SQL Server 2012 Managed Service Account
  3. 蓝桥杯-题目:猜算式
  4. 浅析分布式数据库中间件DDM
  5. 中考数学不准使用计算机,中考数学蒙题技巧
  6. Linq(筛选与排序)
  7. sublime 3 3083验证码
  8. torch.utils.data.DataLoader 详解
  9. Java的clone方法
  10. 客户端考试之渐进增强与优雅降级
  11. jdbc mysql innodb 死锁 deadlock_Mysql InnoDB 数据更新/删除导致锁表
  12. python3x菜鸟教程_菜鸟教程python3
  13. html组件做成圆角,css3制作圆角按钮
  14. idea activation code记录
  15. AXI 基础第 4 讲 - 使用 AXI VIP 作为 AXI4 主接口的协议检查工具
  16. PIC16F877A第一个程序
  17. Android 更换壁纸 代码
  18. 开局一张图帮你充分理解哈希表(散列表)
  19. python中Excel表的读写改详解
  20. 特征工程之One-Hot编码、label-encoding、自定义编码

热门文章

  1. 电磁铁、电磁阀以及螺线管的区别
  2. 介绍一个产品的思维导图_什么叫产品思维导图(产品思维的定义)
  3. CP2102N高度集成USB全速带电池充电检测控制芯片
  4. 自主开发项目说明(新锐售楼管理系统)
  5. 马云,受聘顶尖大学荣誉教授!聘期3年!
  6. 旧手机搭建网站------KSWEB
  7. 基于stm32F4的项目总结:控制层设计(二)步进电机驱动原理及选型
  8. 29岁转行软件测试靠谱吗?一个过来人的心路历程送给迷茫的你
  9. [Canvas画图] 藏图阁(16) 人体穴位
  10. 【数据结构】List相关知识的学习【详解篇2】