FBReader支持txt插件

本文档详细介绍了FBReader支持TXT格式的Java插件实现,包括使用JavaIO读取文件、处理编码、内容解析等核心功能。通过添加字节数据到缓冲区并进行解码,将内容转换为段落字符数组,最后进行格式化处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

了悟生死大事

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

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

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

打赏作者

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

抵扣说明:

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

余额充值