我需要做与Stack Overflow问题几乎相同的事情:Renaming named destinations in PDF files但是我的PDF充满了书签,而不是包含命名目的地的文本本身。当我运行Bruno's code时,我的名字对象是空的 - 尽管(正确读入)PDF中有200多个书签 - 而Java会抛出NullPointerException。有关为什么的任何想法?
Exception in thread "main" java.lang.NullPointerException
at annotations.RenameDestinations.manipulatePdf(RenameDestinations.java:41)
at annotations.RenameDestinations.main(RenameDestinations.java:33)
免责声明:我是iText的新手。
答案 0 :(得分:0)
我得到了这个工作。如果其他人需要在许多PDF文件中重命名PDF书签(批量书签重命名),您可以避免使用下面的脚本支付Autobookmark。我是第一个承认它可以改进的人,可能是极大的(尤其是通过重构),但它确实有效!我使用的是Windows 7 64位和带有UTF-8编码字形的文件。它假定您使用" in"创建一个c:\ in和c:\ out。包含原件的文件夹和" out"包含重命名的书签版本。该计划不会改变您原来的PDF格式。观察控制台输出以查看itext无法处理的任何PDF。就我而言,我有一些零字节的PDF,安全的PDF,甚至已经损坏的PDF也无法处理。
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!");
}
}