-1

I have a main class that expects an input file name to be provided through the command line argument; if this is not true then the program exits with an error message.

We are assuming the existence of a class called SudokuReducer. After making sure there is an input file, the main function will pass the input file (not just the name of the file) to an instance of SudokuReducer.

What I want to know, is this bad form/practice? Is it wrong to put the entirety of the scan inside a try/catch like this? Because then if I wanted to declare the SudokuReducer instance in 'main' outside of the try/catch instead of in, I can't since it doesn't recognize what 'fileInput' has been passed due to its limited scope inside the 'try'

Is there a better way of doing this? Here's what I have:

import java.io.File;

public class MainMV {

File inputFile;

public static void main(String args[]) {

    // check if file is entered and handle exception
    try {
        if (args.length > 0) {
            File inputFile = new File(args[0]);

            System.out.println("Processing file");
            SudokuReducer reducer = new SudokuReducer(inputFile);

        } else {
            System.out.println("No file entered.");
            System.exit(1);
        }

    } catch (Exception e) {
        System.out.println("File failed to open.");
        System.exit(1);
    }

}

}

teddymv
  • 49
  • 1
  • 9
  • Your code doesn't really match your description, although I can see why you would think it would. Also, without seeing SudokuReducer, or knowing the contents of the file, it is virtually impossible to figure out what you are really trying to do. – Mad Physicist Feb 18 '18 at 00:00
  • SudokuReducer is empty as of right now. Haven't written it yet. It just receives a file stated in the main's argument and processes it. – teddymv Feb 18 '18 at 00:06
  • 1
    You do understand that a File object is essentially just a file name? It is not necessarily tied to anything on disk and certainly doesn't initiate any I/O on it's own. – Mad Physicist Feb 18 '18 at 00:09
  • 2
    Well, here's an assumption. It appears that it's possible for `SudokuReducer` to throw a `IOException` at the very least, possibly even a `ParserException`, if the file is not found or is not in the correct format. So, yes, arguably, it is correct to use a `try-catch` in this way – MadProgrammer Feb 18 '18 at 00:10
  • I'm pointing that out because it is extremely unclear what your issue or concern actually is. – Mad Physicist Feb 18 '18 at 00:10
  • I'm pretty sure I get what you're saying. I provided an argument for this in Eclipse and it runs fine. I can even include a scanner and scan thru and print out each line and it works. I just wanted to know if there's a better way to handle this input, instead of putting everything in the 'try'? – teddymv Feb 18 '18 at 00:12
  • It just seems clunky to put everything in that. Wanted to know essentially what the minimum I can include in the try/catch is, I guess. – teddymv Feb 18 '18 at 00:13

2 Answers2

1

To answer the question in the title: no, it's not bad practice, if that method needs a File to do its work.

Another option would be passing a String; and that's a poor choice, because it doesn't convey that the parameter is supposed to represent a File of some sort.

Perhaps a better option would be to pass in an InputStream to the method, since a) that clearly conveys that it's going to be used for input (as opposed to being a File that you will write to); b) it's more flexible, because it doesn't have to refer to a file on disk.


To answer the question in the question: no, it's not really good practice to wrap everything in one try/catch like this. It makes it hard to distinguish the modes of failure: many different things could go wrong in your code, and it's better to handle those things separately, e.g. to provide specific failure messages.

A better way to structure the code is something like this:

if (args.length == 0) {
  System.out.println("No file entered.");
  System.exit(1);
}

File inputFile = new File(args[0]);
System.out.println("Processing file");
try {
  SudokuReducer reducer = new SudokuReducer(inputFile);
  // Do something with reducer.
} catch (IOException e) {
  e.printStackTrace();
  System.out.println("File failed to open.");
  System.exit(1);
}

Note that this has small blocks, handling specific errors, rather than a great big block where the error handling is separated from the thing causing the error.

Also, note that it's not catching Exception: you really don't want to do that unless you have to, because you're not correctly handling exceptions that it would catch that have to be handled in special ways (i.e. InterruptedException). Catch the most specific exception type you can.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

From my understanding, Java passes parameters as a reference of the object by value which for me was terribly confusing.

Link to explanation of Pass by Reference vs Pass by Value.

Link to explanation of the Java implementation

Depending on how much information from the file is required to generate an instance of your SudokuReducer class, the overhead of this could be significant. If this is the case, you'll want to parse your input line by line doing something like this in your main method.

 try {
     SudokuReducer reducer = SudokuReducer.makeSudokuReducer(args[0])
  }
 catch(Exception e) { 
     System.out.println("No file entered.");
     System.exit(1);
 }

Here's an example of reading a file line by line There are many ways to do this, but the most efficient way I can think of is by using Java 8's Stream and Files classes.

The method signature will look something like this:

public static SudokuReducer makeSudokuReducer(String filename) {
    //Open file
    //Parse input line by line
    //Use information to create a new instance of your class
    //Return the instance of this class
}

You'll be able to call this static method anywhere to produce a new instance of your class from a filename.

  • OP's question has nothing to do with passing by value or by reference. – Andy Turner Feb 18 '18 at 00:34
  • The title of the post is *Is this bad practice for passing an input file in Java*. This was my first post so thanks for the feedback. I figured just because a post doesn't explicitly ask a question, but the structure of a post implies OP doesn't understand something, shouldn't it be answered? – Matt McCarthy Feb 18 '18 at 00:41
  • Matt - sorry, my question was pretty poorly conveyed. Appreciate the answer anyways. – teddymv Feb 18 '18 at 01:02