如何允许用户在 JFileChooser 对话框中输入 Windows 环境变量

How to allow a user to enter Windows Environment Variables in a JFileChooser dialog

我正在为我的 Java GUI 使用 JFileChooser,以允许用户浏览要导入的文件。我正在使用 TestComplete 为我的程序创建一些测试,并且需要能够在 JFileChooser window "File Name:" 文本字段中使用环境变量。

例如,我希望能够在 "File Name:" 文本框中输入以下行...

%TEST_FILES%\file_set_1\testfile.xml

有谁知道如何让 JFileChooser 接受 Windows 环境变量。

我希望能够使用环境变量的原因是因为 TestComplete 测试将在各种计算机上进行 运行,并且每个人的测试文件都可能位于不同的位置。

也许你可以动态生成一个批处理脚本然后执行它?

为什么不直接询问用户文件在哪里?

JFileChooser 不会自动执行此操作,但您可以通过解释从接受处理程序中的 JFileChooser 返回的文件名字符串的内容来自己执行此操作。

所以我们有一个例程来获取所有的环境变量,为了更容易匹配,它们都变成了小写:

private Map<String, String> getEnv() {
    Map<String, String> fromEnv = System.getenv();
    Map<String, String> toReturn = new HashMap<>();
    for (String key : fromEnv.keySet()) {
        toReturn.put(key.toLowerCase(), fromEnv.get(key));
    }
    return toReturn;
}

这将由扩展文件名的例程使用,这相对简单 - 只需找到 %VAR% 项并替换它们。在变量不匹配的情况下,直接打断,让字符串部分解析。

private String expandFileName(String filename) {
    Pattern p = Pattern.compile("%([^%]*)%");
    Matcher m = p.matcher(filename);
    Map<String, String> env = getEnv();
    while (m.find()) {
        String var = m.group(1);
        String value = env.get(var.toLowerCase());
        if (value != null) {
            filename = filename.replaceAll("%" + var + "%",
                    Matcher.quoteReplacement(value));
        } else {
            return filename;
        }
        m = p.matcher(filename);
    }
    return filename;
}

接下来,我们需要使用JFileChooser的一个子类来处理尝试使用文件名,所以我们需要重写approveSelection方法,获取文件名,展开它并尝试确定文件有问题。因为这段代码将在打开的对话框中使用,所以我在接受例程中采取了一些自由,它要求文件存在而不是返回文件的扩展名。

public void approveSelection() {
    File f = getSelectedFile();
    // remove the CWD from the string - leaving the text from the edit box
    String prena = f.toString().replace(getCurrentDirectory().toString() + File.separator, "");
    String name = expandFileName(prena);
    if (prena.equals(name)) {
        if (!f.exists()) {
            return;
        }
        // This expanded to the same, and the file is there
        super.approveSelection();
        return;
    }
    // try to use the name
    f = new File(name);
    if (f.isFile()) { // file, ok
        setSelectedFile(f);
        super.approveSelection();
    } else if (f.isDirectory()) { // change to dir
        setCurrentDirectory(f);
        return;
    } else if (!f.exists()) { // try with cwd and name in field
        f = new File(getCurrentDirectory(), name);
        if (f.exists()) {
            setSelectedFile(f);
            super.approveSelection();
        }
    }
}

逻辑相当复杂,但重点是尽量抓住您会考虑的大部分条件。

总而言之,您必须手动完成,但所需的工作量确实不多。

然后您可以将它们全部粘合成一个:

JFileChooser chooser = new JFileChooser() {
    // put in all the routines as listed earlier
};
chooser.setAcceptAllFileFilterUsed(true);
int choice = chooser.showOpenDialog(null);
if (choice == JFileChooser.APPROVE_OPTION) {
    String name = chooser.getSelectedFile().getAbsolutePath();
    System.out.println(name);
}