简体   繁体   中英

Is this bad practice for passing an input file in Java?

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);
    }

}

}

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, eg 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 (ie InterruptedException ). Catch the most specific exception type you can.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM