I Have a question abouth the code for handling erros made by the user.
So the thing is, I need my user to add a name of a program, to add the memory that program takes in the RAM and to add the time he will have that program open.
I need to add in my code defensive programming, so I thought maybe I could do it by checking if the user actually add the type of the variables that the program need, or if it didn't.
Either way I am confused on how to use the try and catch blocks, for now this is what I have...
System.out.println("add program Id");
String programID = scan.next();
try{
String check;
check = programID;
}catch(Exception e){
System.out.println("add a value of String type");
}
That doesn't work.
anything you can type is a string. I can type '5'. That's a string. You may think it is a number, but this entire block of text is a String, and '5' is in it.
No text is a string too. String x = ""; compiles fine.
Thus, no exception would ever occur here, and it's not clear what scenario you are trying to detect.
Perhaps a programID is of the form: "one capital letter (and only english capitals, not Ü for example), and then up to 3 different digits". For example, 'Z5' or 'Y495'.
You'd need to write code to detect this, no need for try/catch. For example, regular expressions:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
programId = scanner.next();
if (!PROGRAM_ID_PATTERN.matcher(programId).matches()) {
System.err.println("Enter a valid program ID, e.g. A123");
} else {
break;
}
} while (true);
}
Exceptions are for when a method has multiple different ways to exit.
For example, imagine this method:
byte[] contentsOfFile = Files.readFileFully("myfile.txt");
The readFileFully method seems simple: You provide the name of a file, and it returns a byte array with its contents.
However, that's just one way that could go. What if the file doesn't exist? What if the file exists, but your process doesn't have read access rights? What if the disk is failing or it's a removable drive and it's yanked out halfway through reading it?
These somewhat predictable potential alternate ways out are generally done by exceptions. That method would be throwing FileNotFoundException, noReadAccessException, and more generally IOException, for example.
There's no 'that is not a string' variant of scanner.next().
There is scanner.next(Pattern) which you could use:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
try {
programId = scanner.next(PROGRAM_ID_PATTERN);
break;
} catch (NoSuchElementException e) {
System.err.println("Enter a valid program ID, e.g. A123");
}
} while (true);
}
The javadoc generally explains what exceptions can occur; if a method doesn't mention any, you're not supposed to try/catch there.
Related
I downloaded my extended listening history from Spotify and I am trying to make a program to turn the data into a list of artists without doubles I can easily make sense of. The file is rather huge because it has data on every stream I have done since 2016 (307790 lines of text in total). This is what 2 lines of the file looks like:
{"ts":"2016-10-30T18:12:51Z","username":"edgymemes69endmylifepls","platform":"Android OS 6.0.1 API 23 (HTC, 2PQ93)","ms_played":0,"conn_country":"US","ip_addr_decrypted":"68.199.250.233","user_agent_decrypted":"unknown","master_metadata_track_name":"Devil's Daughter (Holy War)","master_metadata_album_artist_name":"Ozzy Osbourne","master_metadata_album_album_name":"No Rest for the Wicked (Expanded Edition)","spotify_track_uri":"spotify:track:0pieqCWDpThDCd7gSkzx9w","episode_name":null,"episode_show_name":null,"spotify_episode_uri":null,"reason_start":"fwdbtn","reason_end":"fwdbtn","shuffle":true,"skipped":null,"offline":false,"offline_timestamp":0,"incognito_mode":false},
{"ts":"2021-03-26T18:15:15Z","username":"edgymemes69endmylifepls","platform":"Android OS 11 API 30 (samsung, SM-F700U1)","ms_played":254120,"conn_country":"US","ip_addr_decrypted":"67.82.66.3","user_agent_decrypted":"unknown","master_metadata_track_name":"Opportunist","master_metadata_album_artist_name":"Sworn In","master_metadata_album_album_name":"Start/End","spotify_track_uri":"spotify:track:3tA4jL0JFwFZRK9Q1WcfSZ","episode_name":null,"episode_show_name":null,"spotify_episode_uri":null,"reason_start":"fwdbtn","reason_end":"trackdone","shuffle":true,"skipped":null,"offline":false,"offline_timestamp":1616782259928,"incognito_mode":false},
It is formatted in the actual text file so that each stream is on its own line. NetBeans is telling me the exception is happening at line 19 and it only fails when I am looking for a substring bounded by the indexOf function. My code is below. I have no idea why this isn't working, any ideas?
import java.util.*;
public class MainClass {
public static void main(String args[]){
File dat = new File("SpotifyListeningData.txt");
List<String> list = new ArrayList<String>();
Scanner swag = null;
try {
swag = new Scanner(dat);
}
catch(Exception e) {
System.out.println("pranked");
}
while (swag.hasNextLine())
if (swag.nextLine().length() > 1)
if (list.contains(swag.nextLine().substring(swag.nextLine().indexOf("artist_name"), swag.nextLine().indexOf("master_metadata_album_album"))))
System.out.print("");
else
try {list.add(swag.nextLine().substring(swag.nextLine().indexOf("artist_name"), swag.nextLine().indexOf("master_metadata_album_album")));}
catch(Exception e) {}
System.out.println(list);
}
}
Find a JSON parser you like.
Create a class that with the fields you care about marked up to the parsers specs.
Read the file into a collection of objects. Most parsers will stream the contents so you're not string a massive string.
You can then load the data into objects and store that as you see fit. For your purposes, a TreeSet is probably what you want.
Your code will throw a lot of exceptions only because you don't use braces. Please do use braces in each blocks, whether it is if, else, loops, whatever. It's a good practice and prevent unnecessary bugs.
However, everytime scanner.nextLine() is called, it reads the next line from the file, so you need to avoid using that in this way.
The best way to deal with this is to write a class containing the fields same as the json in each line of the file. And map the json to the class and get desired field value from that.
Your way is too much risky and dependent on structure of the data, even on whitespaces. However, I fixed some lines in your code and this will work for your purpose, although I actually don't prefer operating string in this way.
while (swag.hasNextLine()) {
String swagNextLine = swag.nextLine();
if (swagNextLine.length() > 1) {
String toBeAdded = swagNextLine.substring(swagNextLine.indexOf("artist_name") + "artist_name".length() + 2
, swagNextLine.indexOf("master_metadata_album_album") - 2);
if (list.contains(toBeAdded)) {
System.out.print("Match");
} else {
try {
list.add(toBeAdded);
} catch (Exception e) {
System.out.println("Add to list failed");
}
}
System.out.println(list);
}
}
I have this input stream that checks if I have a certain CAD file open or not. I am doing this by using an input stream to run a tasklist command with the name I want to check. I currently have a boolean that returns true if the specific CAD file isn't open. If the CAD file is open, it returns false. However, I want it to be able to loop this until the CAD file is open because as of right now I have to keep running it in order for it to work. I also need to be able to check this boolean from a separate class. I have it in my main right now so i could test it. My code looks like this...
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
String notOpen = "INFO: No tasks are running which match the specified criteria";
StringBuilder textBuilder = new StringBuilder();
String command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
int i;
InputStream myStream = Runtime.getRuntime().exec(command).getInputStream();
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
String output = textBuilder.toString();
boolean logical = output.contains(notOpen);
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
}
}
My other class is going to have an 'if statement' that checks whether my boolean "logical" is false, and if so, print something. I have tried every possible method I could think of, but I cannot get it to function the way I want it to. Every other thing I found involving looping an inputstream didn't really apply to my situation. So hopefully someone can help me out in achieving what I want to do.
I would start by moving everything out of main and into a different class. This will make retrieving values and calling specific functions easier. Then create an object of that class in main. Once that is done, I'd create a get method for the boolean variable. Now to focus on the loop. Once the object is created in main, create a conditional loop inside of main which calls the function you need until a different condition is met. This condition might be met once the file is open. After the condition is met, it exits to another loop that relies on another conditional, such as user input.
public class AutoCadCheck {
public static void main(String[] argv) throws Exception {
AutoCadFile file = new AutoCadFile();
//loop 1
//Some conditional so the program will
//continue to run after the file has been found.
// while(){
//loop 2
//check to see if the file is open or not
//while(logical){
//}
//}
}
}
Other class
import java.io.IOException;
import java.io.InputStream;
public class AutoCadFile {
private String notOpen;
private StringBuilder textBuilder;
private String command;
private int i;
private InputStream myStream;
private String output;
private boolean logical;
public AutoCadFile() {
notOpen = "INFO: No tasks are running which match the specified criteria";
textBuilder = new StringBuilder();
command = "tasklist /fi \"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]";
output = textBuilder.toString();
logical = output.contains(notOpen);
try {
myStream = Runtime.getRuntime().exec(command).getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void checkForFileOpen() {
try {
while ((i = myStream.read()) != -1) {
textBuilder.append((char) i);
}
if (logical) {
System.out.println("DWG Not Open");
} else {
System.out.print(output);
}
myStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean getFileBoolean() {
return logical;
}
}
My other class is going to have an if statement that checks whether my boolean logical is false ...
Well, logical is a local variable within a method. So no code in another class is going to be able to see it.
There are two common approaches to this kind of thing:
Make the variable (i.e. logical) a field of the relevant class. (Preferably NOT a static field because that leads to other problems.)
Put your code into a method that returns the value you are assigning to logical as a result.
From a design perspective the second approach is preferable ... because it reduces coupling relative to the first. But if your application is tiny, that hardly matters.
I can see a couple of other significant problems with your code.
When you use exec(String), you are relying on the exec method to split the command string into a command name and arguments. Unfortunately, exec does not understand the (OS / shell / whatever specific) rules for quoting, etcetera in commands. So it will make a mess of your quoted string. You need to do the splitting yourself; i.e something like this:
String[] command = new String{} {
"tasklist",
"/fi",
"windowtitle eq Autodesk AutoCAD 2017 - [123-4567.dwg]"
};
Your code potentially leaks an input stream. You should use a "try with resource" to avoid that; e.g.
try (InputStream myStream = Runtime.getRuntime().exec(command).getInputStream()) {
// do stuff
} // the stream is closed automatically ... always
This is just for a simple command-line standalone program in Java.
I'd like to open a file to write to, and keep it open. I need to write formatted floats/doubles to it, in human-readable ASCII, like a CSV file.
I have tried various approaches (1) (2) (3) I have found through my favorite search engine, and they have the form:
try {
// some file handle opening sequence
}
catch ( <some exception> ) {
// do something
}
finally {
// do something else
}
(...or in the case of the third example, the file opening/writing/closing is inside a function that throws an exception.) I realize it's good programming style to make sure that you've opened a file ok, but for my purposes that's really not necessary.
Anyway the problem with the above approach is that outside of the try{} block, the filehandle is closed. I'd like to keep it open, because the kernel of my code consists of a huge loop that I go through a few 100,000 times (say), and each time through I'd like to output a single float (in ASCII) to the file.
With the above form, the only way to do that is to enclose my huge for loop inside the try{} block. Which seems silly. Alternatively, I could re-open the file every time through the loop, but that means additional logic, opening the file as a 'new' file the first time, and appending in all subsequent times.
Is there some way to open the file, keep it open to write to it occasionally, and then close it when I'm done?
Something like:
{
// open file "data.out"
}
for (i=0;i<100000;i++) {
// do a lot of stuff
//
// calculate some quantity "x"
//
// output float "x" in ASCII form, appending it to data.out
}
{
// close data.out
}
Does Java allow that? Thanks.
Of course you can simple store your FileWriter somewhere, as any other variable. You can, for example, encapsulate the whole writing logic in its own class, which offers one write method for your specified format.
But why does it seem silly? Perhaps this approach might help...
public void methodA(File myFile) throws IOException{
try ( FileWriter writer = new FileWriter( myFile ) ) {
writeTo(writer);
}
}
private void writeTo(FileWriter writer) throws IOException {
for (i=0;i<100000;i++) {
// do a lot of stuff
//
// calculate some quantity "x"
//
// output float "x" in ASCII form, appending it to data.out
}
}
This way, one method takes care of the opening/closing/exceptions, while the other method can concentrate on the important writing stuff, using the FileWriter given to it.
as you said the file is closed at the end of the try block. Possibly
the FileWriter object is created inside the try block:
(You did not post a real java code, only a pseudo code.)
Example, hope this helps
public static void main(String[] args)
{
...
BufferedWriter ofs=null; // should by outside the try block
try
{
Path logfile = Paths.set("C:\\temp\\log.log");
ofs = Files.newBufferedWriter(logfile); // new in java 8
YourWorker.doYourJob(ofs);
} catch (Exception e)
{ e.printStackTrace();
} finally
{
if (ofs!=null) { try { ofs.close(); } catch (Exception e) {} }
}
System.exit(1);
} //---------- end of main()
} //---- end of class
I have the following code:
TestClass test=new TestClass();
test.setSomething1(0); //could, but probably won't throw Exception
test.setSomething2(0); //could, but probably won't throw Exception
I would like to execute: test.setSomething2(0); even if test.setSomething(0) (the line above it) throws an exception. Is there a way to do this OTHER than:
try{
test.setSomething1(0);
}catch(Exception e){
//ignore
}
try{
test.setSomething2(0);
}catch(Exception e){
//ignore
}
I have a lot of test.setSomething's in a row and all of them could throw Exceptions. If they do, I just want to skip that line and move to the next one.
For clarification, I don't care if it throws an Exception, and I can't edit the source code of the code which throws this exception.
THIS IS A CASE WHERE I DON'T CARE ABOUT THE EXCEPTIONS (please don't use universally quantified statements like "you should never ignore Exceptions"). I am setting the values of some Object. When I present the values to a user, I do null checks anyway, so it doesn't actually matter if any of the lines of code execute.
try {
// Your code...
} catch (Exception ignore) { }
Use the word ignore after the Exception keyword.
There is no way to fundamentally ignore a thrown exception. The best that you can do is minimize the boilerplate you need to wrap the exception-throwing code in.
If you are on Java 8, you can use this:
public static void ignoringExc(RunnableExc r) {
try { r.run(); } catch (Exception e) { }
}
#FunctionalInterface public interface RunnableExc { void run() throws Exception; }
Then, and implying static imports, your code becomes
ignoringExc(() -> test.setSomething1(0));
ignoringExc(() -> test.setSomething2(0));
IntelliJ Idea IDE suggests to rename a variable to ignored
when it isn't used.
This is my sample code.
try {
messageText = rs.getString("msg");
errorCode = rs.getInt("error_code");
} catch (SQLException ignored) { }
Unfortunately no, there isn't, and this is by intention. When used correctly, exceptions should not be ignored as they indicate that something didn't work and that you probably shouldn't continue down your normal execution path. Completely ignoring exceptions is an example of the 'Sweep it under the rug' anti-pattern, which is why the language doesn't support doing so easily.
Perhaps you should look at why TestClass.setSomething is throwing exceptions. Is whatever you're trying to 'test' really going to be valid if a bunch of setter methods didn't work correctly?
You can't ignore exception in Java. If a method declares being able to throw something this is because something important can't be done, and the error can't be corrected by the method designer. So if you really wan't to simplify your life encapsulate the method call in some other method like this :
class MyExceptionFreeClass {
public static void setSomething1(TestClass t,int v) {
try {
t.setSomething1(v);
} catch (Exception e) {}
public static void setSomething2(TestClass t,int v) {
try {
t.setSomething2(v);
} catch (Exception e) {}
}
and call it when you need it:
TestClass test=new TestClass();
MyExceptionFreeClass.setSomething1(test,0);
MyExceptionFreeClass.setSomething2(test,0);
You should not ignore Exceptions. You should handle them. If you want to make your test code simple, then add the try-catch block into your functions. The greatest way to ignore exceptions is to prevent them by proper coding.
I know this is old, but I do think there are occasions when you want to ignore an exception. Consider you have a string that contains a delimited set of parts to be parsed. But, this string can sometimes contain say, 6 or 7 or 8 parts. I don't feel that checking the len each time in order to establish an element exists in the array is as straight forward as simply catching the exception and going on. For example, I have a string delimited by '/' character that I want to break apart:
public String processLine(String inLine) {
partsArray = inLine.split("/");
//For brevity, imagine lines here that initialize
//String elems[0-7] = "";
//Now, parts array may contains 6, 7, or 8 elements
//But if less than 8, will throw the exception
try {
elem0 = partsArray[0];
elem1 = partsArray[1];
elem2 = partsArray[2];
elem3 = partsArray[3];
elem4 = partsArray[4];
elem5 = partsArray[5];
elem6 = partsArray[6];
elem7 = partsArray[7];
catch (ArrayIndexOutOfBoundsException ignored) { }
//Just to complete the example, we'll append all the values
//and any values that didn't have parts will still be
//the value we initialized it to, in this case a space.
sb.append(elem0).append(elem1).append(elem2)...append(elem7);
//and return our string of 6, 7, or 8 parts
//And YES, obviously, this is returning pretty much
//the same string, minus the delimiter.
//You would likely do things to those elem values
//and then return the string in a more formatted way.
//But was just to put out an example where
//you really might want to ignore the exception
return sb.toString();
}
Those who write empty catch blocks shall burn in the Hell for the eternity.
Or worse, they will be forced to debug the damn rubbish they wrote forever and ever.
That said, one thing you might want to do is writing exception handling in a less verbose way. The NoException library is very good at that.
How to handle error conditions when writing a Java API/Utility
This is my Implementation for my API interface
public void bin2zip(InputStream[] is,OuputStream os, String[] names)
{
//if number of streams and number of names do not match do something
}
What I am trying to do is handling a case when the length of the is != length of name.
How do i handle this. I dont want my API to do some work until ArrayOutOfBound exception to be thrown. I want to catch this early.
One solution is something like this:
if it does not match I throw
if(is.length==names.length)
throws new Exception("ParemeterValidationException: The inputstream array and name array length should match");
if(containsInvalidFileName(names))
throws new Exception("ParemeterValidationException: The names array length should contain valid filenames");
Also, can this be done compile time using DataDependency (I can make ValidationClass for the API and make sure the developer get hold of this object to pass on to this conversion API) or the runtime exception is the best way?
I believe doing a ValidationClass will make API use complicated
I did go through some materials (if anyone interested), but need some directions.
http://lcsd05.cs.tamu.edu/slides/keynote.pdf
Java: checked vs unchecked exception explanation
http://docs.oracle.com/javase/tutorial/collections/interoperability/api-design.html
Wherever possible, don't let end users screw it up.
public final class Bin2Zipper {
private final List<InputStream> inputStreams = ...;
private final List<String> names = ...;
public BinZipper() {
}
public void add(final InputStream is, final String name) {
this.inputStreams.add(is);
this.names.add(name);
}
public void bin2zip(final OutputStream os) {
// ...
}
}
A fluent interface might even be better. Then your code would look like:
Bin2Zipper.add(is1, name1).add(is2, name2).add(is3, name3).toZip(os);
public final class Bin2Zipper {
private final List<InputStream> inputStreams = ...;
private final List<String> names = ...;
private Bin2Zipper(final InputStream is, final String name) {
this.inputStreams.add(is);
this.names.add(name);
}
public static Bin2Zipper add(final InputStream is, final String name) {
return new Bin2Zipper(is, name);
}
public Bin2Zipper add(final InputStream is, final String name) {
this.inputStreams.add(is);
this.names.add(name);
return this;
}
public void zip(final OutputStream os) {
...
}
}
Where these fall down is when the client starts off with the two arrays. In that case, it can be annoying for them to have to loop over all the entries themselves. I think it's still worth it. If you don't, then you'll have to compare the sizes of the inputs right away. You almost certainly want to throw an unchecked exception, probably an IllegalArgumentException like Vince said.
I think your solution of comparing the array lengths is perfectly appropriate. I think in this case you should throw an IllegalArgumentException; this exception is defined in the standard and used by most standard functions doing this kind of checking.
Many standard libraries use this kind of interface it is easily understood.
That said I think you should prefer an interface that simply doesn't facilitate such misuse such as that suggested by #Eric - the library everybody likes to use is the one that works first time every time because it's too simple to mess up.