【问题标题】:Read text files from source folder OR JAR depending on execution runtime根据执行运行时从源文件夹或 JAR 中读取文本文件
【发布时间】:2015-12-18 17:51:44
【问题描述】:

我的程序显示从文本文件中读取的元素。文本文件将存储在包含 .java.class 文件的包文件夹中的文件夹中,以便它们可以嵌入到 jar 中。

我正在尝试让应用程序在这两种情况下都能正确读取文本文件

  1. 从 IDE (Netbeans) 运行
  2. 从 JAR 运行

目前我可以毫无问题地完成第一点,但代码使用File 读取,而我看到如何使用Jars 执行此操作的方式是使用InputStream

适用于 IDE 的函数运行

public void loadWidgets() {

    ArrayList<String> results = new ArrayList<>();
    String dir = new File("").getAbsolutePath() + "/src/Creator/textFiles/widgets/;
    System.out.println(dir);
    getWidgetFiles(dir, results);

    results.stream().forEach((s) -> {
        readFile(s); // given a string and it opens the file using a Scanner
    });

    updateWidgetVariables(); // gui updates
}

public void getWidgetFiles(String dirName, ArrayList<String> filePaths) {

    File directory = new File(dirName);
    File[] files = directory.listFiles();

    for (File file : files) {
        if (file.isFile()) {
            filePaths.add(file.getName() + "," + file.getAbsolutePath());
        } else if (file.isDirectory()) {
            getWidgetFiles(file.getAbsolutePath(), filePaths);
        }
    }
}

所以我有一堆按小部件类型组织的文本文件,所以我在 /widgets/ 目录中运行以查找所有文本文件。

我遇到的问题是如何浏览 Jar 的目录和文件?它们可以转换为文件,还是读入字符串?

我从question 获得了这个代码,它可以读取文件,但我不知道如何使用new Scanner(file); 代码打开它们

CodeSource src = WidgetPanel.class.getProtectionDomain().getCodeSource();
try {
    System.out.println("Inside try");
    List<String> list = new ArrayList<>();
    if (src != null) {
        URL jar = src.getLocation();
        ZipInputStream zip = new ZipInputStream(jar.openStream());
        ZipEntry ze = null;
        System.out.println(jar.getPath());
        System.out.println(zip.getNextEntry());

        while ((ze = zip.getNextEntry()) != null) {
            String entryName = ze.getName();
            System.out.println("Entry name: " + entryName);
            if (entryName.startsWith("Creator/textFiles/widgets") && entryName.endsWith(".txt")) {
                list.add(entryName);
                System.out.println("Added name: " + entryName);
            }
        }
        list.stream().forEach((s) -> {
            readFile(s);
        });

        updateWidgetVariables();

    } else {
        System.out.println("Src null");
    }
}catch (IOException e) {
    System.out.println(e.getMessage());
}

【问题讨论】:

  • Java 的哪个版本?
  • 你可以直接用 unzip 解压 jar 或者使用docs.oracle.com/javase/tutorial/deployment/jar/view.html
  • @fge 版本 8 在 NorbertvanNobelen 我不明白这有什么帮助? jar运行时需要读取文件,不需要查看文件。
  • 嗯,这当然有帮助;你知道 JSR 203 的存在吗?
  • 在发布之前查看类似主题时从未见过提及它。对我的情况有帮助吗?

标签: java file jar inputstream


【解决方案1】:

尝试获取与您的来源相关联的FileSystem;事情就变得很简单了。以下是如何以文本形式读取给定文件系统中的所有文件的说明:

private static final BiPredicate<Path, BasicFileAttributes> FILES
    = (path, attrs) -> attrs.isRegularFile();

private static void readAllFilesAsText(final List<Path> paths)
    throws IOException
{
    for (final Path path: paths)
        try (
            final Stream<String> stream = Files.lines(path);
        ) {
            stream.forEach(System.out::println);
        }
}

private static List<Path> getAllFilesFromFileSystems(final FileSystem fs,
    final String pathPrefix)
{
    final Path baseDir = fs.getPath(pathPrefix);

    try (
        final Stream<Path> files = Files.find(baseDir, Integer.MAX_VALUE,
            FILES);
    ) {
        return files.collect(Collectors.toList());
    }
}

为什么要混合使用“旧式”for 循环和“新式”lambda:这是因为 lambda 不处理已检查的异常……这意味着您必须这样做。有关解决方法,请参阅here

但这里的要点是能够从您的资源中创建一个FileSystem,并且您可以做到;是的,你可以这样阅读罐子。见here

【讨论】:

    【解决方案2】:

    我能够使用已有的功能找到解决方案。

    我首先检查是否可以正常找到文本文件(从 IDE 运行)。如果出现文件未找到异常,它会设置 ide = false 以便尝试从 jar 中读取。

    public void loadWidgets() {
    
        boolean ide = true;
        String path = "textFiles/widgets/";        
        ArrayList<String> results = new ArrayList<>();
        String dir = new File("").getAbsolutePath() + "/src/Creator/" + path;
    
        try {
            getWidgetFiles(dir, results);
    
            results.stream().forEach((s) -> {
                readFile(s);
            });
    
            updateWidgetVariables();
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            ide = false;
        }
    
    
        if (!ide) {
            CodeSource src = WidgetPanel.class.getProtectionDomain().getCodeSource();
            try {                
                List<String> list = new ArrayList<>();
                if (src != null) {
                    URL jar = src.getLocation();
                    ZipInputStream zip = new ZipInputStream(jar.openStream());
                    ZipEntry ze = null;                    
    
                    while ((ze = zip.getNextEntry()) != null) {
    
                        String entryName = ze.getName();                        
                        if (entryName.startsWith("Creator/textFiles/widgets") && entryName.endsWith(".txt")) {
                            // Wouldnt work until i added the "/" before the entryName
                            list.add("/"+ entryName);
                            System.out.println("Added name: " + entryName);
                        }
                    }
                    list.stream().forEach((s) -> {
                        readJarFile(s);
                    });
    
                    updateWidgetVariables();
    
                } else {
                    System.out.println("Src null");
                }
    
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

    然后我创建了一个新的 readFile 函数来从 Jar 中读取数据

    public void readJarFile(String result) {
    
        String name = result.substring(result.lastIndexOf("/") + 1);
        String entireWidget = "";
        String line;
    
        ArrayList<String> vars = new ArrayList<>();
        int begin, end;
    
        InputStream loc = this.getClass().getResourceAsStream(result);
        try (Scanner scan = new Scanner(loc)) {
            while (scan.hasNextLine()) {
                line = scan.nextLine();
                entireWidget += line;
    
                while (line.contains("`%")) {
    
                    begin = line.indexOf("`%");
                    end = line.indexOf("%`") + 2;
                    vars.add(line.substring(begin, end));
                    //System.out.println("Variable added: " + line.substring(begin, end));
                    line = line.substring(end);
                }
    
            }
        }
        System.out.println(name + ": " + entireWidget);
        Widget widget = new Widget(name, vars, entireWidget, result);
        widgetList.put(name, widget);
    
    }
    

    这个答案大部分归功于question

    【讨论】:

      猜你喜欢
      • 2020-02-27
      • 1970-01-01
      • 2011-10-11
      • 2016-03-03
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      相关资源
      最近更新 更多