cervotoc
cervotoc

Reputation: 11

Java, edit pdf exist text with PDFBox

i trying edit text with library PDFBox and don't no how. I do not know how to get stream of individual text objects, so I could edit the text and or color.

Any idea, example? Thanks

Upvotes: 1

Views: 5751

Answers (2)

Anton Tsyopa
Anton Tsyopa

Reputation: 21

Remark:

It works under specific circumstances (ASCII'ish font encodings + pretty long string arguments)


/**
 * This is an example that will replace a string in a PDF with a new one.
 *
 * The example is taken from the pdf file format specification.
 *
 * @author <a href="mailto:[email protected]">Ben Litchfield</a>
 * @version $Revision: 1.3 $
 */
public class ReplaceString {
    /**
     * Constructor.
     */
    public ReplaceString() {
        super();
    }

    /**
     * Locate a string in a PDF and replace it with a new string.
     *
     * @param inputFile The PDF to open.
     * @param outputFile The PDF to write to.
     * @param strToFind The string to find in the PDF document.
     * @param message The message to write in the file.
     *
     * @throws IOException If there is an error writing the data.
     * @throws COSVisitorException If there is an error writing the PDF.
     */
    public void doIt( String inputFile, String outputFile, String strToFind,  String message)
        throws IOException, COSVisitorException {
        // the document
        PDDocument doc = null;
        try
        {
            doc = PDDocument.load( inputFile );
            List pages = doc.getDocumentCatalog().getAllPages();
            for( int i=0; i<pages.size(); i++ )
            {
                PDPage page = (PDPage)pages.get( i );
                PDStream contents = page.getContents();
                PDFStreamParser parser = new PDFStreamParser(contents.getStream());
                parser.parse();
                List tokens = parser.getTokens();
                for( int j=0; j<tokens.size(); j++ )
                {
                    Object next = tokens.get( j );
                    if( next instanceof PDFOperator )
                    {
                        PDFOperator op = (PDFOperator)next;
                        //Tj and TJ are the two operators that display
                        //strings in a PDF
                        if( op.getOperation().equals( "Tj" ) )
                        {
                            //Tj takes one operator and that is the string
                            //to display so lets update that operator
                            COSString previous = (COSString)tokens.get( j-1 );
                            String string = previous.getString();
                            string = string.replaceFirst( strToFind, message );
                            previous.reset();
                            previous.append( string.getBytes("ISO-8859-1") );
                        }
                        else if( op.getOperation().equals( "TJ" ) )
                        {
                            COSArray previous = (COSArray)tokens.get( j-1 );
                            for( int k=0; k<previous.size(); k++ )
                            {
                                Object arrElement = previous.getObject( k );
                                if( arrElement instanceof COSString )
                                {
                                    COSString cosString = (COSString)arrElement;
                                    String string = cosString.getString();
                                    string = string.replaceFirst( strToFind, message );
                                    cosString.reset();
                                    cosString.append( string.getBytes("ISO-8859-1") );
                                }
                            }
                        }
                    }
                }
                //now that the tokens are updated we will replace the
                //page content stream.
                PDStream updatedStream = new PDStream(doc);
                OutputStream out = updatedStream.createOutputStream();
                ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
                tokenWriter.writeTokens( tokens );
                page.setContents( updatedStream );
            }
            doc.save( outputFile );
        }
        finally
        {
            if( doc != null )
            {
                doc.close();
            }
        }
    }

    /**
     * This will open a PDF and replace a string if it finds it.
     * <br />
     * see usage() for commandline
     *
     * @param args Command line arguments.
     */
    public static void main(String[] args)
    {
        ReplaceString app = new ReplaceString();
        try
        {
            if( args.length != 4 )
            {
                app.usage();
            }
            else
            {
                app.doIt( args[0], args[1], args[2], args[3] );
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * This will print out a message telling how to use this example.
     */
    private void usage()
    {
        System.err.println( "usage: " + this.getClass().getName() +
            " <input-file> <output-file> <search-string> <Message>" );
    }
}

Upvotes: 0

Bruce
Bruce

Reputation: 791

I found editing text in pdf is not reliable, so try to clear the text with a rectangle (white/background color fill) and write the new text in the cleared position. Here is a sample code.

//to add a link in footer
//to replace a text
//to replace a link/url/href
public static void editTextorUrl(String inputFile, String outputFile)
        throws IOException, COSVisitorException {
    // the document
    PDDocument doc = null;
    try {
        System.out.println(inputFile);
        doc = PDDocument.load(inputFile);
        List pages = doc.getDocumentCatalog().getAllPages();
        for (int i = 0; i < pages.size(); i++) {

            float inch = 72;
            PDGamma colourRed = new PDGamma();
            colourRed.setR(1);
            PDGamma colourBlue = new PDGamma();
            colourBlue.setB(1);
            PDGamma white = new PDGamma();
            white.setR(1);
            white.setB(1);
            white.setG(1);

            PDBorderStyleDictionary borderThick = new PDBorderStyleDictionary();
            borderThick.setWidth(inch / 12); // 12th inch
            PDBorderStyleDictionary borderThin = new PDBorderStyleDictionary();
            borderThin.setWidth(inch / 72); // 1 point
            PDBorderStyleDictionary borderULine = new PDBorderStyleDictionary();
            borderULine.setStyle(PDBorderStyleDictionary.STYLE_UNDERLINE);
            borderULine.setWidth(inch / 72); // 1 point

            PDPage page = (PDPage) pages.get(i);
                    PDFont font = PDType1Font.HELVETICA;

            PDPageContentStream contentStream = new PDPageContentStream(
                    doc, page, true, false);
            contentStream.setNonStrokingColor(Color.WHITE);
            contentStream.fillRect(55, 27, 144, 17);
            contentStream.setNonStrokingColor(Color.BLUE);
            contentStream.beginText();
            contentStream.setFont(font, 11);
            contentStream.moveTextPositionByAmount(55, 37);
            contentStream.drawString("www.loasoftwares.com"); //text to be replaced

            contentStream.endText();
            contentStream.setLineWidth(inch / 300);
            contentStream.setStrokingColor(Color.BLUE);
            contentStream.drawLine(55, 34, 188, 34);
            contentStream.close();

            PDAnnotationLink txtLink = new PDAnnotationLink();
            PDRectangle position = new PDRectangle();
            position.setLowerLeftX(55);
            position.setLowerLeftY(27);
            position.setUpperRightX(188);
            position.setUpperRightY(50);
            txtLink.setRectangle(position);

            // add an action
            PDActionURI action = new PDActionURI();
            action.setURI("www.loasoftwares.com");
            txtLink.setBorderStyle(borderULine);
            txtLink.setAction(action);
            txtLink.setColour(white);

            page.getAnnotations().add(txtLink);
        }
        doc.save(outputFile);
    } finally {
        if (doc != null) {
            doc.close();
        }
    }
}

Upvotes: 1

Related Questions