FBReader支持txt插件

package org.geometerplus.fbreader.formats.txt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.geometerplus.fbreader.bookmodel.BookModel;
import org.geometerplus.fbreader.bookmodel.BookReader;
import org.geometerplus.fbreader.formats.JavaFormatPlugin;
import org.geometerplus.fbreader.library.ReadBook;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.filesystem.ZLTxtPhysicalFile;
import org.geometerplus.zlibrary.core.image.ZLImage;
import org.geometerplus.zlibrary.core.util.ZLArrayUtils;

import com.chineseall.reader.ui.view.FileLocalCache;
import com.chineseall.readerapi.exception.ErrorMsgException;
import com.chineseall.readerapi.util.LogUtil;

public class TxtPlugin extends JavaFormatPlugin {

	private static final int BUFF_SIZE = 512 * 1024;
	private static byte[] readBuffer = new byte[BUFF_SIZE];
	BookReader txtReader;
	public TxtPlugin() {
		super(ZLTxtPhysicalFile.ExtensionName);
		
	}

	@Override
	public String readAnnotation(ZLFile file) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ZLImage readCover(ZLFile file) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean readMetaInfo(ReadBook book) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean readModel(BookModel model) {
//		LogUtil.startTime("readmodel");
		txtReader = new BookReader(model);
		txtReader.setMainTextModel();
//		LogUtil.endTime("readmodel");
		
		LogUtil.startTime("read");
		readContent(model.Book.File.getPath());
		LogUtil.endTime("read");
		return true;
	}
	
	private byte[] myUnderflowByteBuffer = new byte[4];
	private int myUnderflowLength;
	private int myTextBufferLength;
	private char[] myTextBuffer = new char[512 * 1024];
	CharsetDecoder myByteDecoder = null;

	
	public final void addByteData(byte[] data, int start, int length) {
		final int oldLength = myTextBufferLength;
		
//		LogUtil.startTime("addbyte");
		
		if (myTextBuffer.length < oldLength + length) {
			myTextBuffer = ZLArrayUtils.createCopy(myTextBuffer, oldLength, oldLength + length);
		}
		final CharBuffer cb = CharBuffer.wrap(myTextBuffer, myTextBufferLength, length);

		if (myUnderflowLength > 0) {
			int l = myUnderflowLength;
			while (length-- > 0 && l < 4) {
				myUnderflowByteBuffer[l++] = data[start++];
				final ByteBuffer ubb = ByteBuffer.wrap(myUnderflowByteBuffer);
				myByteDecoder.decode(ubb, cb, false);
				if (cb.position() != oldLength) {
					myUnderflowLength = 0;
					break;
				}
			}
			if (length == 0) {
				myUnderflowLength = l;
				return;
			}
		}
//        LogUtil.endTime("addbyte");
//        
//        LogUtil.startTime("addcontent");
		ByteBuffer bb = ByteBuffer.wrap(data, start, length);
		myByteDecoder.decode(bb, cb, false);
		myTextBufferLength = cb.position();
		int rem = bb.remaining();
		if (rem > 0) {
			for (int i = 0, j = start + length - rem; i < rem;) {
				myUnderflowByteBuffer[i++] = data[j++];
			}
			myUnderflowLength = rem;
		}
//        LogUtil.startTime("=====addcontentData=");
		addContentsData(myTextBuffer, oldLength, myTextBufferLength - oldLength);
//		LogUtil.endTime("=====addcontentData=");
//		LogUtil.endTime("addcontent");
	}
	
	/**
	 * 获取byte[]对应的格式化的段落字符数组
	 * 一个段落为一个一维的字符数组
	 * @param data
	 * @param start
	 * @param length
	 * @param isFrontToLastDataBlock 该数据块是不是位于上次操作数据块前面
	 * @return
	 */
	public final char[][] getFormatsParaphData(byte[] data, int start, int length, boolean isFrontToLastDataBlock) {
		if(isFrontToLastDataBlock)
		{
			myUnderflowLength = 0;
		}
		final int oldLength = myTextBufferLength;
		if (myTextBuffer.length < oldLength + length) {
			myTextBuffer = ZLArrayUtils.createCopy(myTextBuffer, oldLength, oldLength + length);
		}
		final CharBuffer cb = CharBuffer.wrap(myTextBuffer, myTextBufferLength, length);

		if (myUnderflowLength > 0) {
			int l = myUnderflowLength;
			while (length-- > 0 && l < 4) {
				myUnderflowByteBuffer[l++] = data[start++];
				final ByteBuffer ubb = ByteBuffer.wrap(myUnderflowByteBuffer);
				myByteDecoder.decode(ubb, cb, false);
				if (cb.position() != oldLength) {
					myUnderflowLength = 0;
					break;
				}
			}
			if (length == 0) {
				myUnderflowLength = l;
				return null;
			}
		}

		ByteBuffer bb = ByteBuffer.wrap(data, start, length);
		myByteDecoder.decode(bb, cb, false);
		myTextBufferLength = cb.position();
		int rem = bb.remaining();
		if (rem > 0) {
			for (int i = 0, j = start + length - rem; i < rem;) {
				myUnderflowByteBuffer[i++] = data[j++];
			}
			myUnderflowLength = rem;
		}
		return getContentsData(myTextBuffer, oldLength, myTextBufferLength - oldLength);
	}
	
	/**
	 * 
	 */
	private StringBuilder cacheBuffer = new StringBuilder(1024 * 256);
	private StringBuilder headerBuffer = new StringBuilder();
	private StringBuilder endBuffer =  new StringBuilder();
	
	private char[][] getContentsData(char[] charBuffer, int offset, int length)
	{
		//cacheBuffer此时内容若不为空,则为上次读取时,末尾未结尾的段落内容.
		if(charBuffer != null)
		{
			cacheBuffer.insert(0, headerBuffer);
			headerBuffer.delete(0, headerBuffer.length());
			cacheBuffer.append(headerBuffer, offset, length);
			cacheBuffer.insert(cacheBuffer.length(), endBuffer);
			endBuffer.delete(0, endBuffer.length());
		}
		charBuffer = null;
		
		String formatContents =formatParagraph(cacheBuffer.toString());
		String[] chapterContents = formatContents.split("\r\n");
		formatContents = null;
		char[][] contentData = null;
		
		if(chapterContents.length > 2)
		{
			headerBuffer.append(chapterContents[0]);
			contentData = new char[chapterContents.length - 2][];
			for(int i = 1; i < chapterContents.length - 1; i++)
			{
				contentData[i - 1] = chapterContents[i].toCharArray();
				chapterContents[i] = null;
			}
			endBuffer.append(chapterContents[chapterContents.length - 1]);
		}
		else
		{
			headerBuffer.append(chapterContents[0]);
			endBuffer.append(chapterContents[0]);
		}
		chapterContents[chapterContents.length - 1] = null;
		myTextBufferLength = 0;
		chapterContents = null;
		
		return contentData;
	}
	
	private void addContentsData(char[] charBuffer, int offset, 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
主要电子书格式:ePub(包括ePub3的主要功能),PDF,Kindle azw3(mobipocket),fb2(.zip)。其他支持的格式:漫画书(CBR / CBZ),RTF,doc(MS Word),html,plain文本。 升级到这个流行的电子书阅读器的高级版。 此高级版本提供的功能: * Google / Yandex翻译集成 *内置支持PDF和漫画书格式 *缩略图库视图 为了帮助阅读外语,请使用FBReader的字典集成来查找单词或短语。您可以从众多外部词典中进行选择。 在FBReader Premium中,您可以使用集成的Google或Yandex翻译器在不离开应用程序的情况下翻译句子。(警告:此功能的每日使用可能会受到限制。) FBReader支持使用基于Google Drive™的云服务FBReader图书网络(https://books.fbreader.org/)同步您的图书馆和/或阅读位置。默认情况下禁用同步; 要启用和配置它,请使用首选项对话框。 FBReader快速且高度可定制 - 它可以使用外部TrueType / OpenType字体和自定义背景,可以在阅读时调整屏幕亮度(沿着左侧屏幕边缘向上/向下滑动手指),并且可以选择不同的日/夜配色方案。 该阅读器还包括一个浏览器/下载器,用于访问不同的网络电子书目录和商店。包括几个流行的英语,法语,俄语,中文和波兰语库。也支持自定义OPDS目录。 或者,您可以手动下载书籍并将其保存在/ sdcard / Books中的设备上。 此外,该阅读器本地化为34种语言,包括24种语言的连字模式。该应用程序是开源(GPL)。 什么是新的 内置文字转语音模块 文件选择器 新升商店目录 重大内部变化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了悟生死大事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值