简体   繁体   中英

Why should I create File object and then use it in FileWriter or PrintWriter when I can create file with latter ones?

Why:

File file = new File("somefile.txt");
PrintWriter printWriter = new PrintWriter(file);

When we can directly:

PrintWriter printWriter = new PrintWriter("somefile.txt");

I understand the concept and understand that File() constructor creates an abstraction of the file, but putting this down to practical problems, why one should want to create File object and then pass it to the FileWriter? (or any other writer constructor)

What is the purpose?

In your example, the two versions do the same thing. The only real difference is code readability. (It is up to you to decide which version you think is more readable.)

On the other hand, if you need to perform manipulations on the file pathnames, it is better to use File or Path to do that rather than trying to do the same thing using string bashing. Examples include getting a parent directory path, forming a child directory path, adding or removing filename suffixes. By using File or Path , you can often avoid complications such as platform specific differences in pathname syntax.

In addition, File and Path (and related classes) allow you to do other things on the files / directories themselves. For example, renaming / moving, deleting or testing and changing permissions.

In short, in other cases there may be good reasons to prefer using File , etcetera. But in your example it makes no real difference.

It's a convenience. Check the source code for the constructors. (Open JDK implementation)

public PrintWriter(String fileName) throws FileNotFoundException {
    this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))), false);
}

public FileOutputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null, false);
}

The method is just overloaded . It is mainly there to provide the user a more comfortable way of using the PrintWriter .

If you have your file currently as File object, you can directly pass it. If you have it as OutputStream , you can use that. If you have a String representing the path, just use that and so on.

Internally they all break down to the same method which opens an OutputStream to the ressource.

Imagine you do not create the ressource by yourself but rather get it as object from another method . If the method returns a File object and PrintWriter would not have this additional constructor, you would need to extract the path from the file object. That is one extra line of code and computer scientists are lazy...

Also the main constructor would be the one that uses the OutputStream as this is the most flexible object, it also allows printing to stuff that is no file like a web ressource or other streams. If you now just want to write some lines into a file the additional constructors are pretty handy and save some lines of code.

If you just want to create a new file at a given location on your file system, sure why not use the new PrintWriter(String path) . It seems to be handy for this scenario. However you maybe do not want to represent the path as String . Possibly the destination location is complex and relative, then a File would be more handy. Like new File("testFile", directory) which creates the file into the directory given as File with a relative path.

Just use the constructor which looks most handy for your current situation.

The main reason is based on a architecture paradigm named separation of concerns .

If you are just working on this specific case, it's simpler just do the second call and encapsulate two actions in one line. But in the software architecture point of view you are solving two different problems with one single operation.The first problem is to define and initialize the output. The second is to write to the choosed output.

This means that if in the future you want to change your application to work with differente outputs, like network connections, consoles or other, you will need to change the entire operation, because network connections can not be described as string, like files. But if you work with the Writer as a generic operation, that will always receive an initialized output stream, in the future you'll not need to make changes.

Your example is a simple case all this talk about software architecture may be a seen as a little complication. But as soon as you begin to work using this ideia of separation of concerns your code will be more consistent, maybe a little more verbose, but more robust.

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