Java randomAccessFileOrArray()的使用

Java randomAccessFileOrArray()的使用,java,pdf,itext,itext7,Java,Pdf,Itext,Itext7,有谁能解释一下iText中randomAccessFileOrArray()函数的用途,以及它与使用Files.readAllBytes()的区别 我正在使用以下代码行: PdfReader reader = new PdfReader(Files.readAllBytes((new File(filenameSource)).toPath())); 但在运行时,我遇到了java堆空间错误,因此我找到了以下选项: PdfReader reader = new PdfReader(new Ran

有谁能解释一下iText中randomAccessFileOrArray()函数的用途,以及它与使用Files.readAllBytes()的区别

我正在使用以下代码行:

PdfReader reader = new PdfReader(Files.readAllBytes((new File(filenameSource)).toPath()));
但在运行时,我遇到了java堆空间错误,因此我找到了以下选项:

PdfReader reader = new PdfReader(new RandomAccessFileOrArray(filenameSource),null);
但我不太确定这会造成什么不同。有人能帮我一下吗?

由于您同时使用和标签,不清楚您使用的是哪个iText版本。但是,考虑到您引用的代码,它不能是iText version 7,因为
PdfReader
不接受
randomAccessFileOrray
作为构造函数参数

在iText 5中,无论您使用哪个
PdfReader
构造函数,最终都会在内部使用
RandomAccessSource
实现来访问pdf。此接口表示可以从中读取字节的抽象源。该接口中的主要数据检索方法是

public int get(long position, byte bytes[], int off, int len) throws IOException;
使其本质上成为一个通用的
InputStream
,为随机访问添加
position
参数

RandomAccessFileOrArray
实际上只是包装了一个
RandomAccessSource
,并提供了许多以特定格式检索数据的方法(
readChar
readFloat
readLine
,…)。在
PdfReader
构造函数中使用时,仅使用底层的
RandomAccessSource

如果为文件名构造,它将基于命名文件的
RandomAccessFile
生成
RAFRandomAccessSource
,如下所示

PdfReader reader = new PdfReader(filenameSource);
可以

然而,一个重要的区别是:当使用基于
randomAccessFileOrray
PdfReader
构造函数时,
PdfReader
部分模式处理PDF,即它只读取PDF上所需操作所需的部分,并在不再需要时立即忘记它们。否则,PDF将被完全解析并一直保存在内存中

PdfReader
构造函数中的
byte[]
将被包装在
ArrayRandomAccessSource
中,并完全加载,而不是以部分模式加载

因此,这两种方法之间的区别在于,该接口的哪种具体实现用于读取pdf字节,以及是否使用了部分模式(对内存使用有影响):

  • 万一

    PdfReader reader = new PdfReader(Files.readAllBytes((new File(filenameSource)).toPath()));
    
    PdfReader reader = new PdfReader(filenameSource);
    
    pdf首先加载到内存中的
    字节[]
    中,该数组与原始pdf一样大,然后由
    PdfReader
    使用该数组从中解析整个pdf

    内存要求:原始PDF的大小加上完整解析PDF的大小

  • 万一

    PdfReader reader = new PdfReader(Files.readAllBytes((new File(filenameSource)).toPath()));
    
    PdfReader reader = new PdfReader(filenameSource);
    
    PdfReader
    (通过
    RAFRandomAccessSource
    实例)立即从磁盘上的文件中读取,中间没有
    字节[]
    ,并解析整个PDF

    内存要求:完整解析PDF的大小

  • 万一

    PdfReader reader = new PdfReader(new RandomAccessFileOrArray(filenameSource),null);
    
    PdfReader
    (通过
    RAFRandomAccessSource
    实例)立即读取磁盘上的文件,中间没有
    字节[]
    ,并且只解析处理中使用的PDF部分

    内存要求:部分解析的PDF的大小

因此,在大PDF的情况下,这三种方法的资源需求之间存在很大差异

性能差异取决于您的用例;如果你操纵PDF的大部分内容,部分阅读会变慢。如果你只处理一些细节,部分阅读会更快。此外,如果您需要快速删除从中读取的文件(同时仍在处理),则可以选择基于
byte[]
的解决方案


因此,了解所有方法并根据手头的用例使用它们是有意义的。

因此,后者(RandomAccessFileOrArray)中不涉及内存映射概念?不,不涉及内存映射(除非在您使用的Java库版本中的
RandomAccessFile
实现中使用)。但是,在检查时,我意识到您实际上使用的是iText 5.x(或更早版本),而不是iText 7,而我最初的答案假设类似于iText 7,因为您使用了标记。我根据iText 5的细节修改了答案。这里还必须考虑另一个因素,部分PDF解析模式。