简体   繁体   English

这是在 Java 中传递输入文件的坏习惯吗?

[英]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.我们假设存在一个名为 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.确定有输入文件后,主函数会将输入文件(不仅仅是文件名)传递给 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?像这样将整个扫描放在 try/catch 中是错误的吗? 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'因为如果我想在 try/catch 之外的“main”中声明 SudokuReducer 实例,而不是在其中,我不能,因为它无法识别传递了什么“fileInput”,因为它在“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.回答标题中的问题:不,如果该方法需要File来完成其工作,这不是坏习惯。

Another option would be passing a String ;另一种选择是传递一个String and that's a poor choice, because it doesn't convey that the parameter is supposed to represent a File of some sort.这是一个糟糕的选择,因为它没有传达参数应该代表某种File

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);也许更好的选择是将InputStream传递给该方法,因为 a) 清楚地表明它将用于输入(而不是您将写入的File ); b) it's more flexible, because it doesn't have to refer to a file on disk. b) 它更灵活,因为它不必引用磁盘上的文件。


To answer the question in the question: no, it's not really good practice to wrap everything in one try/catch like this.要回答问题中的问题:不,像这样将所有内容都包含在一次 try/catch 中并不是一个很好的做法。 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 ).另外,请注意,它没有捕获Exception :除非必须这样做,否则您真的不想这样做,因为您没有正确处理它会捕获的必须以特殊方式处理的异常(即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.根据我的理解,Java 将参数作为对象的引用按值传递,这对我来说非常令人困惑。

Link to explanation of Pass by Reference vs Pass by Value . 链接到按引用传递与按值传递的解释

Link to explanation of the Java implementation 链接到 Java 实现的解释

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.根据生成 SudokuReducer 类实例所需的文件信息量,此操作的开销可能很大。 If this is the case, you'll want to parse your input line by line doing something like this in your main method.如果是这种情况,您将需要在 main 方法中逐行解析您的输入。

 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. 这是逐行读取文件的示例有很多方法可以做到这一点,但我能想到的最有效的方法是使用 Java 8 的 Stream 和 Files 类。

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.您将能够在任何地方调用此静态方法以根据文件名生成类的新实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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