1

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

4

4 回答 4

4

这是我再次更新的 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());
    }
}
于 2009-03-06T00:11:07.357 回答
4

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

我选择在无效行的情况下抛出异常,您可以像他最初所做的那样简单地返回 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);
     }
}
于 2009-03-06T17:15:06.973 回答
2

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

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

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

希望有帮助..

于 2009-03-06T00:52:59.347 回答
0

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

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

于 2009-03-06T00:02:55.440 回答