【问题标题】:How can I create a directory structure that includes copies of particular files?如何创建包含特定文件副本的目录结构?
【发布时间】:2016-09-20 06:43:44
【问题描述】:

我正在编写将项目保存在选定目录中所需的程序。每个项目目录都必须包含一个 HTML 文件,该文件可能具有不同的元素,具体取决于项目的状态,以及子目录中的 JavaScript 文件标准库。

我不熟悉这通常在 Java 中完成的方式(或者甚至在理论上如何完成)。是否有适合此任务的特定工具、技术或库?请注意,我使用 Eclipse 作为我的 IDE。我一直在考虑使用某种模板生成所需的文件,和/或从包中提取它们,但我对这类问题很陌生,不知道如何从这里开始。

编辑:进一步阐述

我的项目是一个供我个人使用的小型实用程序,因此可维护性不是什么大问题。我正在使用 Java 8。在每个用户创建的项目中,库中只有三个不变的 .js 文件和一个将在浏览器中启动以运行脚本的小 html 文件,以及一个用户生成的 .js 文件。非常基本的东西。

编辑:问题已解决...我认为

我已经提出了自己的部分解决方案,我想我可以从这里解决剩下的问题,但 D.B. 的帖子仍然内容丰富且很有帮助,所以我接受它作为答案。

我意识到我最初的问题不够具体。我希望隐藏我的静态脚本资源和 HTML 文件的模板,以便无法从文件系统直接访问它们。我一直在考虑将它们放在与应用程序 jar 位于同一目录中的某种包文件中。然而,我没想到我可以简单地将它们放在 jar 本身的资源文件夹中。

在用户指定的项目目录中创建库目录:

libraryDir = projectDir.resolve("libraries");
new File(libraryDir.toUri()).mkdirs(); // Create libraries directory

// Unpack library resources to project
unpackLibrary("file1.js");
unpackLibrary("file2.js");
unpackLibrary("file3.js");

unpackLibrary 函数:

private void unpackLibrary(String scriptName) {
    String resourcePath = "/libraries/" + scriptName;

    Path fileName = Paths.get(resourcePath).getFileName();
    try (InputStream in = getClass().getResourceAsStream(resourcePath);) {
        Files.copy(in, libraryDir.resolve(fileName));
    }
    catch (FileAlreadyExistsException e) {
        System.out.println("File unpack failed: File already exists (" + e.getFile() + ")");
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}

应用程序将使用临时目录中的项目,直到用户决定保存它,在这种情况下,我将使用 D.B. 的建议将项目文件复制到新目录。

【问题讨论】:

    标签: java eclipse templates filesystems package


    【解决方案1】:

    如何进行完全取决于您和您的项目要求。这实际上取决于这些文件的用途、它们的维护方式等。使用模板似乎是一个很好的解决方案,因为那时您可以在生成一组新项目时简单地替换模板中的变量/令牌文件。这些模板是否以某种方式打包/压缩取决于您。如果您有充分的理由打包或压缩它们,那么就这样做,如果没有,那么真的没有理由需要它们。

    如果您确实使用模板,基本技术将是:读取模板,通过将变量/标记替换为值来处理模板,将结果数据写入新文件。

    如果您使用 Java 1.7 或更高版本,请查看 java.nio 包和 tutorial for Java file I/O featuring NIO,因为它非常好,将帮助您了解 API 以及如何使用它来操作文件。

    希望这有助于您入门。

    编辑 -- 这是我在评论中承诺的更新:

    据我了解,程序必须将一组静态文件复制到一个新目录中。由于您有一个“项目”概念,我不认为代码应该替换现有文件,所以如果项目文件已经存在,这个程序将失败。

    假设:

    1. 静态模板文件将驻留在应用程序 jar 文件的当前工作目录中的文件夹中。也就是说,如果您的可执行 jar 位于文件夹 C:\MyProgram(假设是 Windows 文件系统)中,那么您的模板将存在于该文件夹内的文件夹中 - 例如 C:\MyProgram\templates。
    2. 程序应创建整个目录树结构,直至并包括“项目”文件夹。

    代码如下:

    SaveProjectFolderMain.java

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class SaveProjectFolderMain {
    
        //Note: In eclipse your templates folder must be inside the eclipse project's root directory 
        //      in order for this path to be correct. E.g. myProject/templates
        //      If this program is run outside of eclipse it will look for a templates folder
        //      in the current working directory - the directory in which the jar resides.
        //      E.g. if you jar lives in C:\myProgram then your templates should live in
        //      C:\myProgram\templates (obviously this is a Windows file system example)
        private static final Path TEMPLATES_DIR = Paths.get("templates");
    
        public static void main(String[] args) {
            //Copies the template files to a new folder called "testProject"
            // creating the project folder if it does not exist.
            saveProjectDir(Paths.get("testProject"));
        }
    
        public static void saveProjectDir(Path dirToSaveTo){
            try {
                if(!Files.exists(dirToSaveTo)){
                    System.out.println("The directory " + dirToSaveTo.toAbsolutePath() + " does not exist, it is being created.");
                    Files.createDirectories(dirToSaveTo);
                }
                Files.walkFileTree(TEMPLATES_DIR, new CopyFileVisitor(dirToSaveTo));
            } catch (IOException e) {
                System.err.println("Unable to copy template files to the save location: " + dirToSaveTo.toAbsolutePath());
                e.printStackTrace();
            }
        }
    
    }
    

    CopyFileVisitor.java

    import java.io.IOException;
    import java.nio.file.FileVisitResult;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.attribute.BasicFileAttributes;
    
    public class CopyFileVisitor extends SimpleFileVisitor<Path> {
        private final Path targetPath;
        private Path sourcePath = null;
    
        public CopyFileVisitor(Path targetPath) {
            this.targetPath = targetPath;
        }
    
        @Override
        public FileVisitResult preVisitDirectory(final Path dir,
                final BasicFileAttributes attrs) throws IOException {
            if (sourcePath == null) {
                sourcePath = dir;
            } else {
                Path destDir = targetPath.resolve(sourcePath.relativize(dir));
                System.out.println("Creating directory: " + destDir);
                Files.createDirectories(destDir);
            }
            return FileVisitResult.CONTINUE;
        }
    
        @Override
        public FileVisitResult visitFile(final Path file,
                final BasicFileAttributes attrs) throws IOException {
            Path destFilePath = targetPath.resolve(sourcePath.relativize(file));
            System.out.println("Copying " + file.toAbsolutePath() + " to " + destFilePath.toAbsolutePath());
            Files.copy(file, destFilePath);
            return FileVisitResult.CONTINUE;
        }
    }
    

    【讨论】:

    • 谢谢,很高兴知道我至少没有走错路太远。可维护性不是什么大问题,因为我的项目只是一个小型个人项目,为我自己的方便创建了一个实用程序。我只是希望在此过程中学到一些东西并尝试遵循良好的做法。我将更新我的问题以更好地反映我的项目要求。
    • 很高兴我能帮上忙!对于可维护性不是什么大问题,我不得不稍有不同意,因为您永远不知道什么时候会想到要添加的出色新功能或发现需要修复的错误。正如我的教授在大学时告诉我们的那样——好的课程永远不会完成。如果您编写好代码并编写好的 cmets,您会发现以后很容易跳回并更新、添加或修复内容。我将根据您的更新更新我的帖子以提供示例解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    • 2023-03-30
    • 2015-07-09
    相关资源
    最近更新 更多