i have multiple xml files named media01.xml, media02.xml and so on.
I have written one java code which parses this xml file and fetches its table name and renames xml file. eg: media01--> Records.xml, media02 --> Info.xml and so on.
Part of that code is as follows:
File inputFile = new File(path+File.separator+"media0"+xmlval+".xml");
if(inputFile.exists())
{
try{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
aaaa a= new aaaa();
saxParser.parse(inputFile, a);
String abc = aaaa.nsList();
File dest = new File(path+File.separator+abc+".xml");
inputFile.renameTo(dest);
xmlval++;
}
catch(Exception e)
{
System.err.println(""+e);
}
}
and the function which i am calling is:
class aaaa extends DefaultHandler {
boolean bFirstName = false;
boolean bLastName = false;
boolean loc = false;
String name = null;
static String ans;
#Override
public void startElement(String uri,String localName, String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("table")) {
name = attributes.getValue("name");
}
if(qName.equalsIgnoreCase("row")){
}
ans=name;
}
public static String nsList(){
return ans;
}
}
i deployed my project on server and when i run the project from ubuntu OS then the xml file names are getting changed but the same when i am running from windows then its not renaming the files. what might be the issue?
Pls help me out. Thanks in advance.
i don't thin it is a Parser problem since there is no problem and SAXParser is used by so many projects that depend on SAX to parse their configuration file such as Spring , jsf i think and so many others so it is unlikely to be a saxproblem so the problem can be i your call to
File dest = new File(path+File.separator+abc+".xml");
inputFile.renameTo(dest);
which is platform dependent instruction you better check if the renaming was done successfully by doing like this
File dest = new File(path+File.separator+abc+".xml");
boolean renameSuccess=inputFile.renameTo(dest);
System.out.println("renaming "+renameSuccess?"succeeded":"failed");
One of the problems I could encounter when deploying an application tested on a system to another system is that path and file names are case sensitive on Unix-like system. It is possible that your file already existed on your target system but with a different case. Anyway, as achabahe mentioned it, you should check your return value when you rename a file.
Another remark, path separators are system dependent but generally Java doesn't make any problem. You can for example use '/' in a Windows path. I just would suggest you to instantiate File objects this way:
File myFile = new File(myPath, myFileName);
This is so easier to read and system-independent.
I also suggest you to trace if you actually open the source file. By the way can't you run it in debug mode?
Related
I want to convert any file extension to .ttl (TURTLE) and I need to use Apache Jena, I am aware of how it can be accomplished using RDFJ4 but the output isn't as accurate as it is using Jena. I want to know how I can auto-detect the extension or rather file type if I am not aware of the extension when reading a file from a directory. This is my code when I hardcode the file-name, it works, I just need help in auto detecting the file type. My code is as follows:
public class Converter {
public static void main(String[] args) throws FileNotFoundException {
String fileName = "./abc.rdf";
Model model = ModelFactory.createDefaultModel();
//I know this is how it is done with RDF4J but I need to use Apache Jena.
/* RDFParser rdfParser = Rio.createParser(Rio.getWriterFormatForFileName(fileName).orElse(RDFFormat.RDFXML));
RDFWriter rdfWriter = Rio.createWriter(RDFFormat.TURTLE,
new FileOutputStream("./"+stripExtension(fileName)+".ttl"));*/
InputStream is = FileManager.get().open(fileName);
if (is != null) {
model.read(is, null, "RDF/XML");
model.write(new FileOutputStream("./converted.ttl"), "TURTLE");
} else {
System.err.println("cannot read " + fileName);
}
}
}
All help and advice will be highly appreciated.
There is functionality that handles reading from a file using the extension to determine the syntax:
RDFDataMgr.read(model, fileName);
It also handles compressed files e.g. "file.ttl.gz".
There is a registry of languages:
RDFLanguages.fileExtToLang(...)
RDFLanguages.filenameToLang(...)
For more control see RDFParser:
RDFParser.create().
source(FileName)
... many options including forcing the language ...
.parse(model);
https://jena.apache.org/documentation/io/rdf-input.html
I've made a class which takes in any string of one format (eg. UNIX) and coverts into whatever OS the java is running on.
enum OperatingSystem {
WINDOWS,
LINUX;
static OperatingSystem initOS() {
String osName = System.getProperty("os.name");
switch (osName) {
case "Windows 8.1":
return WINDOWS;
case "Linux":
return LINUX;
default:
return LINUX;
}
}
}
public class OSSP {
public static final OperatingSystem USEROS = OperatingSystem.initOS();
// Auxilarry methods to return OSAppropriateString
private static String makeLinuxCompatible(String[] path) {
return String.join("/", path);
}
private static String makeWindowsCompatible(String[] path) {
return String.join("\\", path);
}
public static String getOSSpecificPath(String path) {
String[] splittedPath = {""}, subpath = {""};
String finalPath = "";
if(path.contains("\\")) {
splittedPath = path.split("\\\\",-1);
}
else if (path.contains("/")) {
splittedPath = path.split("/",-1);
}
if (USEROS == OperatingSystem.LINUX) {
finalPath = makeLinuxCompatible(splittedPath);
}
else if (USEROS == OperatingSystem.WINDOWS) {
finalPath = makeWindowsCompatible(splittedPath);
}
return finalPath;
}
}
This is fine if you're working on small code and you'd have to do it often.
But, I have a huge GUI code where I'd have to insert this function wherever there is path specified in the program. Is there a way to make path like strings automatically OS specific?
Otherwise a setting where any OS function which takes a path automatically changes accordingly under the hood.
Use Path with Files.
Path path = Paths.get(".../...");
Path path = Paths.get("...", "...");
// path.resolve, relativize, normalize, getFileSystem
This class is a generalisation of File which is only for pure file system files.
A path might point in a subdirectory of a .zip using a zip file system and so on.
For established File using APIs one can use Path.toFile() and File.toPath().
Paths.get is very versatile, also due to the Posix compatibility of Windows (accepting / besides \). You can get a canonical normalized path anyway.
path.toRealPath()
The old File you can use:
String separator = File.separator;
For a path which can point to different file systems:
String separator = path.getFileSystem().getSeparator();
In general Path is a nifty class storing the name parts, the file system.
It covers many aspects like "..".
The best way to deal with this kind of situation is to not try to detect the OS since that can be rather hit-or-miss. Instead the Java API does provide a way to tell you what character to use as a path separator. Look at this API documentation on File: https://docs.oracle.com/javase/8/docs/api/java/io/File.html and look for the specific static field separator. I would highly suggest you parse the path using the File class then if you need the path as an string simply call toURI().toString() to get it into a format that the OS can recognize.
I want to read an XML file in Java and then update certain elements in that file with new values. My file is > 200mb and performance is important, so the DOM model cannot be used.
I feel that a StaX Parser is the solution, but there is no decent literature on using Java StaX to read and then write XML back to the same file.
(For reference I have been using the java tutorial and this helpful tutorial to get what I have so far)
I am using Java 7, but there doesn't seem to be any updates to the XML parsing API since...a long time ago. So this probably isn't relevant.
Currently I have this:
public static String readValueFromXML(final File xmlFile, final String value) throws FileNotFoundException, XMLStreamException
{
XMLEventReader reader = new XMLInputFactory.newFactory().createXMLEventReader(new FileReader(xmlFile));
String found = "";
boolean read = false;
while (reader.hasNext())
{
XMLEvent event = reader.nextEvent();
if (event.isStartElement() &&
event.asStartElement().getName().getLocalPart().equals(value))
{
read = true;
}
if (event.isCharacters() && read)
{
found = event.asCharacters().getData();
break;
}
}
return found;
}
which will read the XMLFile and return the value of the selected element. However, I have another method updateXMLFile(final File xmlFile, final String value) which I want to use in conjunction with this.
So my question is threefold:
Is there a StaX implementation for editing XML
Will XPath be any help? Can that be used without converting my file to a Document?
(More Generally) Why doesn't Java have a better XML API?
There are two things you may want to look at. The first is to use JAXB to bind the XML to POJOs which you can then have your way with and serialize the structure back to XML when needed.
The second is a JDBC driver for XML, there are several available for a fee, not sure if there are any open source ones or not. In my experience JAXB is the better choice. If the XML file is too large to handle efficiently with JAXB I think you need to look at using a database as a replacement for the XML file.
This is my approach, which reads events from the file using StaX and writes them to another file. The values are updated as the loop passes over the correctly named elements.
public void read(String key, String value)
{
try (FileReader fReader = new FileReader(inputFile); FileWriter fWriter = new FileWriter(outputFile))
{
XMLEventFactory factory = XMLEventFactory.newInstance();
XMLEventReader reader = XMLInputFactory.newFactory().createXMLEventReader(fReader);
XMLEventWriter writer = XMLOutputFactory.newFactory().createXMLEventWriter(fWriter);
while (reader.hasNext())
{
XMLEvent event = reader.nextEvent();
boolean update = false;
if (event.isStartElement() && event.asStartElement().getName().getLocalPart().equals(key))
{
update = true;
}
else if (event.isCharacters() && update)
{
Characters characters = factory.createCharacters(value);
event = characters;
update = false;
}
writer.add(event);
}
}
catch (XMLStreamException | FactoryConfigurationError | IOException e)
{
e.printStackTrace();
}
}
Obviously ResourceBundle requires a property file like syntax in the files it finds.
We have a situation where we want to use entire files (in our case HTML-files) as "values". This means that we don't have keys as such. Well, maybe the filename would work as the key.
Here's a directory tree:
src/
main/
resources/
html/
content.html
content_de.html
content_fr.html
content_es.html
order.html
order_de.html
order_fr.html
order_es.html
Now we need logic to find the correct file based on the current locale. If the current locale is German and I'm looking for html/content.html file, it should find html/content_de.html. It doesn't necessarily need to load it right away. Is there some existing mechanism in Java? Do we need to do this manually?
Due to some restrictions, we are currently planning to not use any third-party libraries. So if there is something available in Java 6 SE, it would be our best choice; however, if you know of a third-party library, feel free to name it.
EDIT #1:
An obvious solution would be to have a key in messages.properties to name that HTML-file. While that would work it may become a pain in the butt on the long run (and besides that I don't think this would solve all our issues with this).
EDIT #2: I forgot to say that this is a desktop application.
To make this more ideal, if your naming convention for your files remains consistent (i.e. for each locale, you use the two-letter prefix of the language - meaning 'en' for English, 'fr' for French, and 'es' for Spanish), then this process is extremely straightforward.
We will make use of the Properties class to read the properties in, then use MessageFormat to format the appropriate locale we want from the resultant property.
First, we make a change to the property file - we parameterize it such that we are able to pass in whatever we like.
content=content_{0}.html
order=order_{0}.html
The {0} represents the first parameter to the property.
Now, we only need to load the property in, and pass in the appropriate parameter.
Properties prop = new Properties();
try {
MessageFormat messageFormat = new MessageFormat("");
String property;
// change to suit the locale you wish to serve
String[] param = {"en"};
prop.load(new FileReader(new File("/full/path/to/property/file.properties")));
property = prop.getProperty("content");
messageFormat.applyPattern(property);
System.out.println(messageFormat.format(param));
} catch(IOException ioex) {
System.out.println("no property file here");
}
This prints out:
content_en.html
Ensure that the HTML file you want to access exists before making this call, or turn this into a function which returns String, and ensure that the file exists before it's returned.
To show that I wasn't doing nothing, here are two attempts using an "on our own"-approach:
The first attempt with locale-postfix build up and straight forward loading of resources:
public void attempt1(String baseName, String extension) {
List<String> locales = buildLocaleStrings(Locale.getDefault());
String resourceFound = null;
for (String locale : locales) {
String resourceName = baseName + locale + "." + extension;
URL resource = getClass().getClassLoader().getResource(resourceName);
if (resource != null) {
resourceFound = resourceName;
break;
}
}
System.out.println("found #1: " + resourceFound);
}
private List<String> buildLocaleStrings(Locale localeBase) {
String locale = "_" + localeBase;
List<String> locales = new ArrayList<String>();
while (locale.length() > 0) {
locales.add(locale);
locale = locale.replaceFirst("_[^_]*?$", "");
}
locales.add("");
return locales;
}
The second attempt "abusing" ResourceBundle and its toString():
public void attempt2(String baseName, final String extension) {
ResourceBundle.Control control = new ResourceBundle.Control() {
private String resourceFound = null;
#Override
public List<String> getFormats(String baseName) {
return Arrays.asList(extension);
}
#Override
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, format);
if (loader.getResource(resourceName) != null) {
resourceFound = resourceName;
return new ResourceBundle() {
#Override
public Enumeration<String> getKeys() {
return null;
}
#Override
protected Object handleGetObject(String key) {
return null;
}
};
}
return null;
}
#Override
public String toString() {
return resourceFound;
}
};
ResourceBundle.getBundle(baseName, control);
System.out.println("found #2: " + control.toString());
}
Sample calls:
public void proof() {
attempt1("html/content", "html");
attempt2("html/content", "html");
}
Both find the same file.
To be honest, I don't like neither.
I know this is an old question but I just came across the exact same problem and I found a more elegant solution. What you need is to delegate locale to file mapping to the standard Java API the same way the API solves translations for keys. So in your example, if the current locale is fr_FR you want to load the files called "content_fr.html" and "order_fr.html", right?
Then simply have a set of resource bundle files and designate a variable to translate the current locale to the closest existing locale:
File translation.properties:
localeCode =
File translation_fr.properties:
localeCode = fr
File translation_en.properties:
localeCode = en
Then you just need to read the value of "localeCode" and concatenate it with "content" and ".html" or "order" and ".html".
I want to be able to mock the File object in java using Mockery. I seems like we may not be able to create an interface for the File in java. Is this possible?
EDIT:
I need to test the indexDoc function in Indexer Class.
#Test
public void testindexDocs()
{
final File f = mockFile.mock(File.class);
File file = new File("test");
mockFile.setImposteriser(ClassImposteriser.INSTANCE);
final String[] files = {
"C:\\test\\",
"C:\\test\\test1.html",
"C:\\test\\test2",
"C:\\test\\test3.html"};
mockFile.checking(new Expectations(){
{
one(f).list();will(returnValue(files));
}
});
//TODO test if list() how many time i have called
//Document doc = HTMLDocument.Document(file); in function indexDocs
}
Index Docs function in Indexer class
private static void indexDocs(File file) throws Exception{
//Check for file to be a directory or file to be indexed look for html files and add to document
if(file.isDirectory()){
String[] files = file.list();
Arrays.sort(files);
for (int i = 0; i < files.length; i++) // recursively index them
indexDocs(new File(file, files[i]));
} else if(file.getPath().endsWith(".html") || file.getPath().endsWith("htm")){
// Get the document from HTMLDocument class which takes care of stripping of HTML tag, get the path
// of HTML file and title of HTML document.
Document doc = HTMLDocument.Document(file);
// TODO Get the book of HTML, it can be a part of HTML document class.
writer.addDocument(doc);
}
}
Don't mock the file system. We tried to do this in the early days and it diverted us from using tests to guide the design.
From a quick look at your code, there are two things going on, one is file navigation, the other is html stripping. Perhaps one option would be to introduce a html stripping object (passed in as a collaborator) and mock that, then write tests against examples in a real file system.
Jmock can mock concrete classes. Just do
Mockery context = new Mockery();
context.setImposteriser(ClassImposteriser.INSTANCE);
The problems your having are the exact reason, one should use abstractions rather than concrete classes.