我正在使用JAXB来解组XML。然后我想拿一些信息并使用iText将其写成PDF格式。由于某种原因,PDF已创建,但我无法打开该文件。我也在使用ZFile,因为它也适用于大型机,但这不应该是一个问题。
写PDF文件时可能我做错了。这是我的代码:
package music;
import java.io.*;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import com.ibm.jzos.ZFile;
import java.io.FileOutputStream;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
import music.Music.Artist;
import music.Music.Artist.Album;
import music.Music.Artist.Album.Description;
import music.Music.Artist.Album.Song;
public class MusicXml {
public static void main(String[] args) throws JAXBException, IOException {
ZFile inputZ = null, outputZ = null;
File inputW = null;
PdfWriter outputW = null;
PdfContentByte cb = null;
Document pdf = new Document(PageSize.A4);
Paragraph paragraf = new Paragraph();
// Font
Font fnt12n;
JAXBContext jaxb = null;
Unmarshaller unmarsh = null;
String line = null, sep = " ";
Music music;
Date date = new Date();
Date startDate = new Timestamp(date.getTime());
System.out.println("Start: " + startDate);
jaxb = JAXBContext.newInstance(ObjectFactory.class);
unmarsh = jaxb.createUnmarshaller();
String os = System.getProperty("os.name");
System.out.println("System: " + os);
boolean isWin = os.toLowerCase().contains("wind");
if (!isWin) {
// z/OS:
inputZ = new ZFile(args[0], "rt"); // "rt" - readtext
InputStream inpStream = inputZ.getInputStream();
InputStreamReader streamRdr = new InputStreamReader(inpStream, "CP870");
try {
outputW = PdfWriter.getInstance(pdf, (new ZFile(args[1], "wb")).getOutputStream());
} catch (DocumentException e) {
e.printStackTrace();
}
music = (Music) unmarsh.unmarshal(streamRdr);
} else {
// Windows:
inputW = new File(args[0]);
music = (Music) unmarsh.unmarshal(inputW);
try {
outputW = PdfWriter.getInstance(pdf, new FileOutputStream(args[1]));
} catch (DocumentException e) {
e.printStackTrace();
}
}
List<Artist> listaArtystow = music.getArtist();
for (Artist artysta : listaArtystow) {
List<Album> listaAlbumow = artysta.getAlbum();
for (Album album : listaAlbumow) {
Description opis = album.getDescription();
List<Song> listaPiosenek = album.getSong();
for (Song piosenka : listaPiosenek) {
String artistName = artysta.getName();
String albumName = album.getTitle();
int numberOfSongs = listaPiosenek.size();
String albumDescription = album.getDescription().getValue();
String songTitle = piosenka.getTitle();
String songDuration = piosenka.getLength();
line = songTitle + sep + songDuration;
FontFactory.register(args[2], "jakiesFonty");
Font font = FontFactory.getFont("jakiesFonty", BaseFont.CP1250, BaseFont.EMBEDDED);
BaseFont bf = font.getBaseFont();
fnt12n = new Font(bf, 12f, Font.NORMAL, BaseColor.BLACK);
// PDF
outputW.setPdfVersion(PdfWriter.VERSION_1_7);
pdf.addTitle("Musical collection");
pdf.addAuthor("Natalia Nazaruk");
pdf.addSubject("Cwiczenie tworzenia PDF z XML");
pdf.addKeywords("Metadata, Java, iText, PDF");
pdf.addCreator("Program: MusicXML");
pdf.setMargins(60, 60, 50, 40);
pdf.open();
pdf.newPage();
try {
paragraf.setAlignment(Element.ALIGN_JUSTIFIED);
paragraf.setSpacingAfter(16f);
paragraf.setLeading(14f);
paragraf.setFirstLineIndent(30f);
paragraf.setFont(fnt12n);
pdf.add(new Paragraph(line, fnt12n));
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
}
date = new Date();
Date stopDate = new Timestamp(date.getTime());
System.out.println("Stop: " + stopDate);
long diffInMs = stopDate.getTime() - startDate.getTime();
float diffInSec = diffInMs / 1000.00f;
System.out.format("Czas przetwarzenia pliku XML: %.2f s.", diffInSec);
System.exit(0);
if (isWin) {
outputW.close();
} else
outputZ.close();
}
}
答案 0 :(得分:2)
除了您选择使用旧版iText之外,您的代码还有其他一些问题。你读过哪些文件?我不认为您已经发现了官方的iText网站,否则您将使用iText 7而不是iText 5,如果您从未关闭Document
对象,您就会知道没有创建有效文档
简短的回答是你忘记了:
pdf.close();
我看到你关闭了输出流:
if (isWin) {
outputW.close();
} else
outputZ.close();
}
这没有多大意义,因为此时PDF还没有最终确定(例如:没有创建交叉引用表)。当您关闭文档时,隐式关闭基础输出流(除非您明确告知iText不这样做)。
您正在创建的循环也有些尴尬:
List<Artist> listaArtystow = music.getArtist();
for (Artist artysta : listaArtystow) {
...
for (Album album : listaAlbumow) {
...
for (Song piosenka : listaPiosenek) {
...
FontFactory.register(args[2], "jakiesFonty");
Font font = FontFactory.getFont("jakiesFonty", BaseFont.CP1250, BaseFont.EMBEDDED);
BaseFont bf = font.getBaseFont();
fnt12n = new Font(bf, 12f, Font.NORMAL, BaseColor.BLACK);
// PDF
outputW.setPdfVersion(PdfWriter.VERSION_1_7);
pdf.addTitle("Musical collection");
pdf.addAuthor("Natalia Nazaruk");
pdf.addSubject("Cwiczenie tworzenia PDF z XML");
pdf.addKeywords("Metadata, Java, iText, PDF");
pdf.addCreator("Program: MusicXML");
pdf.setMargins(60, 60, 50, 40);
pdf.open();
pdf.newPage();
...
}
}
}
output.close();
您反复创建相同的字体。一个PDF只能有1个版本(在您的情况下为PDF-1.7)和1组元数据,但您一遍又一遍地定义该版本和元数据。最后,您多次打开文档,而只需打开一次。
这更有意义:
FontFactory.register(args[2], "jakiesFonty");
Font font = FontFactory.getFont("jakiesFonty", BaseFont.CP1250, BaseFont.EMBEDDED);
BaseFont bf = font.getBaseFont();
fnt12n = new Font(bf, 12f, Font.NORMAL, BaseColor.BLACK);
// PDF
outputW.setPdfVersion(PdfWriter.VERSION_1_7);
pdf.addTitle("Musical collection");
pdf.addAuthor("Natalia Nazaruk");
pdf.addSubject("Cwiczenie tworzenia PDF z XML");
pdf.addKeywords("Metadata, Java, iText, PDF");
pdf.addCreator("Program: MusicXML");
pdf.setMargins(60, 60, 50, 40);
pdf.open();
List<Artist> listaArtystow = music.getArtist();
for (Artist artysta : listaArtystow) {
...
for (Album album : listaAlbumow) {
...
for (Song piosenka : listaPiosenek) {
...
pdf.newPage();
...
}
}
}
pdf.close();
正如您所看到的那样,在循环之前open()
Document
实例pdf
,编写PDF标题,close()
在循环之后Document
写一些对象(例如字体),交叉引用表和PDF预告片。由于您的代码中没有pdf.close()
,因此PDF中缺少所有必要的信息。
由于您是iText的新手,我强烈建议您不使用早于iText 7的版本。您可能已经发现最新的iText 5版本是iText 5.5.13,但这是一个维护发布。在维护版本中,我们仅为付费客户提供错误修复;我们不添加新功能。例如:新的PDF规范ISO 32000-2(又名PDF 2.0)仅适用于iText 7.1。我们不支持旧版本的PDF 2.0。
如果您访问官方网站,您会注意到iText 7.1.1是最新版本(iText 7 download page)。你在哪里找到iText,你怎么选择旧版本? (这不是一个修辞问题:我们想知道如何改进我们的网站。我们也想知道为什么这么多人在Stack Overflow上发布这么糟糕的代码;就好像他们不能找到教程。这很难过,因为我们在这些教程中投入了大量的时间和金钱。(但如果没有人阅读它们,那有什么意义呢?)
您可以在Jump-Start tutorial和Building Blocks tutorial找到有关iText 7的更多信息。
至于将XML转换为PDF,为什么不首先转换为HTML,然后使用pdfHTML add-on?有关如何在chapter 4 HTML to PDF tutorial以及ZUGFeRD tutorial中执行此操作的示例。