如何使用Apache pdfbox在PDF中生成多行

我正在使用Pdfbox来使用Java生成PDF文件。 问题是,当我在文档中添加长文本内容时,显示不正确。 只显示其中的一部分。 这也是一条线。

我想要文本在多行。

我的代码如下:

PDPageContentStream pdfContent=new PDPageContentStream(pdfDocument, pdfPage, true, true); pdfContent.beginText(); pdfContent.setFont(pdfFont, 11); pdfContent.moveTextPositionByAmount(30,750); pdfContent.drawString("I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox"); pdfContent.endText(); 

我的输出:

这是我的输出文件

添加到马克的答案,你可能想知道在哪里拆分你的长string。 您可以使用PDFont方法getStringWidth

把所有东西放在一起,你会得到这样的东西(根据PDFBox版本的不同而有所不同):

PDFBox 1.8.x

 PDDocument doc = null; try { doc = new PDDocument(); PDPage page = new PDPage(); doc.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(doc, page); PDFont pdfFont = PDType1Font.HELVETICA; float fontSize = 25; float leading = 1.5f * fontSize; PDRectangle mediabox = page.findMediaBox(); float margin = 72; float width = mediabox.getWidth() - 2*margin; float startX = mediabox.getLowerLeftX() + margin; float startY = mediabox.getUpperRightY() - margin; String text = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox"; List<String> lines = new ArrayList<String>(); int lastSpace = -1; while (text.length() > 0) { int spaceIndex = text.indexOf(' ', lastSpace + 1); if (spaceIndex < 0) spaceIndex = text.length(); String subString = text.substring(0, spaceIndex); float size = fontSize * pdfFont.getStringWidth(subString) / 1000; System.out.printf("'%s' - %f of %f\n", subString, size, width); if (size > width) { if (lastSpace < 0) lastSpace = spaceIndex; subString = text.substring(0, lastSpace); lines.add(subString); text = text.substring(lastSpace).trim(); System.out.printf("'%s' is line\n", subString); lastSpace = -1; } else if (spaceIndex == text.length()) { lines.add(text); System.out.printf("'%s' is line\n", text); text = ""; } else { lastSpace = spaceIndex; } } contentStream.beginText(); contentStream.setFont(pdfFont, fontSize); contentStream.moveTextPositionByAmount(startX, startY); for (String line: lines) { contentStream.drawString(line); contentStream.moveTextPositionByAmount(0, -leading); } contentStream.endText(); contentStream.close(); doc.save("break-long-string.pdf"); } finally { if (doc != null) { doc.close(); } } 

(用于PDFBox 1.8.x的BreakLongString.javatestingtestBreakString

PDFBox 2.0.x

 PDDocument doc = null; try { doc = new PDDocument(); PDPage page = new PDPage(); doc.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(doc, page); PDFont pdfFont = PDType1Font.HELVETICA; float fontSize = 25; float leading = 1.5f * fontSize; PDRectangle mediabox = page.getMediaBox(); float margin = 72; float width = mediabox.getWidth() - 2*margin; float startX = mediabox.getLowerLeftX() + margin; float startY = mediabox.getUpperRightY() - margin; String text = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox"; List<String> lines = new ArrayList<String>(); int lastSpace = -1; while (text.length() > 0) { int spaceIndex = text.indexOf(' ', lastSpace + 1); if (spaceIndex < 0) spaceIndex = text.length(); String subString = text.substring(0, spaceIndex); float size = fontSize * pdfFont.getStringWidth(subString) / 1000; System.out.printf("'%s' - %f of %f\n", subString, size, width); if (size > width) { if (lastSpace < 0) lastSpace = spaceIndex; subString = text.substring(0, lastSpace); lines.add(subString); text = text.substring(lastSpace).trim(); System.out.printf("'%s' is line\n", subString); lastSpace = -1; } else if (spaceIndex == text.length()) { lines.add(text); System.out.printf("'%s' is line\n", text); text = ""; } else { lastSpace = spaceIndex; } } contentStream.beginText(); contentStream.setFont(pdfFont, fontSize); contentStream.newLineAtOffset(startX, startY); for (String line: lines) { contentStream.showText(line); contentStream.newLineAtOffset(0, -leading); } contentStream.endText(); contentStream.close(); doc.save(new File(RESULT_FOLDER, "break-long-string.pdf")); } finally { if (doc != null) { doc.close(); } } 

(用于PDFBox 2.0.x的BreakLongString.javatestingtestBreakString

结果

Acrobat Reader中显示的结果PDF的屏幕截图

这看起来和预期一样。

当然有很多改进,但是这应该显示如何去做。

添加无条件的换行符

在一个评论aleskv问:

如果string中有\ n,你可以添加换行符吗?

可以很容易地扩展解决scheme,无条件地在换行符处破解,首先将string拆分为'\ n'字符,然后迭代拆分结果。

例如,如果不是从上面的长string

 String text = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox"; 

你想处理这个甚至更长的string与embedded的新行字符

 String textNL = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox.\nFurthermore, I have added some newline characters to the string at which lines also shall be broken.\nIt should work alright like this..."; 

你可以简单地更换

 String text = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox"; List<String> lines = new ArrayList<String>(); int lastSpace = -1; while (text.length() > 0) { [...] } 

在上面的解决scheme中

 String textNL = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox.\nFurthermore, I have added some newline characters to the string at which lines also shall be broken.\nIt should work alright like this..."; List<String> lines = new ArrayList<String>(); for (String text : textNL.split("\n")) { int lastSpace = -1; while (text.length() > 0) { [...] } } 

(从BreakLongString.javatestingtestBreakStringNL

结果:

截图

我知道这有点迟,但是我对mkl的解决scheme有点问题。 如果最后一行只包含一个单词,那么你的algorithm会把它写在前一个单词上。

例如:“Lorem ipsum dolor sit amet”是你的文本,它应该在“坐”后添加一个换行符。

 Lorem ipsum dolor sit amet 

但它是这样做的:

 Lorem ipsum dolor sit amet 

我想出了我自己的解决scheme,我想与你分享。

 /** * @param text The text to write on the page. * @param x The position on the x-axis. * @param y The position on the y-axis. * @param allowedWidth The maximum allowed width of the whole text (eg the width of the page - a defined margin). * @param page The page for the text. * @param contentStream The content stream to set the text properties and write the text. * @param font The font used to write the text. * @param fontSize The font size used to write the text. * @param lineHeight The line height of the font (typically 1.2 * fontSize or 1.5 * fontSize). * @throws IOException */ private void drawMultiLineText(String text, int x, int y, int allowedWidth, PDPage page, PDPageContentStream contentStream, PDFont font, int fontSize, int lineHeight) throws IOException { List<String> lines = new ArrayList<String>(); String myLine = ""; // get all words from the text // keep in mind that words are separated by spaces -> "Lorem ipsum!!!!:)" -> words are "Lorem" and "ipsum!!!!:)" String[] words = text.split(" "); for(String word : words) { if(!myLine.isEmpty()) { myLine += " "; } // test the width of the current line + the current word int size = (int) (fontSize * font.getStringWidth(myLine + word) / 1000); if(size > allowedWidth) { // if the line would be too long with the current word, add the line without the current word lines.add(myLine); // and start a new line with the current word myLine = word; } else { // if the current line + the current word would fit, add the current word to the line myLine += word; } } // add the rest to lines lines.add(myLine); for(String line : lines) { contentStream.beginText(); contentStream.setFont(font, fontSize); contentStream.moveTextPositionByAmount(x, y); contentStream.drawString(line); contentStream.endText(); y -= lineHeight; } } 

只需在下面的位置绘制string,通常在一个循环内完成:

 float textx = margin+cellMargin; float texty = y-15; for(int i = 0; i < content.length; i++){ for(int j = 0 ; j < content[i].length; j++){ String text = content[i][j]; contentStream.beginText(); contentStream.moveTextPositionByAmount(textx,texty); contentStream.drawString(text); contentStream.endText(); textx += colWidth; } texty-=rowHeight; textx = margin+cellMargin; } 

这些是重要的路线:

 contentStream.beginText(); contentStream.moveTextPositionByAmount(textx,texty); contentStream.drawString(text); contentStream.endText(); 

只要不断在新的位置绘制新的string。 有关使用表格的示例,请参阅: http : //fahdshariff.blogspot.ca/2010/10/creating-tables-with-pdfbox.html

contentStream.moveTextPositionByAmount(textx,texty)是关键。

例如,如果您正在使用A4尺寸,则意味着580,800宽度和高度对应于(近似)。 所以您已经根据文档大小的位置移动了文本。

PDFBox支持各种页面格式。 所以高度和宽度会因不同的页面格式而有所不同

 ///// FOR PDBOX 2.0.X // FOR ADDING DYNAMIC PAGE ACCORDING THE LENGTH OF THE CONTENT import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.font.PDType1Font; public class Document_Creation { public static void main (String args[]) throws IOException { PDDocument doc = null; try { doc = new PDDocument(); PDPage page = new PDPage(); doc.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(doc, page); PDFont pdfFont = PDType1Font.HELVETICA; float fontSize = 25; float leading = 1.5f * fontSize; PDRectangle mediabox = page.getMediaBox(); float margin = 72; float width = mediabox.getWidth() - 2*margin; float startX = mediabox.getLowerLeftX() + margin; float startY = mediabox.getUpperRightY() - margin; String text = "I am trying to create a PDF file with a lot of text contents in the document. I am using PDFBox.An essay is, generally, a piece of writing that gives the author's own argument — but the definition is vague, overlapping with those of an article, a pamphlet, and a short story. Essays have traditionally been sub-classified as formal and informal. Formal essays are characterized by serious purpose, dignity, logical organization, length,whereas the informal essay is characterized by the personal element (self-revelation, individual tastes and experiences, confidential manner), humor, graceful style, rambling structure, unconventionality or novelty of theme.Lastly, one of the most attractive features of cats as housepets is their ease of care. Cats do not have to be walked. They get plenty of exercise in the house as they play, and they do their business in the litter box. Cleaning a litter box is a quick, painless procedure. Cats also take care of their own grooming. Bathing a cat is almost never necessary because under ordinary circumstances cats clean themselves. Cats are more particular about personal cleanliness than people are. In addition, cats can be left home alone for a few hours without fear. Unlike some pets, most cats will not destroy the furnishings when left alone. They are content to go about their usual activities until their owners return."; List<String> lines = new ArrayList<String>(); int lastSpace = -1; while (text.length() > 0) { int spaceIndex = text.indexOf(' ', lastSpace + 1); if (spaceIndex < 0) spaceIndex = text.length(); String subString = text.substring(0, spaceIndex); float size = fontSize * pdfFont.getStringWidth(subString) / 1000; System.out.printf("'%s' - %f of %f\n", subString, size, width); if (size > width) { if (lastSpace < 0) lastSpace = spaceIndex; subString = text.substring(0, lastSpace); lines.add(subString); text = text.substring(lastSpace).trim(); System.out.printf("'%s' is line\n", subString); lastSpace = -1; } else if (spaceIndex == text.length()) { lines.add(text); System.out.printf("'%s' is line\n", text); text = ""; } else { lastSpace = spaceIndex; } } contentStream.beginText(); contentStream.setFont(pdfFont, fontSize); contentStream.newLineAtOffset(startX, startY); float currentY=startY; for (String line: lines) { currentY -=leading; if(currentY<=margin) { contentStream.endText(); contentStream.close(); PDPage new_Page = new PDPage(); doc.addPage(new_Page); contentStream = new PDPageContentStream(doc, new_Page); contentStream.beginText(); contentStream.setFont(pdfFont, fontSize); contentStream.newLineAtOffset(startX, startY); currentY=startY; } contentStream.showText(line); contentStream.newLineAtOffset(0, -leading); } contentStream.endText(); contentStream.close(); doc.save("C:/Users/VINAYAK/Desktop/docccc/break-long-string.pdf"); } finally { if (doc != null) { doc.close(); } } } } 

产量