I am having trouble using Apache commons configuration to read an ini file. I attached the imports incase I am missing something. Below is an example I found on stackoverflow, and as far as I can find, there are no other examples to look at. The problem is iniObj. Using Eclipse it is highlighted in red.
If I initialize the variable, new "HierarchicalINIConfiguration(iniFile); gets angry and wants to add a try/catch or throws... which should be no problem... but then the try/catch or throws gets angry and says "No exception of type ConfigurationException can be thrown; an exception type must be a subclass of Throwable."
Which then brought me to this question. I added the commons lang 3.1. I have commons config 1.9, commons collections 3.2.1. commons logging 1.1.1 as well. I have also tried this with commons config 1.8 and lang 2.6. Now I get a new error "Exception in thread "main" java.lang.NullPointerException at com.toolbox.dev.ReadIni.main(ReadIni.java:28)" You can see the new code below after the adjustments I made to try and resolve the errors.
My code:
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
public static void main(String[] args) throws ConfigurationException {
String iniFile = "file.ini";
HierarchicalINIConfiguration iniConfObj = new HierarchicalINIConfiguration(iniFile);
// Get Section names in ini file
Set setOfSections = iniConfObj.getSections();
Iterator sectionNames = setOfSections.iterator();
while(sectionNames.hasNext()) {
String sectionName = sectionNames.next().toString();
HierarchicalINIConfiguration iniObj = null;
SubnodeConfiguration sObj = iniObj.getSection(sectionName);
Iterator it1 = sObj.getKeys();
while (it1.hasNext()) {
// Get element
Object key = it1.next();
System.out.print("Key " + key.toString() + " Value " +
sObj.getString(key.toString()) + "\n");
}
}
}
Original code from Stack Overflow:
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
public class ReadIni {
public static void main(String[] args) {
String iniFile = "";
HierarchicalINIConfiguration iniConfObj = new HierarchicalINIConfiguration(iniFile);
// Get Section names in ini file
Set setOfSections = iniConfObj.getSections();
Iterator sectionNames = setOfSections.iterator();
while(sectionNames.hasNext()) {
String sectionName = sectionNames.next().toString();
SubnodeConfiguration sObj = iniObj.getSection(sectionName);
Iterator it1 = sObj.getKeys();
while (it1.hasNext()) {
// Get element
Object key = it1.next();
System.out.print("Key " + key.toString() + " Value " +
sObj.getString(key.toString()) + "\n");
}
}
Since you have already initialized the HierarchicalINIConfiguration (second line in "main") as :
HierarchicalINIConfiguration iniConfObj = new HierarchicalINIConfiguration(iniFile);
I believe you want to remove HierarchicalINIConfiguration iniObj = null; (around 5 lines down) from your code and change
SubnodeConfiguration sObj = iniObj.getSection(sectionName);
to (use iniConfObj in place of iniObj)
SubnodeConfiguration sObj = iniConfObj.getSection(sectionName);
This doesn't look promising ?
HierarchicalINIConfiguration iniObj = null;
SubnodeConfiguration sObj = iniObj.getSection(sectionName);
Is this line 28 ?
You could try JINIFile. Is a translation of the TIniFile from Delphi, but for java. It fully supports all the INI file features
https://github.com/SubZane/JIniFile
Related
Below is the concerned code. Basically what the code is supposed to do is output the URL, name and version of each GitHub release defined by GetUpdateInfo.getInfo().
GetUpdateInfo.getInfo (NOTE Strings login, oauth and password omitted for security reasons.):
import java.util.List;
import org.kohsuke.github.*;
import org.apache.commons.lang3.ArrayUtils;
public class GetUpdateInfo {
public static getInfo() {
String version = "";
String url = "";
String[] urls = {};
String[] names = {};
String[] versions = {};
String[] releases = {};
GitHub github = GitHubBuilder.fromEnvironment(login, password, oauth).build();
//Get the repo name from the organization
GHOrganization gho = github.getOrganization("NuovoLauncher-Mods");
PagedIterable<GHRepository> repos = gho.listRepositories();
List<GHRepository> repos_list = repos.asList();
for(int i=0; i < repos_list.size(); i++) {
GHRepository repo_test = repos_list.get(i);
GHRelease latest = repo_test.getLatestRelease();
ArrayUtils.add(releases, latest.toString());
ArrayUtils.add(names, latest.getName());
ui.setName(names);
ui.setRelease(releases);
List<GHAsset> assets = latest.getAssets();
for( int x = 0; x < assets.size(); x++ ) {
GHAsset asset = assets.get(x);
url = asset.getBrowserDownloadUrl();
version = url.split("/")[7];
System.out.format("URL: %s, Name: %s, Latest Release: %s. Version %s\n", url, latest.getName(), latest, version);
ArrayUtils.add(urls, url);
ArrayUtils.add(versions, version);
ui.setURL(urls);
ui.setVersion(versions);
}
}
return ui;
}
public static void main(String[] args) throws Exception {
GetUpdateInfo.getInfo();
}
}
DownloadUpdate.runner:
public static void runner() throws Exception {
String system_type = System.getProperty("os.name");
File fpath = new File("");
UpdateInfo ui = GetUpdateInfo.getInfo();
for(int i = 0; i < ui.getName().length; i++) {
System.out.format("URL: %s, Name %s, Version, %s", ui.getURL()[i], ui.getName()[i], ui.getVersion()[i]);
System.out.format("Downloading %s-%s", ui.getName()[i], ui.getVersion()[i]);
System.out.print("\n");
if(system_type.equals("Linux")) {
fpath = new File(System.getProperty("user.home") + "/.minecraft/mods/" + ui.getName()[i] + "-" + ui.getVersion()[i] + ".jar");
} else if(system_type.equals("Windows")) {
fpath = new File(System.getProperty("user.home") + "/AppData/Roaming/.minecraft/mods" + ui.getName()[i] + "-" + ui.getVersion()[i] + ".jar");
} else {
fpath = new File(System.getProperty("user.home") + "/.minecraft/mods/" + ui.getName()[i] + "-" + ui.getVersion()[i] + ".jar");
}
String url = ui.getURL()[i];
FileUtils.copyURLToFile(new URL(url), fpath);
}
}
public static void main(String[] args) throws Exception {
System.out.println("DEBUG START");
DownloadUpdate.runner();
}
}
Looking at the code, I cannot see a reason why the code is not outputting like expected; I am getting zero output on console, simply the line stating that the code is being executed. No exceptions either.
EDIT: variable ui is not being returned properly. For example, ui.getName[0] throws an ArrayIndexOutOfBoundsException, due to the length being zero. Seeing this, I now understand why the for loop isn't behaving as expected. Is this a scope issue? What am I missing here?
An obvious problem of your code is the use of ArrayUtils.add: you have to reassign its result to the input array, as you cannot modify arrays like lists in Java.
Use it like this:
releases = ArrayUtils.add(releases, latest.toString());
names = ArrayUtils.add(names, latest.getName());
and later in the for-loop:
urls = ArrayUtils.add(urls, url);
versions = ArrayUtils.add(versions, version);
Also you don't need to set the elements in each loop cycle to the result:
ui.setURL(urls);
ui.setVersion(versions);
Those would be sufficient once the for-loop has completed.
An alternative would be to first use List<String> instead of the arrays. If you have control over the UpdateInfo class, change it there to be lists too, otherwise create an array from the lists before you set it in UpdateInfo.
As a general advice I would recommend that you get rid of your static methods. Create instances and use your credentials (login, password, oauth) as member fields OR pass in even the whole GitHub instance. This way you would have an easier time writing proper tests.
I would like to process CSV file of such structure:
header1,header2
val1.1, val1.2
val2.1, val2.2
But only if the first line contains both header names - otherwise throw an exception.
My current implementations using Apache Common CSV is:
Reader reader = new InputStreamReader(new ByteArrayInputStream(file.getContent()));
CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
.withHeader("header1", "header2")
.withSkipHeaderRecord());
for (CSVRecord csvRecord : csvParser) { /* records processing */ }
The problem is that the first line might have values different than header names and the file is still processed.
Referring to the Java Doc of CSVFormat:
Referencing columns safely
If your source contains a header record, you can simplify your code and safely reference columns, by using withHeader(String...) with no arguments:
CSVFormat.EXCEL.withHeader();
This causes the parser to read the first record and use its values as column names. Then, call one of the CSVRecord get method that takes a String column name argument:
String value = record.get("Col1");
This makes your code impervious to changes in column order in the CSV file.
So you can just follow this and use first line as header, then validate headers CSVParser#getHeaderNames.
Following is a simple demonstration:
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
public class UseFirstRowAsHeader {
public static void main(String[] args) throws IOException {
String validHeaderCsv = "header1,header2\r\n"
+ "val1.1,val1.2\r\n"
+ "val2.1,val2.2";
parseWithHeaderValidation(validHeaderCsv);
String invalidHeaderCsv = "header1,header2,header3\r\n"
+ "val1.1,val1.2\r\n"
+ "val2.1,val2.2";
parseWithHeaderValidation(invalidHeaderCsv);
}
private static void parseWithHeaderValidation(String validHeaderCsv) throws IOException {
Reader reader = new StringReader(validHeaderCsv);
List<String> expectedHeaders = new ArrayList<String>();
expectedHeaders.add("header1");
expectedHeaders.add("header2");
try (CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
.withHeader().withAllowMissingColumnNames(false)
.withSkipHeaderRecord())) {
if (!csvParser.getHeaderNames().equals(expectedHeaders)) {
throw new IllegalStateException("Not expected headers" + csvParser.getHeaderNames());
}
for (CSVRecord csvRecord : csvParser) {
System.out.println(csvRecord.get("header1") + "," + csvRecord.get("header2"));
}
}
}
}
I want to do some work with weka in java. I've added the weka-src.jar and the weka-dev-3.7.10 jar in the java build path and my code doesn't show any error before running it. After I run the code it gives me the following error
Error: Unable to initialize main class selection.ClustererExecution
Caused by: java.lang.NoClassDefFoundError: weka/filters/Filter
Here is my code:
package selection;
import weka.clusterers.ClusterEvaluation;
import weka.clusterers.SimpleKMeans;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
import weka.filters.*;
import weka.filters.unsupervised.attribute.Remove;
public class ClustererExecution {
public static void main(String[] args) {
try {
//Loading data
Instances data = DataSource.read("/Data_Cortex_Nuclear.arff");
System.out.println("The number of attributes is: " + data.numAttributes() + " while the number of instances is: " + data.numInstances());
data.setClassIndex(data.numAttributes()-1);
System.out.println("The class index is: " + data.classIndex());
//Create copy without class attribute
Remove rem = new Remove();
rem.setAttributeIndices("" + (data.classIndex() + 1));
rem.setInputFormat(data);
Instances dataClusterer = Filter.useFilter(data, rem);
//Build clusterer
SimpleKMeans clusterer = new SimpleKMeans();
clusterer.setMaxIterations(100);
clusterer.setNumClusters(8);
clusterer.buildClusterer(dataClusterer);
//Evaluate clusterer with original data
ClusterEvaluation eval = new ClusterEvaluation();
eval.setClusterer(clusterer);
eval.evaluateClusterer(data);
System.out.println(eval.clusterResultsToString());
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Does anyone know how to fix the error?I am using eclipse if that makes any difference. Thank you!
As said in the comments below by Zastai, you added the weka jars to the build path, but the relevant weka jar needs to be in the classpath as well.
I have a problem. I wrote this code that reads a string from a txt file and I exported with the first method a int while the second one particular string. This method is already running but I have used the apache library, now I wanted to rewrite it in Java standard libraries. I have tried this, but I have had problems. Could someone help me? Thank you very much.
package ausiliare;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.*;
public class Read {
public static int getInt() throws IOException {
String content = null;
File folder = new File("C:\\Solution.txt");
content = FileUtils.readFileToString(folder) + "\n";
int outside = Integer.parseInt(content.substring(0,
content.indexOf("[")).trim());
return outside;
}
public static String getString() throws IOException {
String content = null;
File folder = new File("C:\\Solution.txt");
content = FileUtils.readFileToString(folder) + "\n";
String remainingString = content.substring(content.indexOf(" ["),
content.lastIndexOf("]") + 1);
// System.out.println(remainingString);
return remainingString;
}
public static String[] arg() throws IOException {
String[] strArray = getString().split(" ");
// System.out.println(Arrays.toString(strArray));
return strArray;
}
}
Ps: The input file is txt (for example):
50 [8,24,-22] [-8,34,12] [19,14,47] [-49,32,44] [-41,16,-6] [-49,-11,43]
Where the first method extracts the int 50 and the second extraction method extracts the remaining
content = new String(Files.readAllBytes(folder.toPath()),
StandardCharsets.UTF_8);
The missing part is the knowledge of the Files class.
There is a List<String> readAllLines too.
The character set parameter is optional and defaults to the current operating system's encoding - not very portable to other computers.
Java: 1.6
Woodstox: 4.1.4
I just want to skip part of xml file, while parsing.
Let's look at that simple xml:
<family>
<mom>
<data height="160"/>
</mom>
<dad>
<data height="175"/>
</dad>
</family>
I just want do skip dad element. So it look's like using skipElement method like shown below is a good idea:
FileInputStream fis = ...;
XMLStreamReader2 xmlsr = (XMLStreamReader2) xmlif.createXMLStreamReader(fis);
String currentElementName = null;
while(xmlsr.hasNext()){
int eventType = xmlsr.next();
switch(eventType){
case (XMLEvent2.START_ELEMENT):
currentElementName = xmlsr.getName().toString();
if("dad".equals(currentElementName) == true){
logger.info("isStartElement: " + xmlsr.isStartElement());
logger.info("Element BEGIN: " + currentElementName);
xmlsr.skipElement();
}
...
}
}
We just find start of element dad, and skip it. But not so fast, because Exception will be thrown. This is the output:
isStartElement: true
Element BEGIN: dad
Exception in thread "main" java.lang.IllegalStateException: Current state not START_ELEMENT
That is not what expected. This is indeed very unexpected, because method skipElement is executed in START_ELEMENT state. What is going on?
I tried this in java 1.6 (jdk1.6.0_30) with woodstox-core-lgpl-4.1.4.jar, stax2-api-3.1.1.jar on the library path.
My java file is this:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.evt.XMLEvent2;
public class Skip {
public static void main(String[] args) throws FileNotFoundException,
XMLStreamException {
System.setProperty("javax.xml.stream.XMLInputFactory",
"com.ctc.wstx.stax.WstxInputFactory");
System.setProperty("javax.xml.stream.XMLOutputFactory",
"com.ctc.wstx.stax.WstxOutputFactory");
System.setProperty("javax.xml.stream.XMLEventFactory",
"com.ctc.wstx.stax.WstxEventFactory");
FileInputStream fis = new FileInputStream(new File("family.xml"));
XMLInputFactory xmlif = XMLInputFactory.newFactory();
XMLStreamReader2 xmlsr = (XMLStreamReader2) xmlif
.createXMLStreamReader(fis);
String currentElementName = null;
while (xmlsr.hasNext()) {
int eventType = xmlsr.next();
switch (eventType) {
case (XMLEvent2.START_ELEMENT):
currentElementName = xmlsr.getName().toString();
if ("dad".equals(currentElementName) == true) {
System.out.println("isStartElement: "
+ xmlsr.isStartElement());
System.out.println("Element BEGIN: " + currentElementName);
xmlsr.skipElement();
}
else {
System.out.println(currentElementName);
}
}
}
}
}
Works like a charm.
Output is
family
mom
data
isStartElement: true
Element BEGIN: dad
Since Woodstox is a StAX (JSR-173) compliant parser, you could use a StAX StreamFilter to exclude events corresponding to certain elements. I prefer this approach so that you can keep the filtering logic separate from your application logic.
Demo
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/forum14326598/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr = xif.createFilteredReader(xsr, new StreamFilter() {
private boolean accept = true;
#Override
public boolean accept(XMLStreamReader reader) {
if((reader.isStartElement() || reader.isEndElement()) && "dad".equals(reader.getLocalName())) {
accept = !accept;
return false;
} else {
return accept;
}
}
});
while(xsr.hasNext()) {
if(xsr.isStartElement()) {
System.out.println("start: " + xsr.getLocalName());
} else if(xsr.isCharacters()) {
if(xsr.getText().trim().length() > 0) {
System.out.println("chars: " + xsr.getText());
}
} else if(xsr.isEndElement()) {
System.out.println("end: " + xsr.getLocalName());
}
xsr.next();
}
}
}
Output
start: family
start: mom
start: data
end: data
end: mom
end: family
I've found the reason, why I was getting the IllegalStateException. The very useful was flup's answer. Thanks a lot.
It is worth to read answer given by Blaise too.
But getting to the heart of the matter.
The problem was not skipElement() method itself. The problem was caused becouse of methods used to read attributes. There are three dots (...) in my question. So let's look what was there:
switch(eventType){
case (XMLEvent2.START_ELEMENT):
currentElementName = xmlsr.getName().toString();
logger.info("currentElementName: " + currentElementName);
if("dad".equals(currentElementName) == true){
logger.info("isStartElement: " + xmlsr.isStartElement());
logger.info("Element BEGIN: " + currentElementName);
xmlsr.skipElement();
}
case (XMLEvent2.ATTRIBUTE):
int attributeCount = xmlsr.getAttributeCount();
...
break;
}
Important thing. There is no break statement for START_ELEMENT. So every time START_ELEMENT event occurs the code for event ATTRIBUTE is also executed.
That looks OK according to Java Docs, becouse methods getAttributeCount(), getAttributeValue() etc. can be executed for both START_ELEMENT and ATTRIBUTE.
But after calling method skipElement(), event START_ELEMENT is changed to END_ELEMENT. So calling method getAttributeCount() is not allowed. This call is the reason why IllegalStateException is thrown.
The simplest way to avoid that Exception is just calling break statement after calling skipElement() method. In that case code for getting attributes will not be executed, thus Exception will not be thrown.
if("dad".equals(currentElementName) == true){
logger.info("isStartElement: " + xmlsr.isStartElement());
logger.info("Element BEGIN: " + currentElementName);
xmlsr.skipElement();
break; //the cure for IllegalStateException
}
I'm sorry I gave you no chance to answer my original question becouse of to much code hidden.
It looks like the method xmlsr.skipElement() is the one that must consume the XMLEvent2.START_ELEMENT event. And since you already consumed it (xmlsr.next()), that method throws you an error.