从源文件夹或JAR读取文本文件,具体取决于执行运行时

时间:2015-12-18 17:51:44

标签: java file jar inputstream

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

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

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

    目前我可以做一点没有问题,但是代码使用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());
    }
    

2 个答案:

答案 0 :(得分:0)

尝试获取与您的来源相关联的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());
    }
}

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

但这里的要点是能够从你的来源创建FileSystem,你可以做到;是的,你可以这样阅读罐子。请参阅here

答案 1 :(得分:0)

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

我首先检查文本文件是否可以正常找到(从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