【问题标题】:Why should I create File object and then use it in FileWriter or PrintWriter when I can create file with latter ones?当我可以使用后者创建文件时,为什么要创建 File 对象然后在 FileWriter 或 PrintWriter 中使用它?
【发布时间】:2017-12-04 22:46:25
【问题描述】:

为什么:

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

当我们可以直接:

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

我理解这个概念并理解 File() 构造函数创建文件的抽象,但是将其归结为实际问题,为什么要创建 File 对象然后将其传递给 FileWriter? (或任何其他编写器构造函数)

目的是什么?

【问题讨论】:

  • 因为String 不一定表示它是用来表示文件名的。然而,File(以及最近的Path)正是出于这个原因而存在。
  • 你能澄清一下吗?所以你说传递给 File 构造函数的字符串.. 还有什么其他用途?没看懂。。
  • 因为您误解了File 对象是什么。它不是文件系统上的文件。它只是一个用于处理文件paths(即限定文件名)的包装器/帮助器类。 “创建”File 对象不会 在文件系统上创建文件。阅读File的javadoc:文件和目录的抽象表示路径名
  • 该方法只是重载。它主要是为用户提供更舒适的使用PrintWriter 的方式。如果您的文件当前为File 对象,则可以直接传递它;如果你有InputStream,你可以使用它;如果你有一个代表路径的String,就使用它。在内部,它们都分解为相同的方法,该方法打开一个InputStream 到资源。
  • @Andreas,我完全理解你在说什么,它没有在磁盘上创建物理对象这一事实与我的问题无关。是你不明白我的问题。

标签: java stream java-io filewriter


【解决方案1】:

主要原因是基于名为separation of concerns的架构范式。

如果您只是在处理这种特定情况,那么只需执行第二次调用并将两个操作封装在一行中就更简单了。但是从软件架构的角度来看,您正在通过一个操作解决两个不同的问题。第一个问题是定义和初始化输出。第二个是写入选择的输出。

这意味着如果将来你想改变你的应用程序以使用不同的输出,比如网络连接、控制台或其他,你将需要改变整个操作,因为网络连接不能被描述为字符串,比如文件。但是,如果您将 Writer 作为通用操作使用,它将始终收到一个初始化的输出流,将来您将不需要进行更改。

您的示例是一个简单的案例,所有关于软件架构的讨论都可能被视为有点复杂。但是,一旦您开始使用这种关注点分离的理念,您的代码就会更加一致,可能会更加冗长,但更加健壮。

【讨论】:

    【解决方案2】:

    在您的示例中,两个版本执行相同的操作。唯一真正的区别是代码可读性。 (由您决定您认为哪个版本更具可读性。)

    另一方面,如果您需要对文件路径名执行操作,最好使用FilePath 来执行此操作,而不是尝试使用字符串抨击来执行相同的操作。示例包括获取父目录路径、形成子目录路径、添加或删除文件名后缀。通过使用FilePath,您通常可以避免复杂性,例如路径名语法中特定于平台的差异。

    此外,FilePath(以及相关类)允许您对文件/目录本身进行其他操作。例如,重命名/移动、删除或测试和更改权限。

    简而言之,在其他 情况下,可能有充分的理由更喜欢使用File 等。但在你的例子中,它没有真正的区别。

    【讨论】:

    • 谢谢@Stephen C!好的和正常的答案。
    【解决方案3】:

    方法只是重载。主要是为了给用户提供一种更舒适的使用PrintWriter的方式。

    如果您的文件当前为File 对象,则可以直接传递它。 如果您将其命名为OutputStream,则可以使用它。 如果你有一个代表路径的String,就使用它等等。

    在内部,它们都分解为相同的方法,即打开一个OutputStream 到资源。

    假设您不是自己创建资源,而是从另一种方法获取它作为对象。如果该方法返回一个File 对象并且PrintWriter 没有这个额外的构造函数,那么您需要从文件对象中提取path。那是额外的一行代码,计算机科学家很懒惰......

    此外,主要构造函数将是使用OutputStream 的构造函数,因为这是最灵活的对象,它还允许打​​印到像网络资源或其他流这样的非文件内容。 如果您现在只想将一些行写入文件,那么额外的构造函数非常方便,并且可以节省一些代码。

    如果您只想在文件系统的给定位置创建一个新文件,请确定为什么不使用new PrintWriter(String path)。对于这种情况,它似乎很方便。但是,您可能不想将路径表示为String。可能目标位置是复杂且相对的,那么File 会更方便。就像new File("testFile", directory) 一样,它将文件创建到以File 给出的目录中,并带有相对路径。

    只需使用最适合您当前情况的构造函数即可。

    【讨论】:

    • 我明白你所说的一切,我同意..这就是我自己所知道的。问题是,如果我要创建一个新文件并简单地写入它,我为什么要通过 File 对象? - 其他情况对我来说很清楚,当然,可能是我从远程接口接收 File 对象等......问题完全是关于创建新的普通文件并在其中写入。我认为在后一种情况下,简化的 FileWriter 只是对开发人员的一种安慰。
    【解决方案4】:

    这是一种方便。检查构造函数的源代码。 (开放JDK实现)

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      相关资源
      最近更新 更多