java.io.FileNotFoundException: open failed: EROFS (Read-only file system) - java

I have this code that generates an XML file and saves to an external directory.
try //database structure
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//test report elements, does not reflect the real database in the future
//mandatory/ username, location, caption, media, time(Actually, it's best if the server determines recieve time)
//optional/
//reportdata elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("reportdata");
doc.appendChild(rootElement);
//username elements
Element username = doc.createElement("username");
username.appendChild(doc.createTextNode("testusername"));
rootElement.appendChild(username);
//Location ELEMENTS
//latitude elements
Element lat = doc.createElement("latitude");
lat.appendChild(doc.createTextNode(String.valueOf(latitude)));
rootElement.appendChild(lat);
//longitude
Element longi = doc.createElement("longitude");
longi.appendChild(doc.createTextNode(String.valueOf(longitude)));
rootElement.appendChild(longi);
//caption text elements
Element capt = doc.createElement("caption");
capt.appendChild(doc.createTextNode(captionText.getText().toString()));
rootElement.appendChild(capt);
//tag elements
String[] tagArr = new String[selectItems.size()];
tagArr = selectItems.toArray(tagArr);
Element tags = doc.createElement("tags");
rootElement.appendChild(tags);
int o = selectItems.size();
for(String s: tagArr) {
Element tagname = doc.createElement("tagname");
tagname.appendChild(doc.createTextNode(s));
tags.appendChild(tagname);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
//StreamResult result = new StreamResult(System.out);
StreamResult result = new StreamResult(new File(android.os.Environment.getRootDirectory(), "upload_data.xml"));
transformer.transform(source, result);
Log.d("MESSAGE", result.toString());
After the creation of the XML file, this exception was raised
D/XML TransformerException﹕ java.io.FileNotFoundException: /system/upload_data.xml: open failed: EROFS (Read-only file system)
Any way to fix this?

... saves to an external directory
This is not quite right. You are trying to save it in the root system partition which is always read-only.
From javadoc of Environment.getRootDirectory():
Return root of the "system" partition holding the core Android OS. Always present and mounted read-only.
Solution : just save your file somewhere else :
StreamResult result = new StreamResult(new File(android.os.Environment.getExternalStorageDirectory(), "upload_data.xml"));
Note that :
you must ask the permission to write to the external storage :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
External storage is not always available. The partition may not be mounted -yet- when you try to write on it. (just be careful)

Related

Adding element to XML using javax parser without document modification

i am trying to add elements to xml document. Elements are added successfuly but problem is, that parser modifies original xml file in other places e.g it swaps namespace and id attributes or deletes duplicate namespace definitions. I need to get precisely the same document (same syntax, preserved whitespaces) only with specific elements added. I would greatly appreciate any suggestions. Here is my code:
public void appendTimestamp(String timestamp, String signedXMLFile, String timestampedXMLFile){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try{
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(signedXMLFile));
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList list = (NodeList)xPath.evaluate("//*[local-name()='Signature']/*[local-name()='Object']/*[local-name()='QualifyingProperties']", doc, XPathConstants.NODESET);
if(list.getLength() != 1){
throw new Exception();
}
Node node = list.item(0);
Node unsignedProps = doc.createElement("xades:UnsignedProperties");
Node unsignedSignatureProps = doc.createElement("xzep:UnsignedSignatureProperties");
Node timestampNode = doc.createElement("xzep:SignatureTimeStamp");
timestampNode.appendChild(doc.createTextNode(timestamp));
unsignedSignatureProps.appendChild(timestampNode);
unsignedProps.appendChild(unsignedSignatureProps);
node.appendChild(unsignedProps);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
DOMSource source = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult stringWriter = new StreamResult(writer);
transformer.transform(source, stringWriter);
writer.flush();
System.out.println(writer.toString());
}catch(Exception e){
e.printStackTrace();
}
}
The original xml file:
...
<ds:Object Id="objectIdVerificationObject" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
Modified xml file:
...
<ds:Object xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="objectIdVerificationObject">
...
If you use the dom model, then the whole xml file is read, then represented in the memory as the node tree and then saved to xml in a way determined by the writer. So it is almost impossible to preserve the original xml format as you don't have the control over it and for example whitespaces are not represented at all in the node tree.
You need to read partially the original xml and ouptut its content to the new file preserving what was read, then in the "right" place you need to add your new content adn then continue simple coapying of the original.
For example you could use the XMLStreamWriter and XMLStreamReader to achieve that as they offer "the low" level operations.
But probably it would be much easier to just copy the xml as the text line by one till you recognize the insertion point, then create new xml portion and append it as text and continue with copying.

create and write file from XML

I have XML about article
<ARTICLE ID="74">
<ARTICLE_CATEGORY_ID>1</ARTICLE_CATEGORY_ID >
<ARTICLE_NAME>......</ARTICLE_NAME >
<ARTICLE_EXTENSION>pdf</ARTICLE_EXTENSION >
<ARTICLE_BYTE>[B#6d78f375</ARTICLE_BYTE >
<ARTICLE_DATE>2014-10-11 00:00:00.0</ARTICLE_DATE >
<ARTICLE_ACTIVE>1</ARTICLE_ACTIVE>
</MAKALE>
i want to create file ,and write ARTICLE_BYTE but i can't do it ,it seems, byte seems is String i quess so i don't know how can i do this ? Thank you for helping
//EDIT
Sorry i'm very new stackoverflow..
yes this is from a program that i've written.
That's part of code from the program
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// XML Kok Ismi
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("ARTICLES");
doc.appendChild(rootElement);
for (Nesne nesne : userList) {
// ARTICLE ELEMENT
Element ARTICLE_ID= doc.createElement("ARTICLE ");
rootElement.appendChild(ARTICLE_ID);
//ID
Attr attr = doc.createAttribute("ID");
attr.setValue(String.valueOf(nesne.getArticleID()));
MAKALE_ID.setAttributeNode(attr);
//ARTICLE_CATEGORY_ID
Element ARTICLE_CATEGORY_ID= doc.createElement("ARTICLE_CATEGORY_ID");
ARTICLE_CATEGORY_ID.appendChild(doc.createTextNode(String.valueOf(nesne.getARTICLE_CATEGORY_ID())));
ARTICLE_ID.appendChild(ARTICLE_CATEGORY_ID);
//[ARTICLE_NAME]
Element ARTICLE_NAME= doc.createElement("ARTICLE_NAME");
ARTICLE_NAME.appendChild(doc.createTextNode(nesne.getARTICLE_NAME()));
ARTICLE_ID.appendChild(ARTICLE_NAME);
//[ARTICLE_EXTENSION]
Element ARTICLE_EXTENSION= doc.createElement("ARTICLE_EXTENSION");
ARTICLE_EXTENSION.appendChild(doc.createTextNode(nesne.getARTICLE_EXTENSION()));
ARTICLE_ID.appendChild(ARTICLE_EXTENSION);
//[ARTICLE_BYTE]
Element ARTICLE_BYTE= doc.createElement("ARTICLE_BYTE");
ARTICLE_BYTE.appendChild(doc.createTextNode(nesne.getARTICLE_BYTE().toString()));
ARTICLE_ID.appendChild(ARTICLE_BYTE);
//[ARTICLE_DATE]
Element ARTICLE_DATE = doc.createElement("ARTICLE_DATE");
ARTICLE_DATE.appendChild(doc.createTextNode(nesne.getARTICLE_DATE()));
ARTICLE_ID.appendChild(ARTICLE_DATE);
//[ARTICLE_ACTIVE]
Element ARTICLE_ACTIVE= doc.createElement("ARTICLE_ACTIVE");
ARTICLE_ACTIVE.appendChild(doc.createTextNode(String.valueOf(nesne.getArticleActive())));
ARTICLE_ID.appendChild(ARTICLE_ACTIVE);
}
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("dosyalar.xml"));
// Output to console for testing
// StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
System.out.println("File saved!");
Your problem appears to be here:
nesne.getARTICLE_BYTE().toString()
I'm not familiar with your Nesne class, but I can tell that the method, getARTICLE_BYTE() returns a byte array, that calling toString() on it will return the useless information that you're currently seeing, and that if this needs to be stored, then you somehow need to store the entire array. Using a for loop and storing the array as the String representations of each byte would not be the most efficient thing to do and would lead to a super-large unreadable XML, so perhaps you could store it off of the XML and pass a reference to the byte array file in the XML. Or store in a database as a BLOB. Note that this is not something I do much of, and so I'm no expert.

Save XML to a relative file location.

I have a writeScore.class which is doing the following:
Get URL and than InputStream of a relative file score.xml
Start building new xml document by parsing through existing one
Append new record to the document builder
The last thing the program does should be to write the new document in a place of the old one. Sadly I can't find any way to use the relative path I already have. I've tried to use the use URLConnection and than .getOutputStream, but I get the protocol doesn't support output error. I also gave a try to OIUtils.copy(is, os) to convert InputStream into OutputStream but although there are no errors, for some reason the file doesn't change and the last modification date points to the last time I did it with direct file address. (I did a system wide search in case new file was created somewhere else, found nothing).
Here is simplified code using the URLConnection method:
public class writeScore {
public writeScore(Score NewScore, Interface obj) {
try {
// prepare file path
URL scoreUrl = new URL("file","localhost","save/score.xml");
InputStream is = scoreUrl.openStream();
final URLConnection scoreCon = scoreUrl.openConnection();
final OutputStream os = scoreCon.getOutputStream();
// build the document
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(is);
// root element
Element root = doc.getDocumentElement();
Element rootElement = doc.getDocumentElement();
// add new save
/* removed for code cleaning */
// save source
DOMSource source = new DOMSource(doc);
// set up the transformer
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// add properties of the output file
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
// save the file
StreamResult result = new StreamResult(os);
transformer.transform(source, result);
} // and catch all the exceptions
}
}
If need be I'm happy to change the way I input the file as well, as long I can have a relative path from Java/bin/game/writeScore.class to Java/save/score.xml where 'Java' is my project directory. But also once the game is package into a .jar and save is a folder outside of that jar.
Just use new File("name") that creates a file in the current working directory. With new File("../name") you create a file in the parent directory. You then need to wrap the file in a FileOutputStream.
But I would consinder using JAXB.unmarshal(file, clazz) for reading and JAXB.marshal(object, file) for writing. Just delete the old file before you write the new one. I never had troubles with updating resp. overwriting.
Here is how I did it, I removed the exception handling and logging. Pretty concise and generic, too.
public static <T> void writeXml(T obj, File f)
{
JAXB.marshal(obj, f);
}

Writing XML in Java FileNotFoundException

i am facing some problem for this following codes
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("subcompany");
doc.appendChild(rootElement);
//id elements
Element id = doc.createElement("id");
id.appendChild(doc.createTextNode(subCompanyId != null ? subCompanyId : " "));
rootElement.appendChild(id);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
String xmlPath = "/project/MallDirectory/mall";
//EDITED for File creation before writing.
boolean isFileCreated = new File(xmlPath, "subcompany.xml").createNewFile();
System.out.println(isFileCreated);
StreamResult result = new StreamResult(new File(xmlPath, "subcompany.xml"));
transformer.transform(source, result);
} catch (Exception ex) {
ex.printStackTrace();
}
After i run, i get this following error:
javax.xml.transform.TransformerException: java.io.FileNotFoundException: file:/project/MallDirectory/mall/subcompany.xml (No such file or directory)
It used to work on my other project, however not this time round. What exactly went wrong here ?
EDITED:
Here is the path that i am trying to write into. The file is created, but it is empty.
I managed to solve the problem.
Here is the Error:
javax.xml.transform.TransformerException: java.io.FileNotFoundException: file:/project/MallDirectory/mall/subcompany.xml (No such file or directory)
I am thinking maybe the transformer is trying to write the xml to this path 'file:/project/MallDirectory/mall/subcompany.xml'. I don't know how it happened, as i have specifically set the file path '/project/MallDirectory/mall/subcompany.xml', and does not prefixed with 'file:/'.
Therefore, i somehow managed to fix it by doing this:
...
//ERROR CODE:
//StreamResult result = new StreamResult(new File(xmlPath, "subcompany.xml"));
//
StreamResult result = new StreamResult(new File(xmlPath, "subcompany.xml").getPath());
transformer.transform(source, result);
...
The number of files that can be in open state at any point of time is specific to the OS (offcourse ,Can be configured) and you have reached the upper limit of that.Look in the code base of your application ,whehter you have some code that is trying to open a file but not closing the stream after its use.Check for such codes.
The directory path you have defined is incorrect. Take a look at the JavaDoc to determine which form of the directory path you need to get to your file location.
JavaDoc java.io.File
If "/project" is your project name then try "./MallDirectory/mall" else try "./project/MallDirectory/mall". Please observe the string carefully it contains dot in it.

How can I parse an XML file stored in blobstore on Google App Engine?

I need to parse an XML file stored in the blobstore. How do I do that?
This is what I have done till now:
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = fileService.getBlobFile(new BlobKey(key));
I cannot parse the XML file using javax.xml package or can I? The classes in that package if put into action requires a reference of a java.io.File object. But I do not have that.
This is what I have been doing till now : (not on the server but locally)
File blobKeys = new File("/home/non-admin/NetBeansProjects/Personal Site_Testers/web/xml/xml_1.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(blobKeys);
Element root = doc.getDocumentElement();
Element firstName = doc.createElement("first-name");
firstName.setTextContent(name);
root.appendChild(firstName);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("/home/non-admin/NetBeansProjects/Personal Site_Testers/web/xml/xml_1.xml"));
transformer.transform(source, result);
Note : There are 3 xml files uploaded to the blobstore. Those xml files just have a root tag . I want to get the xml reference and parse them to append child node several times depending upon the request made.
If you want to parse *.xml, I think jdom2 may be is more convenient which I use in the app engine and it works.
However, you can read the FileService API document and there is an example with how to read and write the file. If you can get a InputStream or Reader, then you can use javax.xml to parse the xml content in the InputStream or Reader.
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile readableFile = new AppEngineFile("your_file_name");
FileReadChannel readChannel = fileService.openReadChannel(readableFile,
false);
InputStream input = Channels.newInputStream(readChannel);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(input);
Element root = doc.getDocumentElement();
Element firstName = doc.createElement("first-name");
firstName.setTextContent("content");
root.appendChild(firstName);
// Now write
GSFileOptionsBuilder optionsBuilder = new GSFileOptionsBuilder()
.setBucket("mybucket").setKey("myfile")
.setMimeType("text/html").setAcl("public_read")
.addUserMetadata("myfield1", "my field value"); // change as
// your need
AppEngineFile writableFile = fileService.createNewGSFile(optionsBuilder
.build());
FileWriteChannel writeChannel = fileService.openWriteChannel(
writableFile, false);
OutputStream output = Channels.newOutputStream(writeChannel);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(output);
transformer.transform(source, result);

Categories

Resources