FBreader问题记录及多端同步心得开篇

android端做过epub阅读器的小伙伴应该对这个都不陌生了,可谓是又爱又恨.既爱其强大,又恨自己看不懂(可能只是我一人).
我先讲下背景,公司是做数字阅读的,而我们选择了FBReader作为epub的文件解析器,在我接手之前已经用了好几年了(公司之前的大佬集成进去的),而我(不会c++的android菜鸡)来的2年期间也没有深入了解过.随之而来的就是慢慢的折磨,遇到了以下几个问题.
一是新制作的epub结构不兼容FBReader结构导致无法阅读,那时排查了3天才发现是解析路径出了问题,最后勉强修复了这个问题.在github上有提过fbreader的请求分支,大家可以看看这种low操作.

ZLFile.cpp 的 ZLFile::ZLFile()方法中
//兼容content.opf在根目录的epub制作规则
	myPath = ZLStringUtil::replace(myPath, ":./", ":");

二是无法读取epub文件中的css样式导致排版太丑,同样是路径的问题.

XTHMLReader.cpp	的 void XHTMLTagLinkAction::doAtStart()方法中
	cssFilePath = ZLStringUtil::replace(cssFilePath, ":", "/");

三是极少数设备so库100%崩溃的问题,都是先try(){}catch()看是否影响正常阅读,如果不影响则就用这种low办法处理.
一年前公司计划(其实这应该是常规功能)要多端同步!当时我把这个功能分给另一个同事了,后来也不知道进展,今年疫情由于某种原因离职了(当然不是公司的原因咯),看来这始终还得折磨我弱小的心理.
于是我开始恶补FBReader的相关文档,此处得感谢大佬的文章让我初步了解了解析流程.因为多端都是各自的方案实现的,所以我们在epub上的每个段落p标签标记属性id来同步.FbReader其实已经对已实现的标签中(XHTMLReader:fillTagTable())的id属性是有解析的,在XHTMLReader::startElementHandler()中可以找到根据,但存储的是myReferenceAlias + # + id,与我们实际要的id多myReferenceAlias + #,所以在取id对应的段位置时需要注意,具体取id对应的段位置在BookModel.getLabelInternal()中,根据需求,需要调整一下实现

public Label getLabelInternal(String id) {
		final int len = id.length();
		final int size = myInternalHyperlinks.size();

		for (int i = 0; i < size; ++i) {
			final char[] block = myInternalHyperlinks.block(i);
			for (int offset = 0; offset < block.length; ) {
				final int labelLength = (int)block[offset++];
				if (labelLength == 0) {
					break;
				}
				final int idLength = (int)block[offset + labelLength];
				String idCache = new String(block, offset, labelLength);
				//TODO 获取属性id BK3468093014-37对应的段位置,但myInternalHyperlinks已此方式拼接9#BK3468093014-37,
				// 所以判断lengh的条件去掉, equals()修改为contains()
				// 详细拼接见XHTMLReader.cpp中addHyperlinkLabel(),同理也可增加其他属性
				//if (labelLength != len || !id.equals(idCache)) {
				if (!idCache.contains(id)) {
					offset += labelLength + idLength + 3;
					continue;
				}
				offset += labelLength + 1;
				final String modelId = (idLength > 0) ? new String(block, offset, idLength) : null;
				offset += idLength;
				final int paragraphNumber = (int)block[offset] + (((int)block[offset + 1]) << 16);
				return new Label(modelId, paragraphNumber);
			}
		}
		return null;
	}

以上就是根据已知的属性id取到对应的位置,然后跟目录一样的操作跳转就可以跳到指定的id位置了.
后面还需要解决的是如何根据当前阅读页的段落取到其属性id,作为同步的依据.如果细化的话,对每段中每句都加上属性id该怎么处理?
还在研究中,若有大佬,烦请赐教!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值