【问题标题】:Is there a Java package to read the UNIX /etc/group file?是否有用于读取 UNIX /etc/group 文件的 Java 包?
【发布时间】:2009-03-05 23:29:14
【问题描述】:

我一直在 Internet 上搜索一个 Java 包/类,它可以让我解析 UNIX /etc/group 文件。虽然从头开始写这个真的不会那么难,但我很惊讶没有找到已经存在的东西。有一个 POSIX passwd 类(请参阅http://www.bmsi.com/java/posix/docs/posix.Passwd.html),但我没有为 /etc/group 找到类似的类。有这种事吗?

【问题讨论】:

标签: java class posix


【解决方案1】:

这是我再次更新的 tofubeer 更新的代码。他的没有编译。缺少 InvalidGroupException 类。此外,没有指定包。将 EMPTY_LIST 切换为 emptyList() 以避免缺少参数化。

package fileutils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class GroupReader2 {
    public static class InvalidGroupException extends Exception {
        private static final long serialVersionUID = 1L;

        public InvalidGroupException(String string) {
            super(string);
        }
    }

    public static GroupReader2 parseGroup(final String groupLine)
            throws InvalidGroupException {
        final String line;
        final String[] parts;

        if (groupLine == null) {
            throw new IllegalArgumentException("groupLine cannot be null");
        }

        line = groupLine.trim();

        if (line.startsWith("#") || line.isEmpty()) {
            return null;
        }

        parts = line.split(":");

        if (parts.length < 3) {
            throw new InvalidGroupException(groupLine
                    + "must be in the format of name:passwd:gid[:userlist]");
        }

        try {
            final GroupReader2 group;
            final String name;
            final String passwd;
            final int gid;
            final List<String> userList;

            name = parts[0];
            passwd = parts[1];
            gid = Integer.parseInt(parts[2]);

            if (parts.length == 4) {
                userList = Arrays.asList(parts[3].split(","));
            } else {
                userList = Collections.emptyList();
            }

            group = new GroupReader2(name, passwd, gid, userList);

            return group;
        } catch (final NumberFormatException ex) {
            throw new InvalidGroupException(groupLine + " gid must be a number");
        }
    }

    private final int gid;
    private final String name;
    private final String passwd;

    private final List<String> userList;

    public GroupReader2(final String nm, final String pw, final int id,
            final List<String> users) {
        name = nm;
        passwd = pw;
        gid = id;
        userList = Collections.unmodifiableList(new ArrayList<String>(users));
    }

    public int getGid() {
        return (gid);
    }

    public String getName() {
        return (name);
    }

    public String getPasswd() {
        return (passwd);
    }

    public List<String> getUserList() {
        return (userList);
    }

    @Override
    public String toString() {
        final StringBuilder sb;

        sb = new StringBuilder();
        sb.append(name);
        sb.append(":");
        sb.append(passwd);
        sb.append(":");
        sb.append(gid);
        sb.append(":");

        for (final String user : userList) {
            sb.append(user);
            sb.append(",");
        }

        sb.setLength(sb.length() - 1);

        return (sb.toString());
    }
}

【讨论】:

  • 不错。两个小问题:(1)Vector 是古老的,考虑 ArrayList 代替; (2) Setter 具有误导性,因为您提供的是只读访问权限。
  • 你的小东西上的小东西,ArrayList 不应该是变量类型,而是将变量声明为 List。还要将变量设为final,set方法不会编译。
  • @TofuBeer 所有的变量都已经是 List 了,还有什么不能编译?我在发布之前针对我自己的 /etc/groups 运行了这个。
  • 只是对 nits 做出响应...但将 gid、name、passwd 和 userlist 设为最终状态(并去掉 Group() 构造函数)。对于列表,我只是回复 jdigitals nits :-)
  • @TofuBeer 哦,好的,我明白了,对不起。如果我将成员变量设为 final,它将无法编译,因为 parseGroup 需要设置它们。我会摆脱构造函数,但有人可能想用它来构造一个组文件,而不是仅仅读取一个。
【解决方案2】:

这是 John Ellinwood 提供的代码,但更安全(编辑:添加了 Johns 的更改,略有不同,以保持与 cmets 的同步。很高兴看到两个人如何实现相同类型的代码)。

我选择在无效行的情况下抛出异常,您可以像他最初所做的那样简单地返回 null (我看不出使用包含错误数据的文件的意义......)。

唯一“必须做”的更改是将 userList 包装为 UnmodifableList(或返回列表的新副本),否则此方法的恶意用户可能会向 userList 添加内容(调用 getUserList,然后继续将项目添加到它或从中删除项目)。

由于 Group 类是不可变的(所有实例变量都是最终变量),因此不必担心它们会被调用者更改。

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Group
{
    private final int gid;
    private final String name;
    private final String passwd;
    private final List<String> userList;

    public static Group parseGroup(final String groupLine)
        throws InvalidGroupException
    {
        final String   line;
        final String[] parts;

        if(groupLine == null)
        {
            throw new IllegalArgumentException("groupLine cannot be null");
        }

        line = groupLine.trim();

        if(line.startsWith("#") || line.isEmpty())
        {
             return null;
        }

        parts = line.split(":");

        if(parts.length < 3)
        {
            throw new InvalidGroupException(groupLine + "must be in the format of name:passwd:gid[:userlist]", line);
        }

        try
        {
            final Group        group;
            final String       name;
            final String       passwd;
            final int          gid;
            final List<String> userList;

            name   = parts[0];
            passwd = parts[1];
            gid    = Integer.parseInt(parts[2]);

            if(parts.length == 4)
            {
                userList = Arrays.asList(parts[3].split(","));
            }
            else
            {
                userList = Collections.emptyList();
            }

            group = new Group(name, passwd, gid, userList);

            return group;
        }
        catch(final NumberFormatException ex)
        {
            throw new InvalidGroupException(groupLine + " gid must be a number", line);
        }
    }

    public Group(final String nm, final String pw, final int id, final List<String> users)
    {
        name     = nm;
        passwd   = pw;
        gid      = id;
        userList = Collections.unmodifiableList(new ArrayList<String>(users));
    }

    public int getGid()
    {
        return (gid);
    }

    public String getName()
    {
        return (name);
    }

    public String getPasswd()
    {
        return (passwd);
    }

    public List<String> getUserList()
    {
        return (userList);
    }

    @Override
    public String toString()
    {
        final StringBuilder sb;

        sb = new StringBuilder();
        sb.append(name);
        sb.append(":");
        sb.append(passwd);
        sb.append(":");
        sb.append(gid);
        sb.append(":");

        for(final String user : userList)
        {
            sb.append(user);
            sb.append(",");
        }

        sb.setLength(sb.length() - 1);

        return (sb.toString());
    }
}

public class InvalidGroupException
    extends Exception
{
     private static final long serialVersionUID = 1L;
     private final String line;

     public InvalidGroupException(final String msg, final String ln)
     {
         super(msg);

         line = ln;
     }

     public String getLine()
     {
         return (line);
     }
}

【讨论】:

  • 不编译。缺少 InvalidGroupException 类。此外,没有指定包。将 EMPTY_LIST 切换为 emptyList() 以避免缺少参数化。
  • 包不是必需的(总是一个很好的做法,但我不打扰这样的示例代码)。
【解决方案3】:

如果您要在除您自己的机器之外的任何地方运行该程序,那么阅读 /etc/group 并不是一个好主意。

现实世界使用 nis/ldap 等来保存所有这些信息..

你可能想用 JNI 封装 getpwent / getgrent 系列 你可能会得到一些包装这些的 posix 实现。

希望对您有所帮助..

【讨论】:

  • 正是我所建议的那种事情......毕竟,这些 C 库已经知道如何访问适当的文件。
【解决方案4】:

Java 是独立于机器的,我对此并不感到惊讶。你指的班级不标准。

我认为与向所有人隐藏 /etc/group 文件的原因相同,可以为我们理解 java 不提供它的原因提供线索。

【讨论】:

  • 我当然同意 Java 不提供内置类是可以理解的。令我惊讶的是,在 Internet 上的某个地方不存在这样的第三方类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多