Java tutorial
/** * pdfformfiller 1.0-alpha is a command line utility for filling in Adobe PDF Forms. * * Well known pdftk utility can be used for filling in Adobe Pdf Forms. * However, I was not able to get the version pdftk1.4 to work with UTF-8. * It's XFDF format support UTF-8 encoding, however it assumes Adobe uses an UTF-8 * font by default. Whereas, Adobe Readers (at least upto version X) do not, * and UTF-8 text is entered by pdftk but is not shown in its form until user clicks * on the form and edits it. * * In PdfFormFiller, you can use the -font option to specify a UTF-8 font * to use to fill in the forms to resolve this issue. * * Also, our fields input file format is much simpler then XFDF of pdftk that * requires XML parsing. * * Based on the Belgian iText library v. 5.2.0, http://www.itextpdf.com/ * * (C) copyleft AGPL license, http://itextpdf.com/terms-of-use/agpl.php, Nikolay Kitsul. * * @author Nikolay Kitsul * @version 1.0-alpha */ package PdfFormFiller; import java.io.*; import java.io.OutputStream; import java.util.*; import java.util.Map; import java.util.Scanner; import com.itextpdf.text.pdf.*; import com.itextpdf.text.*; //import com.itextpdf.text.pdf.Item; class WrongParamsExeption extends Exception { }; public class PdfFormFiller { static Boolean verbose; /** * @param args the command line arguments */ public static void main(String[] args) { String document, operation = "fill", fields = null, font = null, output = null; Boolean flatten = false; verbose = false; try { if (args.length < 1) throw new WrongParamsExeption(); document = args[0]; for (int i = 1; i < args.length; i++) { if (args[i].equals("-v")) { verbose = true; } else if (args[i].equals("-flatten")) { flatten = true; } else if (args[i].equals("-l")) { operation = "list"; } else if (args[i].equals("-f")) { if (i + 1 >= args.length) throw new WrongParamsExeption(); fields = args[++i]; } else if (args[i].equals("-font")) { if (i + 1 >= args.length) throw new WrongParamsExeption(); font = args[++i]; } else if (i + 1 == args.length) { output = args[i]; } else { throw new WrongParamsExeption(); } } fillPDFFile(document, output, fields, font, operation, flatten, verbose); } catch (WrongParamsExeption e) { if (e.getMessage() != null) System.out.println(e.getMessage()); System.out.println( "USAGE: pdfformfiller document.pdf [ -l ] [ -v ] [ -f fields_filename ] [ -font font_file ] [ -flatten] [ output.pdf ]\n\n" + " document.pdf - name of source pdf file (required).\n" + " -l - only list availible fields in document.pdf.\n" + " -v - verbose. Use to debug the fields_filename file. \n" + " -f fields_filename - name of file with the list of fields values to apply to document.pdf. \n" + " if ommited, stdin is used.\n" + " -font font_file - font to use. Needed UTF-8 support, e.g. cyrillic and non-latin alphabets.\n" + " -flatten - Flatten pdf forms (convert them to text disabling editing in PDF Reader).\n" + " output.pdf - name of output file. If omitted, the output if sent to stdout. \n\n" + "fields_filename file can be in UTF-8 as is of the following format:\n" + " On each line, one entry consists of 'field name' followed by value of that field without any quotes.\n" + " Any number of whitespaces allowed before 'field name', and one space separates 'field name' and its value.\n" + " In value, newline characters should be encoded as \"\\n\",\n" + " 'U+2029 utf-8 E280A9 : PARAGRAPH SEPARATOR PS' should be encoded as \"\\p\",\n" + " and '\\' characters should be escaped as \"\\\\\".\n" + " For checkboxes, values are 'Yes'/'Off'.\n\n" + " Based on the Belgian iText library v. 5.2.0, http://www.itextpdf.com/\n"); System.exit(1); } } public static void fillPDFFile(String pdf_filename_in, String pdf_filename_out, String fields_filename) { fillPDFFile(pdf_filename_in, pdf_filename_out, fields_filename, null, "fill", false, false); } public static void fillPDFFile(String pdf_filename_in, String pdf_filename_out, String fields_filename, String font_file, String op, Boolean flatten, Boolean verbose) { OutputStream os; PdfStamper stamp; try { PdfReader reader = new PdfReader(pdf_filename_in); if (pdf_filename_out != null) { os = new FileOutputStream(pdf_filename_out); } else { os = System.out; } stamp = new PdfStamper(reader, os, '\0'); AcroFields form = stamp.getAcroFields(); if (op.equals("list")) { formList(form); } else { if (font_file != null) { BaseFont bf = BaseFont.createFont(font_file, BaseFont.IDENTITY_H, true); form.addSubstitutionFont(bf); } Map<String, String> fields = readFile(fields_filename); for (Map.Entry<String, String> entry : fields.entrySet()) { if (verbose) System.out.println("Field name = '" + entry.getKey() + "', New field value: '" + entry.getValue() + "'"); form.setField(entry.getKey(), entry.getValue()); } stamp.setFormFlattening(flatten); stamp.close(); } } catch (FileNotFoundException e) { System.err.println("FileNotFoundException: " + e.getMessage()); System.exit(2); } catch (IOException e) { System.err.println("Input output error: " + e.getMessage()); System.exit(3); } catch (DocumentException e) { System.err.println("Error while processing document: " + e.getMessage()); System.exit(4); } } public static void formList(AcroFields form) { Map<String, AcroFields.Item> map = form.getFields(); System.out.println("Field names:"); for (Map.Entry<String, AcroFields.Item> entry : map.entrySet()) System.out.println(entry.getKey()); System.out.println("END: Field names"); } /** * <var>filename</var> file can be in UTF-8 and in of the following format:<br><br> * On each line, one entry consists of <i>field name</i> followed by value of that field without any quotes. <br> * Any number of whitespaces allowed before <i>field name</i> and between <i>field name</i> and its value.<br> * In value, newline characters should be encoded as \n * and '\' characters should be escaped as "\\". <br> * For checkboxes, values are 'Yes'/'Off'."<br> * * @param filename name of file with fields and their values. * @return * @throws java.io.FileNotFoundException */ public static Map<String, String> readFile(String filename) throws java.io.FileNotFoundException { Map<String, String> fields = new HashMap<String, String>(); String s, v; String[] t; Scanner input; if (filename != null) //input = new Scanner(new File(filename)); input = new Scanner(new BufferedReader(new FileReader(filename))); else input = new Scanner(System.in); int i = 1; while (input.hasNext()) { s = input.nextLine().trim(); t = s.split("\\s", 2); if (t.length == 2) { // Unescape "\n": v = unescape(t[1]); fields.put(t[0], v); } else { if (verbose) System.out.println("Line " + i + ": " + s + "\nskipped."); } i++; } IOException ex = input.ioException(); if (ex != null) ex.printStackTrace(System.out); if (verbose) System.out.println((i - 1) + " lines from " + (filename == null ? "stdin" : filename) + " parsed."); input.close(); return fields; } /** * Unescapes "\n", etc. * * @param str * @return resuling string. */ public static String unescape(String str) { String out = ""; char ch, next; if (str == null) { return null; } final int length = str.length(); for (int offset = 0; offset < length;) { ch = str.charAt(offset); if ((ch == '\\') && ((offset + 1) < length)) { next = str.charAt(offset + 1); switch (next) { case '\\': out += '\\'; break; case 'n': out += '\n'; break; case 'p': // U+2029 utf-8 E280A9 : PARAGRAPH SEPARATOR PS out += '\u2029'; break; default: { out += (ch + next); } } offset++; } else out += ch; offset++; } return out; } }