19

at the moment I am using itext to read the page count of a pdf. This takes quite long because the lib seems to scan the whole file.

Is the page information somewhere in the header of the pdf, or is a full filescan needed?

hans sausage
  • 221
  • 1
  • 3
  • 4

6 Answers6

26

That's correct. iText parses quite a bit of a PDF when it is opened (it doesn't read the contents of stream objects, but that's about it)...

UNLESS you use the PdfReader(RandomAccessFileOrArray) constructor, in which case it will only read the xrefs (mostly required), but not parse anything until you start requesting specific objects (directly or via various calls).

The first PDF program I ever wrote did exactly this. It opened up a PDF and doing the bare minimum amount of work necessary, read the number of pages. It didn't even parse the xrefs it didn't have to. Haven't thought about that program in years...

So while not perfectly efficient, it'll be vastly more efficient to use a RandomAccessFileOrArray:

int efficientPDFPageCount(String path) {
  RandomAccessFileOrArray file = new RandomAccessFileOrArray(path, false, true );
  PdfReader reader = new PdfReader(file);
  int ret = reader.getNumberOfPages();
  reader.close();
  return ret;
}

Update:

The itext API underwent a little overhaul. Now (in version 5.4.x) the correct way to use it is to pass through java.io.RandomAccessFile:

int efficientPDFPageCount(File file) {
     RandomAccessFile raf = new RandomAccessFile(file, "r");
     RandomAccessFileOrArray pdfFile = new RandomAccessFileOrArray(
          new RandomAccessSourceFactory().createSource(raf));
     PdfReader reader = new PdfReader(pdfFile, new byte[0]);
     int pages = reader.getNumberOfPages();
     reader.close();
     return pages;
  }
Lauri Lehtinen
  • 10,647
  • 2
  • 31
  • 29
Mark Storer
  • 15,672
  • 3
  • 42
  • 80
  • Shouldn't raf.close() be called to free resources ? – Olivier Masseau Dec 05 '17 at 16:08
  • 1
    I ran a quick test locally where I read a bunch of PDF files using `Apache PDFBox (2.0.26)` vs `IText (5.5.13.3)` with the `byte[]` constructor for `PdfReader` vs same `IText` with the code shown above using a `RandomAccessFile`. For some reason, the code above seems to come out as slowest. `IText` with `byte[]` constructor finished in `767ms`, followed by `PDFBox` in `1485ms` and the code above in `8462ms`. Not sure if I'm missing something, or if something changed in `IText` in the meantime, but using the `byte[]` constructor seems to be much faster. – SND Jul 07 '22 at 06:20
4

Lars Vogel uses the following code:

PdfReader reader = new PdfReader(INPUTFILE);
int n = reader.getNumberOfPages();

I'd be surprised if the implementation of getNumberOfPages is slower than any other solution.


Section F.3.3 says there is a header-field called N described as follows:

N     integer (Required)      The number of pages in the document.
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • yes i know that's my code. But does this piece of code have to scan the full pdf or would their be an easier way if you only read the header of the pdf. – hans sausage May 17 '11 at 06:32
3

You just need to read the Page tree (Catalogue, Pages, Kids) and count the Page entries.

mark stephens
  • 3,205
  • 16
  • 19
1

In iText version 5.5.13 the method bellow will give you a page number without scanning the whole file. It will not read full file content into memory.

int efficientPDFPageCount(String filePath){
     PdfReader reader = new PdfReader(filePath, new byte[0], true);
     int pages = reader.getNumberOfPages();
     reader.close();
     return pages;

}

Deividas Duda
  • 123
  • 1
  • 8
  • You can also use the `PdfReader(ReaderProperties properties, final String filename)` constructor and set partial read to `true`. – dvlcube Aug 18 '23 at 04:52
0
PdfReader document = new PdfReader(new FileInputStream(new File("filename")));  
int noPages = document.getNumberOfPages(); 
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
TKV
  • 2,533
  • 11
  • 43
  • 56
0
PdfReader document = new PdfReader(new FileInputStream(new File("filename")));   
int noPages = document.getNumberOfPages(); 

above is the process for counting the pdf pages

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
developer
  • 9,116
  • 29
  • 91
  • 150