1

I need to do almost the same thing as this Stack Overflow question: Renaming named destinations in PDF files but my PDF is full of bookmarks rather than the text itself containing the named destinations. When I run Bruno's code, my names object is empty--despite the 200+ bookmarks in the (properly read in) PDF--and Java throws a NullPointerException. Any thoughts about why?

Exception in thread "main" java.lang.NullPointerException
at annotations.RenameDestinations.manipulatePdf(RenameDestinations.java:41)
at annotations.RenameDestinations.main(RenameDestinations.java:33)

Disclaimer: I'm new to iText.

Community
  • 1
  • 1
mellow-yellow
  • 1,261
  • 1
  • 11
  • 30

1 Answers1

0

I got this working. In case anyone else needs to rename the PDF bookmarks in many PDF files (batch bookmark renaming), you can avoid paying for Autobookmark with the script below. I'll be the first to admit that it could be improved, probably drastically (not least by refactoring), but it works! I'm using Windows 7 64bit and files with UTF-8 encoded glyphs. It assumes you'll create a c:\in and c:\out with the "in" folder containing your originals and "out" containing the renamed bookmark versions. This program won't change your original PDF's. Watch the console output for any PDF's that itext can't handle. In my case, I had some zero byte PDF's, secured PDF's, and even corrupted PDF's that wouldn't process.

package annotations;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.SimpleBookmark;

 public class RenameDestinations {
public static void main(String[] args) throws IOException, DocumentException {
    String in = "c:/in"; // this must be a directory
    String out = "c:/out"; // this must be a directory

    // Parent Bookmarks
    String find1 = "_\n    <"; // e.g., Something_ <Title ...> child bookmark</Title>
    String repl1 = "X\n    <"; // e.g., SomethingX <Title ...> child bookmark</Title>

    // No children
    String find2 = "_</Title>"; // e.g., <Title>Something_</Title>
    String repl2 = "X</Title>"; // e.g., <Title>SomethingX</Title>

    // read a directory of files
    // http://stackoverflow.com/questions/13918876/java-open-directory
    File directory = new File(in);
    File[] contents = directory.listFiles();
    for (File f : contents) {
        // get extension
        String filename = f.getName();
        String extension = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase();

        // leave if not a PDF
        if (!extension.equals("pdf")) {
            System.out.println(filename);
            System.out.println("   NOT PDF, SKIPPED");
            continue;
        }

        // inform user
        System.out.println(filename);

        String src = f.getAbsolutePath();
        String dst = out + "/" + f.getName();
        String srcx = in + "/bookmarks.xml"; // save this book's bookmarks

        // read and create an xml file of the bookmarks
        PdfReader reader = new PdfReader(src);
        List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader);

        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dst));

        //leave if no bookmarks
        if (list == null) {
            System.out.println(filename);
            System.out.println("   NO BOOKMARKS, THUS NO CHANGES MADE");
            stamper.setOutlines(list);
        }else {
            // create bookmarks xml
            SimpleBookmark.exportToXML(list, new FileOutputStream(srcx), "UTF-8", true);

            // find and replace bookmark titles
            // http://stackoverflow.com/questions/3935791/find-and-replace-words-lines-in-a-file
            Path path = Paths.get(srcx);
            Charset charset = StandardCharsets.UTF_8;
            // store
            String content = new String(Files.readAllBytes(path), charset);
            // replace
            content = content.replaceAll(find1, repl1);
            content = content.replaceAll(find2, repl2);
            // write
            Files.write(path, content.getBytes(charset));

            // read
            // https://code.google.com/p/pdf-pub-tools/source/browse/trunk/pdf-pub-tools/src/java/net/mitnet/tools/pdf/book/pdf/util/PdfBookmarkBuilder.java?spec=svn133&r=133
            List<HashMap<String, Object>> bookmarks = SimpleBookmark.importFromXML(new FileReader(srcx));
            stamper.setOutlines(bookmarks);

            //inform user
            System.out.println("   BOOKMARKS RENAMED!");
        }

        // Close the stamper and reader
        stamper.close();
        reader.close();

    }
    //inform user
    System.out.println("DONE!");
}

}

mellow-yellow
  • 1,261
  • 1
  • 11
  • 30