尝试使用带有Streams的Java 8解析/ etc / passwd

问题描述 投票:-3回答:1

我试图使用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();
        }   
    }
}

抛出:IllegalArgumentException:

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)

问题(S):

  1. 我可能做错了什么?
  2. 有没有不同的方法来实现这一点,而不是使用Java 1.8的Streams功能?似乎Streams更难调试......
java unix stream java-stream
1个回答
1
投票

我认为您需要考虑注释/以'#'开头的行。

所以:

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

关于你的观点:调试 - 是的 - 工具还不是很好(还)。您可能已经通过检查传递给User构造函数的filePath并观察它是注释来捕获这一点。

© www.soinside.com 2019 - 2024. All rights reserved.