如何创建包含特定文件副本的目录结构?
How can I create a directory structure that includes copies of particular files?
我正在编写一个程序,需要将项目保存在选定的目录中。每个项目目录都必须包含一个 HTML 文件,该文件可能具有不同的元素,具体取决于项目的状态,以及子目录中 Java 脚本文件的标准库。
我不熟悉在 Java 中通常会用什么方法来完成(甚至在理论上是如何完成的)。是否有适合这项任务的特定工具、技术或库?请注意,我使用 Eclipse 作为 IDE。我一直在考虑使用某种模板生成所需的文件,and/or 从包中提取它们,但我对这类问题还很陌生,不确定如何从这里开始。
编辑:进一步阐述
我的项目是供我个人使用的小型实用程序,因此可维护性不是什么大问题。我正在使用 Java 8。在每个用户创建的项目中,库中只有三个不变的 .js 文件和一个将在浏览器中启动到 运行 的小 html 文件脚本,以及用户生成的 .js 文件。非常基本的东西。
编辑:问题已解决...我认为
我已经提出了我自己的部分解决方案,我想我可以从这里找到其余的解决方案,但是 D.B. 的 post 仍然提供了信息和帮助,所以我我接受它作为答案。
我意识到我原来的问题不够具体。我希望隐藏我的静态脚本资源和 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 的建议将项目文件复制到新目录。
如何进行完全取决于您和您的项目要求。这实际上取决于这些文件的用途、维护方式等。使用模板似乎是一个很好的解决方案,因为这样您就可以在生成新集时简单地替换模板中的 variables/tokens的项目文件。这些模板是否以某种方式 packaged/zipped 再次取决于您。如果您有充分的理由打包或压缩它们,那么就这样做,如果没有,那么就真的没有理由需要它们。
如果您使用模板,基本技术是:读取模板,通过用值替换 variables/tokens 来处理模板,将结果数据写入新文件。
如果您使用的是 Java 1.7 或更高版本,请查看 java.nio 软件包和 tutorial for Java file I/O featuring NIO,因为它非常好,可以帮助您理解 API 以及如何使用它来操作文件。
希望这有助于您入门。
编辑——这是我在评论中承诺的更新:
据我了解,该程序必须将一组静态文件复制到一个新目录中。因为你有一个 "project" 的概念,我不认为代码应该替换现有文件,所以如果项目文件已经存在,这个程序将失败。
假设:
- 静态模板文件将驻留在应用程序 jar 文件的当前工作目录中的文件夹中。也就是说,如果您的可执行 jar 位于文件夹 C:\MyProgram 中(假设一个 Windows 文件系统),那么您的模板将存在于该文件夹内的一个文件夹中 - 例如 C:\MyProgram\templates。
- 程序应创建整个目录树结构,包括 "project" 文件夹。
代码如下:
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;
}
}
我正在编写一个程序,需要将项目保存在选定的目录中。每个项目目录都必须包含一个 HTML 文件,该文件可能具有不同的元素,具体取决于项目的状态,以及子目录中 Java 脚本文件的标准库。
我不熟悉在 Java 中通常会用什么方法来完成(甚至在理论上是如何完成的)。是否有适合这项任务的特定工具、技术或库?请注意,我使用 Eclipse 作为 IDE。我一直在考虑使用某种模板生成所需的文件,and/or 从包中提取它们,但我对这类问题还很陌生,不确定如何从这里开始。
编辑:进一步阐述
我的项目是供我个人使用的小型实用程序,因此可维护性不是什么大问题。我正在使用 Java 8。在每个用户创建的项目中,库中只有三个不变的 .js 文件和一个将在浏览器中启动到 运行 的小 html 文件脚本,以及用户生成的 .js 文件。非常基本的东西。
编辑:问题已解决...我认为
我已经提出了我自己的部分解决方案,我想我可以从这里找到其余的解决方案,但是 D.B. 的 post 仍然提供了信息和帮助,所以我我接受它作为答案。
我意识到我原来的问题不够具体。我希望隐藏我的静态脚本资源和 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 的建议将项目文件复制到新目录。
如何进行完全取决于您和您的项目要求。这实际上取决于这些文件的用途、维护方式等。使用模板似乎是一个很好的解决方案,因为这样您就可以在生成新集时简单地替换模板中的 variables/tokens的项目文件。这些模板是否以某种方式 packaged/zipped 再次取决于您。如果您有充分的理由打包或压缩它们,那么就这样做,如果没有,那么就真的没有理由需要它们。
如果您使用模板,基本技术是:读取模板,通过用值替换 variables/tokens 来处理模板,将结果数据写入新文件。
如果您使用的是 Java 1.7 或更高版本,请查看 java.nio 软件包和 tutorial for Java file I/O featuring NIO,因为它非常好,可以帮助您理解 API 以及如何使用它来操作文件。
希望这有助于您入门。
编辑——这是我在评论中承诺的更新:
据我了解,该程序必须将一组静态文件复制到一个新目录中。因为你有一个 "project" 的概念,我不认为代码应该替换现有文件,所以如果项目文件已经存在,这个程序将失败。
假设:
- 静态模板文件将驻留在应用程序 jar 文件的当前工作目录中的文件夹中。也就是说,如果您的可执行 jar 位于文件夹 C:\MyProgram 中(假设一个 Windows 文件系统),那么您的模板将存在于该文件夹内的一个文件夹中 - 例如 C:\MyProgram\templates。
- 程序应创建整个目录树结构,包括 "project" 文件夹。
代码如下:
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;
}
}