新程序员需要学习的两个常见任务是如何读取和写入存储在计算机上的文件。一些示例包括在一个应用程序中创建的数据和配置文件需要被另一个应用程序读取,或者当第三个应用程序需要将信息、警告和错误写入日志文件或保存其结果以供他人使用时。
每种语言都有几种不同的读取和写入文件的方法。本文介绍 Groovy 编程语言 中的一些细节,该语言基于 Java,但具有不同的优先级,使 Groovy 感觉更像 Python。Groovy 新手首先看到的是它比 Java 简洁得多。下一个观察结果是它是(默认情况下)动态类型的。第三个是 Groovy 具有闭包,这有点像 Java 中的 lambda,但提供对整个封闭上下文的访问(Java lambda 限制了可以访问的内容)。
我的同事 Seth Kenlon 写了关于 Java 输入和输出 (I/O) 的文章。我将从他的 Java 代码出发,向您展示如何在 Groovy 中完成。
安装 Groovy
由于 Groovy 基于 Java,因此需要安装 Java。您可以在 Linux 发行版的存储库中找到最新且不错的 Java 和 Groovy 版本。或者您可以按照 Groovy 的下载页面上的说明安装 Groovy。Linux 用户的一个不错的替代方案是 SDKMan,您可以使用它来获取多个版本的 Java、Groovy 和许多其他相关工具。对于本文,我使用的是我的发行版的 OpenJDK11 版本和 SDKMan 的 Groovy 3.0.7 版本。
使用 Groovy 读取文件
首先回顾一下 Seth 的 Java 文件读取程序
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Ingest {
public static void main(String[] args) {
try {
File myFile = new File("example.txt");
Scanner myScanner = new Scanner(myFile);
while (myScanner.hasNextLine()) {
String line = myScanner.nextLine();
System.out.println(line);
}
myScanner.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} //try
} //main
} //class
现在我将用 Groovy 做同样的事情
def myFile = new File('example.txt')
def myScanner = new Scanner(myFile)
while (myScanner.hasNextLine()) {
def line = myScanner.nextLine()
println(line)
}
myScanner.close()
Groovy 看起来像 Java,但更简洁。首先要注意的是,所有这些 import
语句都已经完成了。由于 Groovy 的部分目的是作为一种脚本语言,因此通过省略周围的 class
和 public static void main
的定义,Groovy 将在后台构造这些东西。
分号也消失了。Groovy 支持使用它们,但除非您想在同一行上放置多个语句,否则不需要它们。还有单引号——Groovy 支持使用单引号或双引号来分隔字符串,这在您需要在字符串中放置双引号时很方便,就像这样
'"I like this Groovy stuff", he muttered to himself.'
另请注意,try...catch
消失了。Groovy 支持 try...catch
,但不需要它,它会给出非常好的错误消息和堆栈跟踪,就像 Java 示例中的 ex.printStackTrace()
调用一样。
Groovy 在 Java 提出 var
关键字之前很久就采用了 def
关键字和从语句右侧推断类型的功能,并且 Groovy 允许在任何地方使用它。但是,除了使用 def
之外,完成主要工作的代码看起来与 Java 版本非常相似。哦,是的,除了 Groovy 还内置了这种很好的元编程能力,除其他外,它允许您编写 println()
而不是 System.out.println()
。这种相似性远不止表面,它允许 Java 程序员非常快速地使用 Groovy。
就像 Python 程序员一直在寻找执行操作的 Pythonic 方式一样,有看起来像 Java 的 Groovy,然后还有……更 Groovy 的 Groovy。这解决了相同的问题,但使用 Groovy 的 with
方法使代码更 DRY(“不要重复自己”)并自动关闭输入文件
new Scanner(new File('example.txt')).with {
while (hasNextLine()) {
def line = nextLine()
println(line)
}
}
.with {
和 }
之间的是闭包体。请注意,您不需要编写 myScanner.hasNextLine()
或 myScanner.nextLine()
,因为 with
将这些方法直接暴露给闭包体。此外,with 消除了对 myScanner.close() 进行编码的需要,因此我们实际上根本不需要声明 myScanner。
运行它
$ groovy ingest1.groovy
Caught: java.io.FileNotFoundException: example.txt (No such file or directory)
java.io.FileNotFoundException: example.txt (No such file or directory)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at ingest1.run(ingest1.groovy:1)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
$
请注意“文件未找到”异常;这是因为还没有一个名为 example.txt
的文件。另请注意,这些文件来自 java.io
等。
所以我会写一些东西到那个文件中...
使用 Groovy 将数据写入文件
结合我之前分享的内容,嗯,变得“groovy”
new FileWriter("example.txt", true).with {
write("Hello world\n")
flush()
}
记住文件名后的 true
表示“追加到文件”,所以您可以运行几次
$ groovy exgest.groovy
$ groovy exgest.groovy
$ groovy exgest.groovy
$ groovy exgest.groovy
然后您可以使用 ingest1.groovy
读取结果
$ groovy ingest1.groovy
Hello world
Hello world
Hello world
Hello world
$
调用 flush()
是因为 with
/ write
组合在关闭之前没有进行刷新。 Groovy 并不总是更短!
Groovy 资源
Apache Groovy 网站有很多很棒的 文档。另一个很棒的 Groovy 资源是 Mr. Haki。学习 Groovy 的一个非常好的理由是学习 Grails,它是一个非常高效的全栈 Web 框架,建立在 Hibernate、Spring Boot 和 Micronaut 等优秀组件之上。
评论已关闭。