「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」
PDF神器iText英文版翻译与学习
作者: 薛大郎.
英文原版: iText in Action 2nd Edition.pdf
坚持. 分享. 成长. 利他 !
一. 前言
我以前是干什么的来着
经过一个春节假期, 如果你很快乐. 而且制定了学习计划的你, 还是一如既往的忘了一干二净的. 远离了电脑, 也少有同事找你处理问题. 导致一上班, 都怀疑自己 我以前是干什么的来着
.
卷王- 小傅哥
又开始了出征了. 只要你上了他的车, 就算你不卷, 你也会觉得了解了很多名词, 如果你卷了, 那你将收获满满. 这个男人卷的路线图, 项目, 和技术点 九浅一深, 助你终成正果.
二.正文.
1.1 PdfReader类源码分析
首先分析构造方法. PdfReader类的构造方法有很多的重载, 能够让我们非常方便的获取一个Reader类. 这里只说一个 这个RandomAccessSource的默认操作, 这里运用了工厂模式和策略模式.
RandomAccessSource byteSource = new RandomAccessSourceFactory()
.setForceRead(false)
.setUsePlainRandomAccess(Document.plainRandomAccess)
.createBestSource(filename)
// RandomAccessSourceFactory#createBestSource(String fileName)
public RandomAccessSource createBestSource(String filename) throws IOException{
// 如果可以获取到这个文件类, 而不抛出IOexception.
File file = new File(filename);
// 先看是否可读, 不可读进行返回其他resource
if (!file.canRead()){
if (filename.startsWith("file:/")
|| filename.startsWith("http://")
|| filename.startsWith("https://")
|| filename.startsWith("jar:")
|| filename.startsWith("wsjar:")
|| filename.startsWith("wsjar:")
|| filename.startsWith("vfszip:")) {
// 其实就是获取InputStream然后获取byte[]然后构造ArrayRandomAccessSource(byte[] array)
return createSource(new URL(filename));
} else {
// 也是获取InputStream然后获取byte[]然后构造ArrayRandomAccessSource(byte[] array)
return createByReadingToMemory(filename);
}
}
// 上边默认的设置为 false
if (forceRead){
return createByReadingToMemory(new FileInputStream(filename));
}
String openMode = exclusivelyLockFile ? "rw" : "r";
RandomAccessFile raf = new RandomAccessFile(file, openMode);
if (exclusivelyLockFile){
raf.getChannel().lock();
}
// 默认Document.plainRandomAccess = false;
if (usePlainRandomAccess){
return new RAFRandomAccessSource(raf);
}
try{
// if this throws, the RAF will be closed by the FileChannelRandomAccessSource or PagedChannelRandomAccessSource
return createBestSource(raf.getChannel());
} catch (MapFailedException e){
// if this throws, the RAF will be closed by the RAFRandomAccessSource
return new RAFRandomAccessSource(raf);
} catch (IllegalArgumentException iae) { //pdf files with zero or negative length stay opened without this catch
return new RAFRandomAccessSource(raf);
}
}
RandomAccessSource的实现类如下:
在构造函数中还有一个关键的参数为: boolean partialRead
, 如果使用 PdfReader(String filename), 默认为全部读取.
if (partialRead){
// 只读部分
readPdfPartial();
} else {
// 全部都读到内存中.
readPdf();
}
这就需要我们去斟酌了, 一般都是采用都读到内存中, 方便使用, 但是我们在处理大型Pdf文件的时候, 使用PdfReader的时候, 就要使用自己构造一个RandomAccessFileOrArray, 并将参数 partialRead 改为true.
另一种可以减少内存使用的方法是我们同样也都读取到内存中, 但是可以 PdfReader#selectPages(String ranges);
这个ranges的语法为:
[!][o][odd][e][even]start[-end]
[!] 代表非 可选
[o] 代表奇数 可选
[e] 代表偶数 可选
start 代表起始页 必选 包含此页
[-end] 代表终止页 可选 包含此页
public void selectPages(final String ranges) {
selectPages(SequenceList.expand(ranges, getNumberOfPages()));
}
public void selectPages(final List<Integer> pagesToKeep) {
pageRefs.selectPages(pagesToKeep);
// 也会将无用的页码 去掉, 并重新排序页码数为第一页, 依此类推.
removeUnusedObjects();
}
这就是今天这一篇的内容了. 咱们明天继续.