Đọc và Ghi File PDF trong Java
Bài đăng này đã không được cập nhật trong 3 năm
PDF (Portable Document Format) là một định dạng tập tin văn bản khá phổ biển của hãng Adobe Systems. Tương tự như định dạng Word (.doc), PDF hỗ trợ văn bản thô (text) cùng với phông chữ, hình ảnh đồ họa, âm thanh và nhiều hiệu ứng khác. Tuy nhiên, việc hiển thị văn bản PDF không phụ thuộc vào môi trường làm việc của người sử dụng (cấu hình máy, phần mềm và hệ điều hành). Không như văn bản Word, một văn bản PDF, trong hầu hết các trường hợp, sẽ được hiển thị giống nhau trên những môi trường làm việc khác nhau. Chính vì ưu điểm này, định dạng PDF đã trở nên phổ biển cho việc phát hành sách, báo hay các tài liệu khác qua mạng Internet.
Có nhiều lựa chọn để tạo file .pdf trong Java: 1. Từ data object chuyển đổi thành XML (sủ dụng JAXB, XStream...), sau đó chuyển đổi thành XSL-FO (XSL Formatting Objects) và từ đó render ra file PDF bằng cách sử dụng Formatting Objects Processor (thường là Apache™ FOP). 2. Ngoài ra bạn của thể lựa chọn sử dụng library để thực hiện việc này. Một số library phổ biến: - iText - Apache PDFBox - BFO
Trong khuôn khổ blog này tôi xin giới thiệu với các bạn cách đọc và ghi file .pdf sử dụng iText. Itext là một thư viện cho phép bạn đọc, tạo và chỉnh sửa file pdf trên nhiều ngôn ngữ như Java, .Net, Android...
Để sử dụng itext trước tiên bạn cần download itext http://sourceforge.net/projects/itext/ và include itext vào chương trình của bạn.
I. Tạo file PDF đơn giản với Itext.
Chúng ta cùng tìm hiểu qua một chút về cấu trúc cơ bản của 1 file pdf. Mọi file pdf đều gồm các thành phần sau: 1. Header là dòng đầu tiên của file .pdf xác định version kĩ thuật được sử dụng trong file pdf. 2. Body được sử dụng để giữ toàn bộ dữ liệu được hiển thi cho người dùng bao gồm : text stream, image, các thành phần multimedia... 3.'xref' Table là bảng tham khảo chéo, trong đó có chứa các tài liệu tham khảo cho tất cả các đối tượng trong tài liệu. 4. Trailer quy định cách đọc các 'xref' Table và các đối tượng đặc biệt khác.
Bây giờ chúng ta sẽ thực hiện tạo một file .pdf đơn giản.
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
public class HelloWorldExample {
public static void main(String[] args) {
// tạo một document
Document document = new Document();
try {
// khởi tạo một PdfWriter truyền vào document và FileOutputStream
PdfWriter.getInstance(document, new FileOutputStream("HelloWorld.pdf"));
// mở file để thực hiện viết
document.open();
// thêm nội dung sử dụng add function
document.add(new Paragraph("A Hello World PDF document."));
// đóng file
document.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Và đây là kết quả mà ta nhận được.
Bây giờ chúng ta sẽ tìm hiểu một số Element đơn giản trong iText:
Chunk : dùng để thêm một đoạn nhỏ của văn bản
import com.itextpdf.text.Chunk;
...
for(int i = 0; i < 10; i++) {
Chunk chunk = new Chunk("Hello World!!");
document.add(chunk);
}
...
kết quả nhận được sẽ là:
Chunk chỉ thực hiện việc viết từ trái sang phải và không biết khi nào cần phải xuống dòng, để làm điều này chúng ta cần bọc nó trong 1 Phrase.
Phrase:
import com.itextpdf.text.Phrase;
...
Phrase phrase = new Phrase();
for(int i = 0; i < 10; i++) {
Chunk chunk = new Chunk("Hello World!!");
phrase.add(chunk);
}
document.add(phrase);
...
Phrase giúp bạn thêm được dấu xuống dòng nhưng nếu bạn muốn căn chỉnh vị trí, thụt đầu dòng thì nó lại không thực hiện được. Để giải quyết vấn đề này ta sử dụng Paragraph.
Paragraph:
import com.itextpdf.text.Element;
...
//Khai báo 2 paragraph
Paragraph paragraph1 = new Paragraph("This is Paragraph 1");
Paragraph paragraph2 = new Paragraph("This is Paragraph 2");
//Định dạng đoạn văn bản thứ nhất
paragraph1.setIndentationLeft(80);
paragraph1.setIndentationRight(80);
paragraph1.setAlignment(Element.ALIGN_CENTER);
paragraph1.setSpacingAfter(15);
//Đinh dạng đoạn văn bản thứ 2
paragraph2.setSpacingBefore(15);
paragraph2.setAlignment(Element.ALIGN_LEFT);
//Thêm nội dung cho cả 2 đoạn văn bản trên
Phrase phrase = new Phrase("This is a large sentence.");
for(int i = 0; i < 10; i++)
{
paragraph1.add(phrase);
paragraph2.add(phrase);
}
//Thêm 2 đoạn văn bản vào document
document.add(paragraph1);
document.add(paragraph2);
...
Và đây là kết quả thu được: Bạn có thể thực hiện hầu hết các format văn bản khi sử dụng Paragraph
II. Anchor (link), Image, List, Table trong iText
-
Anchor (link)
Để tạo link với iText ta sử dụng class Anchor. Link được tạo ra tương tự như trong Html.
import com.itextpdf.text.Anchor;
...
//Tạo 1 đoạn văn bản
Paragraph paragraph = new Paragraph();
paragraph.add(new Phrase("You can download the IText at "));
//Tạo 1 link
Anchor anchor = new Anchor("Download");
anchor.setReference("http://sourceforge.net/projects/itext/");
//Thêm link vào đoạn văn bản
paragraph.add(anchor);
//Thêm đoạn văn bản vào document
document.add(paragraph);
...
Kết quả:
![Untitled.png](https://images.viblo.asia/0aafc5df-204e-4c19-a117-16d81e7fc0d8.png)
Ngoài ra bạn có thể tạo internal links trong document của bạn tương tự như internal links trong HTML.
-
Image
Bạn có thể làm rất nhiểu thứ với Image khi sử dụng itext như là zoom, xoay, tạo border...
import com.itextpdf.text.Image;
...
//Thêm 1 ảnh
Image image1 = Image.getInstance("framgia.png");
document.add(new Paragraph("Image 1"));
document.add(image1);
//Thêm 1 ảnh được zoom 300%
Image image2 = Image.getInstance("framgia.png");
document.add(new Paragraph("Image 2"));
image2.scalePercent(300f);
document.add(image2);
//Thêm 1 ảnh xoay 45 độ
Image image3 = Image.getInstance("framgia.png");
document.add(new Paragraph("Image 3"));
image3.setRotationDegrees(45f);
document.add(image3);
...
Kết quả:
-
List
Bạn có thể thêm ordered list hoặc unordered list vào document của bạn khi sử dụng class List của iText.
import com.itextpdf.text.List;
...
//Tạo một ordered list
List orderedList = new List(List.ORDERED);
orderedList.add(new ListItem("Item 1"));
orderedList.add(new ListItem("Item 2"));
orderedList.add(new ListItem("Item 3"));
document.add(orderedList);
//Tạo một unordered list
List unorderedList = new List(List.UNORDERED);
unorderedList.add(new ListItem("Item 1"));
unorderedList.add(new ListItem("Item 2"));
unorderedList.add(new ListItem("Item 3"));
document.add(unorderedList);
...
Kết quả
![Capture.PNG](https://images.viblo.asia/81905a1f-b4e1-4595-9098-8949b511af92.png)
-
Table
Khi bạn muốn tạo 1 table trong document thì PdfPTable là class mà bạn cần dùng đến
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
...
//Khởi tạo một table có 3 cột
PdfPTable table = new PdfPTable(3);
//Khởi tạo 3 ô header
PdfPCell header1 = new PdfPCell(new Paragraph("Header 1"));
PdfPCell header2 = new PdfPCell(new Paragraph("Header 2"));
PdfPCell header3 = new PdfPCell(new Paragraph("Header 3"));
//Thêm 3 ô header vào table
table.addCell(header1);
table.addCell(header2);
table.addCell(header3);
//Khởi tạo 3 ô data: ô số 1 là string, ô số 2 là ảnh, ô số 3 là table
PdfPCell data1 = new PdfPCell(new Paragraph("Data String"));
PdfPCell data2 = new PdfPCell(Image.getInstance("framgia.png"), false);
PdfPTable nestedTable = new PdfPTable(2);
nestedTable.addCell(new Paragraph("Nested Cell 1"));
nestedTable.addCell(new Paragraph("Nested Cell 2"));
PdfPCell data3 = new PdfPCell(nestedTable);
//Thêm data vào bảng.
table.addCell(data1);
table.addCell(data2);
table.addCell(data3);
document.add(table);
...
Với đoạn code trên thì đây là kết quả ta thu được.
![Capture.PNG](https://images.viblo.asia/e2eef3df-7368-41c5-945a-8aa0ecf405a4.png)
Nếu sử dụng PdfTable thì bạn chỉ có lựa chọn là thêm từng ô dữ liệu.
III. Đọc file PDF với iText
Bây giờ ta sẽ tiến hành đọc file .pdf có sẵn.
import java.io.IOException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
public class Progam {
public static void main(String[] args) {
try {
//Khai báo PdfReader với giá trị truyền vào là path của file cần đọc
PdfReader reader = new PdfReader("Java How to Program, 9th edition.pdf");
//In ra số lượng page của file đã đọc
System.out.println("This PDF has "+reader.getNumberOfPages()+" pages.");
//Sử dụng PdfTextExtractor để đọc toàn bộ text ở trang 100
String page = PdfTextExtractor.getTextFromPage(reader, 100);
System.out.println("Page 100 Content:\n\n"+page+"\n\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Và đây là kết quả thu được:
IV. Lời kết
iText là 1 library rất tiện ích khi làm việc với file PDF trong java. Trong khuôn khổ blog này mình chỉ giới thiệu được những tính năng cơ bản nhất của iText. Hẹn gặp lại các bạn ở blog sau.
Tài liệu tham khảo: - Itext documents: http://itextpdf.com/apis - Ebook : iText in Action, Second Edition
Link Git sản phẩm: Đang cập nhật
All rights reserved