What exception to throw when file is not properly formated/empty - java

For example I've this file that should be formated like this:
PersonName
2,5,6,7,8,9
First line only has a name and from the second line onwards its all comma separated values.
Ending in a new line. For some reason I can't make a new empty line in code format.
Now lets say that those comma separated values will be copied into an ArrayList and then I check if the ArrayList is empty or not. If it is empty I've to throw an exception. My question is, what exception to throw here?
Something like (in pseudo code):
FileReader fr = new FileReader(f);
BufferedReader buffReader = new BufferedReader(fr);
ArrayList list = new ArrayList();
while(interator.hasCSV) {
// copy values to list
Object obj = interator.next();
list.add(obj);
}
if(list.isEmpty()) {
// What exception to throw here?
// It means there was a name in the file (first line) but then no csv values
}
I hope I made myself clear otherwise just let me know and I'll try to explain it better.

as paxdiablo said you can create your own exception here is an example link
class CheckListException extends Exception
{
//Parameterless Constructor
public CheckListException() {}
//Constructor that accepts a message
public CheckListException(List list)
{
super(list);
}
}
to use the exception
try
{
if(list.isEmpty()) {
// What exception to throw here?
// It means there was a name in the file (first line) but then no csv values
throw new CheckListException();
}
}
catch(CheckListException ex)
{
//Process message however you would like
}

Create your own exception. For further details follow this
if()//your condition
/*create custom exeception*/
throw new Exception("My custom exception");
}
But this is one time exception.
You have to follow the above link to create a new class for your custom exception to reuse.

There's no requirement to use the standard ones defined in Java since you can create whatever ones you need.
While it looks like (from here) the closest one in the standard set is probably DataFormatException (see here), that's targeted to ZIP files.
Perhaps a better match would be ParseException. If you wanted to use one of the more targeted standard ones, that would be the one I'd be looking to use (if you don't wish to create your own), or inherit from (if you do).
But keep in mind you can always inherit from the top-level Exception class if you're not overly concerned about where it is in the hierarchy.

It would be normal to place all the code responsible for parsing the content of the file in its own method. Most parsers interleave reading from the input stream and examining what it has read. Such a method must declare that it throws IOException, because the parts of the method that read from the input stream can throw an IOException. The parsing method will be easier to use if parse errors are also indicated by throwing an IOException: a caller of the method can use one catch to handle all problems, if they are not interested in the details of the problems.
A caller of the method might however want to be able to distinguish between different kinds of problems. The caller might want to report different error messages for a missing file and for an incorrectly formatted file. To support this, you could create your own InvalidFormatException that extends IOException and throw that when there is a parse error.

Related

How can I convert JSON file into List of objects?

I'm trying to do a loader for my program and the saver into json works, but the reader doesn't. I'm basically converting my list of objects, let's say ArrayList ProjectArr into json which is working, now I'm gonna close terminal and load the info into my initially blank ProjectArr list so I can add the saved data loading feature. here is my reader :
public static ArrayList<Project> MapReaderforProject() {
ObjectMapper objectMapperforProject = new ObjectMapper();
String jsonfile = "C:/Users/elmm/Desktop/DS Project/DsProject/target/test1.json";
File file = new File("C:/Users/elmm/Desktop/DS Project/DsProject/target/test1.json");
try {
ProjectArr = objectMapperforProject.readValue(jsonfile,new TypeReference<ArrayList<Project>>(){});
}
catch (JsonMappingException e) {
} catch (JsonProcessingException e) {
}
System.out.println(ProjectArr.toString());
return ProjectArr;
}
But when I call this even though the JSON file is working and has the info, it's not reading anything and just prints [], empty list basically meaning it's not reading the data from JSON back into my list. Can someone please guide me?
There is some context information missing to give you more help. For example, what is ObjectMapper? Does it come from a library (and from which one) or have you written it yourself?
But what I have recognized so far: In line 3 you create a String which contains the file name. In line 4 you create a File object with the same file name. You could use the String there which you created the line above.
In line 6 you call the readValue method on the ObjectMapper instance and pass the String created in line 3, which contains the file name. Does this method really want a String there with the file name? If this is the ObjectMapper from the Jackson library, you need to parse the JSON code as the first parameter to the readValue call, not the file name.
So it looks like after line 4 you need code to read the content of the file which you should pass to the readValue method.
Check out this short tutorial: https://www.baeldung.com/jackson-object-mapper-tutorial
hth
McPringle

PrintWriter the output file is not there although no exception thrown

I have just started learning Java and I have got following problem I have been struggling for hours with. I want to use PrintWriter in order to produce a simple text file.
I do not get any runtime exception, still the file is not appearing in the specified directory.
public class Main {
public static void main(String[] args) {
try (final PrintWriter writer = new PrintWriter(
new File("c:\test\new\notes.txt"))) {
writer.write("Test note");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
What am I doing wrong?
\ represents an escape character so needs to be escaped itself for literal backslash characters. You can also use / and Java will resolve the correct separation character for the platform
try (final PrintWriter writer = new PrintWriter("c:\\test\new\\notes.txt")) {
Add writer.flush() after writer.write("Test note"), and use double backslashes for Windows paths (as other answers are suggesting).
As Reimeus already said, \ is an escape character in java.
That means that a string containing "\n" or "\t" does not represent the stringliteral \n or \t!
'\n' represents the newline character and '\t' represents the TAB character!
For the better understanding, the following code:
System.out.println("c:\test\new\notes.txt");
would not print c:\test\new\notes.txt to the console, it would print
c: est
ew
otes.txt
to the console!
To be able to write the backslash in a string you'll need to use '\\'!
I see your question as having 2 parts:
Why doesn't the code work?
Why was no exception thrown?
The first question has already been answered, but I think the answer to the second question is at least as important because your current code will still fail silently if there is any problem writing to the file.
From the documentation of PrintWriter (http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html):
Methods in this class never throw I/O exceptions, although some of its
constructors may. The client may inquire as to whether any errors have
occurred by invoking checkError().
Therefore it is essential that you call checkerror() after every call to a PrintWriter method or your code will not be reliable.

Using File I/O in Java

I am trying to create a pet project for the summer, which requires a large amount of information. I think the best way to do this would be to store all the data in a text file, and proceed to pull the necessary information from that file when it's called upon. My question, though, is how to pull specific sets of information, and then proceed to store parts of that into an array perhaps or some other data structure which would allow for that to be more easily accessed during the execution of the program. The text file would have hundreds (if not thousands) of "sets" of data, and each "set" will have multiple parts. For example,
ID001 Name Data1 Data2 Data3 TypeData
Where ID001 would just be an index, the name would be a string, the three "Data" would be integers, and the TypeData would be a String (for example). What is the best way to go about taking all that information (there'll actually be more data per "set" but for simplicity's sake let's go with just this) and separating it so each part is usable by a different part of the program? Is this even the right way to go about doing something like this? I was originally imagining something along the lines of a spreadsheet but I don't know how to use something quite like that as I/O for a program.
Here's one possible way of reading a file and getting just the "chunks":
import java.io.*;
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));
while (s.hasNext()) {
System.out.println(s.next());
}
} finally {
if (s != null) {
s.close();
}
}
}
}
You can take a look at the Java Scanner Tutorial for other ideas.

Jena- Writing onto owl file- Unexpected result result

I created a file system that stores metadata of files and folders in an owl file.
For file system, I am using java binding of FUSE i.e. FUSE-JNA
For OWL, I am using Jena:
Initially my file system runs ok with no error. But after sometime my program stops reading .owl file and throws some errors. One of the error is below:
Errors I get while reading .owl file:
SEVERE: Exception thrown: org.apache.jena.riot.RiotException: [line: 476, col: 52] The value of attribute "rdf:about" associated with an element type "File" must not contain the '<' character.
org.apache.jena.riot.system.ErrorHandlerFactory$ErrorHandlerStd.fatal(ErrorHandlerFactory.java:136)
org.apache.jena.riot.lang.LangRDFXML$ErrorHandlerBridge.fatalError(LangRDFXML.java:252)
com.hp.hpl.jena.rdf.arp.impl.ARPSaxErrorHandler.fatalError(ARPSaxErrorHandler.java:48)
com.hp.hpl.jena.rdf.arp.impl.XMLHandler.warning(XMLHandler.java:209)
com.hp.hpl.jena.rdf.arp.impl.XMLHandler.fatalError(XMLHandler.java:239)
org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
...
I open my .owl file, what I found is the Jena is not writing correctly. In picture below if you see number 3 highlighted error in blue color, its incomplete, there is some code missing there.
Secondly, number 2 blue highlighted error is also written wrongly.In my ontology is property of File. It should be written as of number 1 blue highlighted code.
Although both the number 1 and number 2 code is written by jena. Most of the owl code is written correctly by Jena as similar to number 1 but some time jena writes it wrongly as similar to number 2 in picture. I do not know why.
(to see the picture in full size, open it in new tab or save it on your computer)
This is how I am writing to .owl file using jena api:
public void setDataTypeProperty(String resourceURI, String propertyName, String propertyValue) //create new data type property. Accept four arguments: URI of resource as string, property name (i.e #hasPath), old value as string and new value as string.
{
Model model = ModelFactory.createDefaultModel();
//read model from file
InputStream in = FileManager.get().open(inputFileName);
if (in == null)
{
throw new IllegalArgumentException( "File: " + inputFileName + " not found");
}
model.read(in, "");
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Add property to Model
Resource resource = model.createResource(resourceURI);
resource.addProperty(model.createProperty(baseURI+propertyName), model.createLiteral(propertyValue));
//Writing model to file
try {
FileWriter out = new FileWriter( inputFileName );
model.write( out, "RDF/XML-ABBREV" );
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Please guide me how to fix the number 2 and number 3 blue highlighted errors of Jena.
There is an issue of input-sanitation to your method. I cannot be certain that your input data is invalid, but it is certainly something that should be tested in any method that is programmatically constructing URIs or literals.
URIs
For example, the following two lines are dangerous because they can allow characters that are not allowed in a URI, or they can allow characters for literal values that cannot be serialized as XML.
Resource resource = model.createResource(resourceURI);
resource.addProperty(model.createProperty(baseURI+propertyName), model.createLiteral(propertyValue));
To fix the problem of URIs, use URLEncoder to sanitize the uris themselves:
final String uri = URLEncoder.encode(resourceURI, "UTF-8");
final String puri = URLEncoder.encode(baseURI+propertyName);
final Resource resource = model.createResource(uri);
resource.addProperty(model.createProperty(puri), model.createLiteral(propertyValue));
To test for the problem us URIs, you can use Jena's IRIFactory types in order to validate that the URI you are constructing adheres to some particular specification.
Literals
To solve the problem of literals is a little more tricky. You are not getting an exception that indicates that you have a bad value for a literal, but I am including this for completeness (so you can sanitize all inputs, and not only the ones that may be causing a problem now).
Jena's writers do not test the values of literals until they are being serialized as XML. The pattern that they use to detect invalid XML characters is focused only on the characters that are required to replace as part of the RDF XML specification. Jena delegates the final validation (and exception throwing) to the underlying XML library. This makes sense, because there could exist a future RDF serialization that allows the expression of all characters. I was recently bit by it (for example, a string that contains a backspace character), so I created a more strict pattern in order to eagerly detect this situation at runtime.
final Pattern elementContentEntities = Pattern.compile( "[\0-\31&&[^\n\t\r]]|\127|[\u0080-\u009F]|[\uD800-\uDFFF]|\uFFFF|\uFFFE" );
final Matcher m = elementContentEntities.matcher( propertyValue );
if( m.find() ) {
// TODO sanitise your string literal, it contains invalid characters
}
else {
// TODO your string is good.
}
The nature of the truncation at #3 - "admi" - leads me to think that maybe this is a problem with your underlying data transport and storage, and has nothing to do with XML, RDF, Jena, or anything else up at this level. Maybe an ignored exception?
My main program was some times passing resourceURI argument as blank/null to setDataTypeProperty method. That's why it was creating problem.
So I have modified my code and added two lines at start of the method:
public void setDataTypeProperty(String resourceURI, String propertyName, String propertyValue) //create new data type property. Accept four arguments: URI of resource as string, property name (i.e #hasPath), old value as string and new value as string.
{
if (resourceURI==null)
return;
...
...
Now I am running it since few days but did not face the above mentioned errors yet.

Generating fatal error in Java

Suppose we are writing a Java library, which provides some I/O ulitity functions, for example, a convenient method to read text files as Strings:
public class StringReader {
private static final Logger log = LoggerFactory.getLog(StringReader.class);
/**
* Returns the contents of file <b>fileName</b> as String.
* #param fileName file name to read
* #return null on IO error
*/
public static String readString(String fileName) {
FileInputStream fis = null;
try {
fis = new FileInputStream(fileName);
byte[] data = new byte[fis.available()];
fis.read(data);
return new String(data, "ISO-8859-1"); // may throw UnsupportedEncodingException!
} catch (IOException e) {
log.error("unable to read file", e);
} catch (UnsupportedEncodingException e) {
log.fatal("JRE does not support ISO-8859-1!", e);
// ???
} finally {
closeQuiet(fis);
}
return null;
}
}
This code reads a text file into a String using ISO-8859-1 encoding and returns the String to user.
The String(byte[], String) constructor throws an UnsupportedEncodingException when specified encoding is not supported. But, as we know, ISO-8859-1 must be supported by JRE, as said here (see the Standard charsets section).
Hence, we expect the block
catch (UnsupportedEncodingException e) {
log.fatal("encoding is unsupported", e);
// ???
}
is never reached if JRE distribution conforms the standard.
But what if it doesn't? How to handle this exception in the most correct way?
The question is, how to alert properly about such error?
The suggestions are:
Throw some kind of RuntimeException.
Do not disable the logger in production code, write an exception details in log and ignore it.
Put the assert false here, so it produce AssertionError if user launched VM with -ea.
Throw an AssertionError manually.
Add an UnsupportedEncodingException in method declaration and allow user to choose. Not very convenient, I think.
Call System.exit(1).
Thanks.
But what if it doesn't?
Then you're in a really bad situation, and you should probably get out of it as quickly as possible. When a JRE is violating its own promises, what would you want to depend on?
I'd feel happy using AssertionError in this case.
It's important to note that not all unchecked exceptions are treated equally - it's not unusual for code to catch Exception at the top level of the stack, log an error and then keep going... if you just throw RuntimeException, that will be caught by such a scheme. AssertionError would only be caught if the catch block specified Throwable (or specifically Error or AssertionError, but that's much rarer to see). Given how impossible this should be, I think it's reasonable to abort really hard.
Also note that in Java 7, you can use StandardCharsets.ISO_8859_1 instead of the string name, which is cleaner and removes the problem.
There are other things I'd change about your code, by the way:
I would avoid using available() as far as possible. That tells you how many bytes are available right now - it doesn't tell you how long the file is, necessarily.
I would definitely not assume that read() will read the whole file in one go. Call read() in a loop, ideally until it says there's no more data.
I would personally accept a Charset as a parameter, rather than hard-coding ISO-8859-1. - I would let IOException bubble up from the method rather than just returning null. After all, unless you're really going to check the return value of every call for nullity, you're just going to end up with a NullPointerException instead, which is harder to diagnose than the original IOException.
Alternatively, just use Guava's Files.toString(File, Charset) to start with :) (If you're not already using Guava, now is a good time to start...)
This is a rather common occurrence in code.
Unchecked exceptions are made for this. They shouldn't happen (which is why they are unchecked), but if they do, there is still an exception.
So, throw a RuntimeException that has the original Exception as the cause.
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e); //should not happen
}
assert(false); also throws an unchecked exception, but it assertions can be turned off, so I would recommend RuntimeException.

Categories

Resources