I found here how I can override the print-out of the XML document to my Eclipse console so that it includes standalone = "no", but how do I write standalone = "no" to a file? I have tried writing the same document to a file, and it still will not print standalone = "no". In other words, when I try writing to a file, the overridden method does not work.
Is there some other method that I should override when writing to a file? What is the issue here?
private static void writeXML() {
try {
Document doc = new Document();
Element theRoot = new Element("tvshows");
doc.setRootElement(theRoot);
Element show = new Element("show");
Element name = new Element("name");
name.setAttribute("show_id", "show_001");
name.addContent(new Text("Life on Mars"));
Element network = new Element("network");
network.setAttribute("country", "US");
network.addContent(new Text("ABC"));
show.addContent(name);
show.addContent(network);
theRoot.addContent(show);
//-----------------------------
Element show2 = new Element("show");
Element name2 = new Element("name");
name2.setAttribute("show_id", "show_002");
name2.addContent(new Text("Life on Mars"));
Element network2 = new Element("network");
network2.setAttribute("country", "UK");
network2.addContent(new Text("BBC"));
show2.addContent(name2);
show2.addContent(network2);
theRoot.addContent(show2);
XMLOutputter xmlOutput = new XMLOutputter(Format.getPrettyFormat(), XMLOUTPUT);
//xmlOutput.output(doc, System.out);
xmlOutput.output(doc, new FileOutputStream(new File("./src/jdomMade.xml")));
System.out.println("The file has been written");
}
catch (Exception ex){
ex.printStackTrace();
}
}
public static final XMLOutputProcessor XMLOUTPUT = new AbstractXMLOutputProcessor() {
#Override
protected void printDeclaration(final Writer out, final FormatStack fstack) throws IOException {
write(out, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?> ");
write(out, fstack.getLineSeparator());
}
};
Your code lies ;-)
xmlOutput.output(doc, new FileOutputStream(new File("./src/jdomMade.xml")));
System.out.println("The file has been written");
The println says the file has been written, but it has not.
The File is only written when the file is flushed, and closed. You do not do that.
You should add a try-with-resources to your code:
try (FileOutputStream fos = new FileOutputStream(new File("./src/jdomMade.xml"))) {
xmlOutput.output(doc, fos);
}
System.out.println("The file has been written");
Related
im using iText to get content of a pdf like this :
try {
String parsedText="";
File file = new File(getApplicationContext().getFilesDir(), "test.pdf");
PdfReader reader = new PdfReader(String.valueOf(file));
int n = reader.getNumberOfPages();
for (int i = 0; i <n ; i++) {
parsedText = parsedText+ PdfTextExtractor.getTextFromPage(reader, i+1).trim()+"\n"; //Extracting the content from the different pages
}
reader.close();
} catch (Exception e) {
Log.d("heh", String.valueOf(e));
}
but it returns the error:
/data/user/0/com.clementine.story_project/files/test.pdf not found as file or resource.
what am i doing wrong?
PdfReader doesn't accept file object, but it accept InputStream. So you can use the below code
Path path = file.toPath();
if(Files.exists(path)) {
PdfReader reader = new PdfReader(Files.newInputStream(path));
//other operations
}
Also, added a file exists condition before calling the stream.
I was trying to generate 2 PDF data and put it inside a ZIP file for download (through response.getOutputStream) but I don't have idea how to do it properly:
public void export() {
String fileName = "B2B_Price_List.zip";
String fileNameUSD = "B2B_Price_List_USD.pdf";
String fileNameEU = "B2B_Price_List_EU.pdf";
String contentTypePDF = "application/pdf";
String[] headerPDF = new String[2];
headerPDF[0] = "Content-disposition";
headerPDF[1] = "attachment; filename=\"" + fileNameUSD + "\"";
headerPDF[2] = "attachment; filename=\"" + fileNameEU + "\"";
String contentTypeZIP = "application/zip";
String[] headerZIP = new String[1];
headerZIP[0] = "Content-disposition";
headerZIP[1] = "attachment; filename=\"" + fileName + "\"";
ByteArrayOutputStream outUSD = new ByteArrayOutputStream();
outUSD = CSVHandler.downloadPriceListPDF(outUSD, fileNameUSD, ListToPDFMap(productsUSD), true);
ByteArrayOutputStream outEU = new ByteArrayOutputStream();
outEU = CSVHandler.downloadPriceListPDF(outEU, fileNameEU, ListToPDFMap(productsEU), false);
// ZIP CODING GOES HERE
}
This function returns ByteArrayOutputStream to be used later:
public static ByteArrayOutputStream downloadPriceListPDF
(ByteArrayOutputStream output, final String filename,
Map<String, Map<String, List<B2BProductData>>> datas,
boolean amerCustomer) {
try {
PdfDocument pdfDoc = null;
try {
pdfDoc = new PdfDocument(new PdfWriter(output));
PageSize pageSize = new PageSize(PageSize.A4);
Document doc = new Document(pdfDoc, pageSize, false);
PdfCanvas canvas = new PdfCanvas(pdfDoc.addNewPage());
String coverImage = COVER_IMAGE;
if(!amerCustomer) {
coverImage = COVER_IMAGE_1;
}
canvas.addImage(ImageDataFactory.create(CSVHandler.class.getClassLoader().getResource(coverImage).getPath()), pageSize, false);
// loop thru category
int pageNo = 2;
Map<String, List<B2BProductData>> inputDatas = new LinkedHashMap<>();
for(String category : datas.keySet()) {
Map<String, List<B2BProductData>> prods = datas.get(category);
while(true) {
inputDatas = new LinkedHashMap<>();
Map<String, List<B2BProductData>> remaindatas = filterDatas(inputDatas, prods);
if(inputDatas.size() > 0) {
createPDFPage(pdfDoc, doc, category, inputDatas, pageNo ++, amerCustomer);
}
if(remaindatas.size() > 0) {
prods = remaindatas;
} else {
break;
}
}
}
doc.close();
return output;
} catch (IOException e) {
LOG.error(e.getMessage());
return output;
}
}
catch (final Exception ex) {
LOG.error("Export Products got error: " + ex.getMessage());
return output;
}
}
I made it like this:
Declared the Filenames to be used later.
String fileName = "B2B_Price_List.zip";
String fileNameUSD = "B2B_Price_List_USD.pdf";
String fileNameEU = "B2B_Price_List_EU.pdf";
Declare a new ByteArrawOutputStream class and initialize with "new".
ByteArrayOutputStream outUSD = new ByteArrayOutputStream();
ByteArrayOutputStream outEU = new ByteArrayOutputStream();
After generating a PDF file, return the value ByteArrayOutputStream and assign to the ByteArrayStream declared earlier.
if (hasUSD) outUSD = CSVHandler.generatePriceListPDF(outUSD, ListToPDFMap(productsUSD), true, true);
if (hasEU) outEU = CSVHandler.generatePriceListPDF(outEU, ListToPDFMap(productsEU), false, true);
Declare an outputstream to be used to hold response object's OutputStream.
OutputStream responseOutputStream;
Declare the header strings to be assigned to the response object's header data. In this case the MIME type would be application/zip for zip file. The fileName (B2B_Price_List.zip) is also used to define the download's filename.
String contentTypeZIP = "application/zip";
String[] headerZIP = new String[1];
headerZIP[0] = "Content-disposition";
headerZIP[1] = "attachment; filename=\"" + fileName + "\"";
Set the response object's headers.
response.setContentType(contentTypeZIP);
response.setHeader(headerZIP[0], headerZIP[1]);
Set the responseOutputStream to hold the response object's outputstream.
responseOutputStream = response.getOutputStream();
Declare a ZipOutputStream and initialize new with the response's outputstream as a parameter. The parameter will be used to write to write here the file to be downloaded later, in this case, the ZIP file.
ZipOutputStream zos = new ZipOutputStream(responseOutputStream);
Declare the ZipEntry objects to be put inside the ZIP file. Initialize new with the filename string as a parameter. In this case, we'll put 2 files inside the ZIP file for example.
ZipEntry zipEntryUSD = new ZipEntry(fileNameUSD);
ZipEntry zipEntryEU = new ZipEntry(fileNameEU);
Put each entries (or files) one at a time, after the putNextEntry is called for an entry, it is then assumed that the next .write called will be written to the previously put entry.
In this case we called the .write with the ByteArrayOutputStream.toByteArray() to convert to ByteArray as a parameter. Don't forget to close the entry by calling .closeEntry(), then proceed to the next file(s) with the same procedure earlier.
zos.putNextEntry(zipEntryUSD);
zos.write(outUSD.toByteArray());
zos.closeEntry();
zos.putNextEntry(zipEntryEU);
zos.write(outEU.toByteArray());
zos.closeEntry();
After writing the entries (files) you needed inside the ZIP, don't forget to close the ZipOutputStream (zos in this case).
zos.close();
The file will then proceed for download after you flush / close the response's output stream. You may ignore flush but to be sure, I included it anyway.
responseOutputStream.flush();
responseOutputStream.close();
END OF CODE BLOCK
CSVHandler.generatePriceListPDF
Now this is the function used to generate PDF > to > ByteArrayOutputStream. We passed the output object ByteArrayOutputStream from earlier to be re-assigned to the passed ByteArrayOutputStream object outside this function.
example:
outUSD = CSVHandler.generatePriceListPDF(outUSD, ListToPDFMap(productsUSD), true, true);
FUNCTION BLOCK START
public static ByteArrayOutputStream downloadPriceListPDF
(ByteArrayOutputStream output, final String filename,
Map<String, Map<String, List<B2BProductData>>> datas,
boolean amerCustomer, boolean autoCloseByteArrayOutputStream) {
try {
PdfDocument pdfDoc = null;
try {
Initialize writer as new PdfWriter with the ByteArrayOutputStream as a parameter, in this case the output object from the function parameter.
PdfWriter writer = new PdfWriter(output);
Initialize pdfDoc as new PdfDocument with the PdfWriter object writer in this case as parameter. This instructs the pdfDoc to write directly to the ByteArrayOutputStream (output) object
pdfDoc = new PdfDocument(writer);
Initialize PDF document parameters such as sizes and such.
PageSize pageSize = new PageSize(PageSize.A4);
Document doc = new Document(pdfDoc, pageSize, false);
PdfCanvas canvas = new PdfCanvas(pdfDoc.addNewPage());
This is the part where you write your PDF, with data, images or anything up to you.
// YOUR OWN PDF WRITE OPERATION HERE
Don't forget to close your PDF Document after you finish writing stuff.
doc.close();
The function parameter autoCloseByteArrayOutputStream boolean I added determines if you want to close the ByteArrayOutputStream inside this function, or close it outside if you want to supplement the content outside. Your choice, but don't forget to close ByteArrayOutputStream all the time anyway.
If (autoCloseByteArrayOutputStream) {
output.flush();
output.close();
}
Return the output ByteArrayOutputStream.
return output;
} catch (IOException e) {
If an exception occur, it's important to return an object on all code paths. In this case we return a null value ByteArrayOutputStream in an event of error.
LOG.error(e.getMessage());
return output;
}
}
catch (final Exception ex) {
Same here, errors return null ByteArrayOutputStream in case of error.
LOG.error("Export Products got error: " + ex.getMessage());
return output;
}
}
END OF FUNCTION BLOCK
I can create a PDF file with iText library in Java. This works, but now I have this problem, I execute the method, then I have a PDF file, its name is file.pdf and it is ok. Now I re-call the function to create the PDF file, its name is file.pdf but now, if the file is just open, I have an error.
FileNotFoundException:Impossible to access at file
And is ok this, so I want that if the file is open, from code, close the file then recreate the file and open it.
This is my code to create a PDF file:
public static void printFile(String nomeFolder, String nomeFile,List<Articoli> listaArticoli, boolean aprire)throws DocumentException{
String folderName = DateUtil.getDataGiornaliera();
nomeFolder = (new StringBuilder()).append(nomeFolder).append(nomeFile+"_"+folderName).append(".pdf").toString();
File f = new File(nomeFolder);
try {
OutputStream os = new FileOutputStream(f);
Document doc = new Document(PageSize.A4.rotate(), -65F, -65F, 85F, 40F);
PdfWriter docWriter = PdfWriter.getInstance(doc, os);
EndPageFoglioFatturaFatt hp2 = new EndPageFoglioFatturaFatt(nomeFolder, "Img/ineco1.jpg",folderName);
docWriter.setPageEvent(hp2);
FooterDocumenti hp = new FooterDocumenti(nomeFolder, "Img/ineco1.jpg",folderName);
docWriter.setPageEvent(hp);
doc.open();
float[] colonne = {0.7f,1.5f,4.5f,0.5f,0.5f,1.5f,1.5f,1.5f};
PdfPTable table = new PdfPTable(colonne);
table.setHeaderRows(1);
String[] intestazioni = {"C.ART","C.BARRE", "NOME ARTICOLO","IVA(%)", "Q.TA",
"PR.VENDITA", "ULT.PR.VENDITA", "ULT.DATA ACQUISTO"};
PdfPCell cell = new PdfPCell();
for(int i = 0; i< intestazioni.length; i++){
cell = new PdfPCell(new Paragraph(intestazioni[i], FontFactory.getFont("Century Gothic", 8F)));
cell.setGrayFill(0.9F);
cell.setUseAscender(true);
cell.setHorizontalAlignment(1);
cell.setVerticalAlignment(5);
cell.setBorderWidth(0.5F);
cell.setFixedHeight(15F);
table.addCell(cell);
}
//Vector v = db.eseguiQueryTuttiArticoli("SELECT ARTICOLIDETT.CodArticolo,NomeArticolo,Iva, Quantita,PrezzoAttuale, PrezzoRivenditore, PrezzoIngrosso, Soglia FROM Articolidett,Articoliquantita WHERE ARTICOLIDETT.CODARTICOLO = ARTICOLIQUANTITA.CODARTICOLO ORDER BY NOMEARTICOLO");
for (Articoli articoli : listaArticoli) {
cell = new PdfPCell(new Paragraph(articoli.getCodArticoloString(), FontFactory.getFont("Century Gothic", 10F)));
cell.setVerticalAlignment(5);
cell.setHorizontalAlignment(0);
cell.setColspan(0);
cell.setBorderWidth(0.5F);
table.addCell(cell);
....
....
CODE TO BUILD A FILE
.....
.....
}
doc.add(table);
doc.close();
os.close();
} catch (FileNotFoundException e) {
log.logStackTrace(e);
VisualMessageStampe.getErroreFileAperto();
}
catch(IOException exp)
{
log.logStackTrace(exp);
}
catch(DocumentException exp2)
{
log.logStackTrace(exp2);
}
if(aprire)
{
if(Desktop.isDesktopSupported())
{
try
{
Desktop.getDesktop().open(f.getCanonicalFile());
}
catch(IOException ex)
{
log.logStackTrace(ex);
}
} else
{
VisualMessageStampe.getErroreAcrobatInesistente();
}
}
}
How can I fixed my problem?
You cannot open an OutputStream into a file opened in external application (Adobe Reader or stuff). Some things you could do instead:
Create new filename for each iteration (creating tempfiles is cheap)
Check if file exists before you go and overwrite. If exists create a suffix (_1, _2, ...) and check that does not exist.
Alert user once you see that message to "please close PDF file before creating new"
Something like this might help:
protected File getFile(String nomeFile, String nomeFolder) {
String folderName = DateUtil.getDataGiornaliera();
nomeFolder = (new StringBuilder()).append(nomeFolder).append(nomeFile+"_"+folderName).append(".pdf").toString();
File f = new File(nomeFolder);
int suffix = 1;
while(f.exists()) {
nomeFolder = (new StringBuilder()).append(nomeFolder).append(nomeFile+"_"+folderName+"_"+(suffix++)).append(".pdf").toString();
f = new File(nomeFolder);
}
return f;
}
In the Java code below, I am creating a *.html report by transforming generated xml data that is stored in a string,
combinedDDIString
... against an XSLT file,
reportXSLT
... and writing the result to a physical file,
tmpReportHTML.
The code then reads the file back into a string to use in other methods. I would like to avoid having to write the results to a file, just transform the results directly into a string.
Is there any way I can write the transform results to a string directly, and avoid writing the results out to a physical file?
String reportString = null;
FileInputStream stream = null;
ByteArrayOutputStream reportBAOS = new ByteArrayOutputStream();
try {
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
transformerFactory = TransformerFactory.newInstance();
transformer = transformerFactory.newTransformer(new StreamSource(reportXSLT));
transformer.setOutputProperty(OutputKeys.ENCODING, "US-ASCII");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
/*
* Create a new report file time-stamped for uniqueness, to avoid concurrency issues
*/
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
File tmpReportHTML = new File(reportHTML + dateFormat.format(date) + ".html");
/*
* Perform the transform to get the report
*/
FileOutputStream reportFOS = new FileOutputStream(tmpReportHTML);
OutputStreamWriter osw = new OutputStreamWriter(reportFOS, "US-ASCII");//(reportBAOS), "US-ASCII");
transformer.transform(new StreamSource(new StringReader(combinedDDIString)), new StreamResult(osw));
osw.close();
/*
* Get the report as a string from the temp report file
*/
//FileInputStream stream = new FileInputStream(new File(REPORT_OUTPUT));
stream = new FileInputStream(tmpReportHTML); //(new File(reportXML));
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
reportString = Charset.defaultCharset().decode(bb).toString();
/*
* Delete the temp report file
*/
tmpReportHTML.delete();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
finally {
stream.close();
Thanks in advance for the help.
Try using a StringWriter to create the StreamResult. (You should be able to obtain a String from the StringWriter simply using the toString method.)
I have an object which holds data of a person. When a user clicks on the download button the xml needs to be created by (person.dataitems) and after that user should have an option to download the file (like save file or open file)
I have written the code below which creates a xml file when the button is clicked however the file remains empty. I would like to know how I can write data to this file and then download.
response.setHeader( "Content-Disposition", "attachment;filename="+patient.getGivenName()+".xml");
try {
StringWriter r = new StringWriter();
String ccdDoc = r.toString();
ccdDoc = ccdDoc.replaceAll("<", "<");
ccdDoc = ccdDoc.replaceAll(""", "\"");
byte[] res = ccdDoc.getBytes(Charset.forName("UTF-8"));
response.setCharacterEncoding("UTF-8");
response.getOutputStream().write(res);
response.flushBuffer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thanks.
You have to write into your StringWriter:
import java.io.*;
public class StringWriterDemo {
public static void main(String[] args) {
String s = "Hello World";
// create a new writer
StringWriter sw = new StringWriter();
// write portions of strings
sw.write(s, 0, 4);
sw.write(s, 5, 6);
// write full string
sw.write(s);
// print result by converting to string
System.out.println("" + sw.toString());
}
}
Do not do:
String ccdDoc = r.toString();
It only creates a copy of the r string. Then you are modifying the copy, but not at all the content of the StringWriter.
Do:
r.write("some content");
and to access the string contained by the writer, do:
String a_string = r.toString();
response.getOutputStream().write(a_string);
EDIT :
OK, so what you are asking is not so far from what you have in the link you provided, excepted that you have to write into a StringWriter instead of into a File.
This can be achieved this way:
1) Do build an xml document:
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
// staff elements
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
// set attribute to staff element
staff.setAttribute("id", "1");
// firstname elements
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
:
:
// Then write the doc into a StringWriter
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//initialize StreamResult with StringWriter object to save to string
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
String xmlString = result.getWriter().toString();
System.out.println(xmlString);
// Finally, send the response
byte[] res = xmlString.getBytes(Charset.forName("UTF-8"));
response.setCharacterEncoding("UTF-8");
response.getOutputStream().write(res);
response.flushBuffer();
The point here is to do:
StreamResult result = new StreamResult(new StringWriter());
instead of:
StreamResult result = new StreamResult(new File("C:\\file.xml"));
You tell me if there is still something unclear in this.
it's worked
byte[] res = xmlString.getBytes(Charset.forName("UTF-8"));
response.setCharacterEncoding("UTF-8");
response.setHeader( "Content-Disposition", "attachment;filename=archivo.xml");
response.getOutputStream().write(res);
response.flushBuffer();