java - 尝试使用带有 Streams 的 Java 8 解析 /etc/passwd
问题描述
我正在尝试使用 Java 1.8 的流功能解析 macOS Mojave 10.14.3 操作系统上的 /etc/passwd 文件。
我的 /etc/passwd 文件中的前五行如下:
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
_uucp:*:4:4:Unix to Unix Copy
Protocol:/var/spool/uucp:/usr/sbin/uucico
_taskgated:*:13:13:Task Gate Daemon:/var/empty:/usr/bin/false
这是我的实现:
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class User {
String name;
Integer uid;
Integer gid;
String comment;
String home;
String shell;
public User(String filePath) {
String[] items = filePath.split(":");
if (items.length != 7) {
throw new IllegalArgumentException("Need 7 items from file and there's only: " + items.length);
}
this.name = items[0];
this.uid = Integer.parseInt(items[2]);
this.gid = Integer.parseInt(items[3]);
this.comment = items[4];
this.home = items[5];
this.shell = items[6];
}
// Getters and Setters omitted for brevity.
public static void main(String[] args) {
// Read the file
try (Stream<String> stream = Files.lines(Paths.get("/etc/passwd")))
{
ArrayList<User> users = stream.map(User::new).filter(u -> !u.shell.equals("/bin/false"))
.filter(u -> !u.shell.equals("/usr/sbin/nologin"))
.collect(Collectors.toCollection(ArrayList::new));
for (User user : users) {
System.out.println("User: " + user.name);
}
}
catch(Throwable t) {
t.printStackTrace();
}
}
}
非法参数异常:
java.lang.IllegalArgumentException: Need 7 items from file and there's only: 1
at com.sample.model.User.<init>(User.java:23)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.sample.model.User.main(User.java:88)
问题):
我可能做错了什么?
除了使用 Java 1.8 的 Streams 功能,还有其他方法可以做到这一点吗?似乎Streams更难调试......
解决方案
我认为您需要考虑注释行/以“#”开头的行。
所以:
ArrayList<User> users = stream.filter(s -> s.charAt(0) != '#')
.map(User::new)
.filter(u -> !u.shell.equals("/bin/false"))
.filter(u -> !u.shell.equals("/usr/sbin/nologin"))
.collect(Collectors.toCollection(ArrayList::new));
关于您的观点:调试-是的-工具还不是很好(还)。您可能已经通过检查filePath
传递给 User 构造函数并观察它是注释来发现这一点。
推荐阅读
- forms - Squarespace:表单提交失败:使用 JavaScript 成功处理表单数据后,表单未提交到 Mailchimp
- java - 为什么这种休眠关系不起作用?
- imagemagick - 如何将 ZLIB 的路径传递给 ImageMagick?
- python - Django manage.py migrate ValidationError
- c# - android.runtime.JavaProxyThrowable 在某些 android 设备上的应用程序 initialized() 异常
- android - 发布构建失败并出现 java.lang.RuntimeException:无法启动活动 ComponentInfo - React Native - Android
- javascript - Javascript拼接方法中的奇怪错误
- python - 以多节点方式获取 TensorFlow 中使用的 GPU 数量
- android-tablayout - 当标签页超过 64 个时,如何消除 Android TV 中的 TabLayout 滚动跳跃(跳过)?
- sql - SQL查询:没有聚合函数时如何创建小计行