如何将文件保存到类路径中

15
我该如何保存/加载一个位于我的类所在位置的文件?我不知道那个位置的物理路径,我想要动态地查找该文件。
我想要加载一个XML文件并对其进行读写操作,但不确定如何访问它。

2
这是您在构建过程中想要执行的操作吗(例如,ant构建)? - CoolBeans
1
基本上,我有一个 XML 文件需要读取和写入,但我不确定应该将文件路径放在哪个方法中。 - Doron Sinai
6个回答

40

使用ClassLoader#getResource()getResourceAsStream()从类路径获取它们作为URLInputStream

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/file.ext");
// ...

如果它与当前类在同一个包中,也可以按以下方式获取:

InputStream input = getClass().getResourceAsStream("file.ext");
// ...

保存文件是另外一回事。如果文件位于JAR文件中,则此方法无法工作。如果您可以确保文件已扩展并且可以写入,则可以将getResource()返回的URL转换为File

URL url = classLoader.getResource("com/example/file.ext");
File file = new File(url.toURI().getPath());
// ...

然后您可以使用它构造一个FileOutputStream

相关问题:


3
еҰӮжһңж–Ү件дёҚеӯҳеңЁпјҢи°ғз”Ёurl.toURI()дјҡеҜјиҮҙNullPointerExceptionгҖӮ - naXa stands with Ukraine
3
@naXa: 是正确的。如果你不确定,事先检查一下 url 是否为 null。对于任何你试图使用点号运算符 . 访问的其他 Java 变量来说,情况都是一样的。每个自重的 Java 开发者都知道这一点。 - BalusC
这个问题回答了如何更新一个存在于类路径上的文件,但是由于getResource返回null,它不允许你创建一个文件。 - ScrappyDev
使用URI的对应方法是,你必须捕获URISyntaxException - another

12

假设你的类从文件系统加载,那么你可以尝试以下操作。

String basePathOfClass = getClass()
   .getProtectionDomain().getCodeSource().getLocation().getFile();

要获取该路径下的文件,您可以使用以下方法

File file = new File(basePathOfClass, "filename.ext");

1
你的代码放在项目的根目录中,因此如果你想访问包中的特定文件,只需添加以下内容(到你的代码中):
  • "<包名>/" + 文件名;
- Zuenonentu
1
这对我有效,但对其他人可能无效。我会将以下代码添加到答案中:File file = new File(basePathOfClass + "Filename.txt"); - another

8

new File(".").getAbsolutePath() + "relative/path/to/your/files";

可以获取当前目录下的相对路径。

给答案打负一分,最好能够注明原因。 - user489041
7
这很可能是因为这基本上取决于当前的工作目录,而不是类路径。工作目录本身不是类路径的根目录,更重要的是,程序内部无法对其进行任何控制。它完全取决于启动程序的方式,因此这种方法容易出错。 - BalusC
可以理解,对我来说它足够好用。但是每个人都有自己的选择。 - user489041

8
在一般情况下,你是无法做到这一点的。从类加载器中加载的资源可以是任何东西:目录中的文件、嵌入在jar文件中的文件,甚至是通过网络下载的文件。

11
我不理解为什么这个问题被标记为正确的。 - Rafael Ruiz Tabares
1
@RafaelRuizTabares 这是一个回答。 - Ajinkya
我知道@karna。但问题是为什么?因为我认为这是一个空洞的回答。否则,Baluc的回答更完整。 - Rafael Ruiz Tabares
@RafaelRuizTabares 只有 OP 能够回答。 - Ajinkya
2
@RafaelRuizTabares,我完全同意你的观点,BalusC的答案更加完整,但我认为我的回答是,在一般情况下,你不能将文件保存到类路径中,因为它可能在任何可能的介质上,很可能不支持写操作。 - gabuzo
BalusC的答案更好的原因是因为它考虑了问题提出的具体技术问题,而不是更抽象的元技术问题,“类路径由哪个持久层支持?”后者可能有其自身的优点,但这不是当前问题所问的。 - Chris Browne

5
这是对Peter回答的补充:
如果你希望文件与当前类在同一路径下(例如:project/classes):
URI uri = this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI();
File file = new File(new File(uri), PROPERTIES_FILE);
FileOutputStream out = new FileOutputStream(createPropertiesFile(PROPERTIES_FILE));
prop.store(out, null);

如果您希望将文件保存在不同的类路径中(例如:project/test-classes),只需将this.getClass()替换为TestClass.class之类的内容。
从类路径中读取属性:
Properties prop = new Properties();

System.out.println("Resource: " + getClass().getClassLoader().getResource(PROPERTIES_FILE));
InputStream in = getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
if (in != null) {
    try {
        prop.load(in);
    } finally {
        in.close();
    }
}

将属性写入类路径:

Properties prop = new Properties();
prop.setProperty("Prop1", "a");
prop.setProperty("Prop2", "3");
prop.setProperty("Prop3", String.valueOf(false));

FileOutputStream out = null;
try {
    System.out.println("Resource: " + createPropertiesFile(PROPERTIES_FILE));
    out = new FileOutputStream(createPropertiesFile(PROPERTIES_FILE));
    prop.store(out, null);
} finally {
    if (out != null) out.close();
}

在类路径上创建文件对象:

private File createPropertiesFile(String relativeFilePath) throws URISyntaxException {
    return new File(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()), relativeFilePath);
}

1
根据系统属性文档,您可以将其作为"java.class.path"属性访问:
string classPath = System.getProperty("java.class.path");

2
不够,因为它无法告诉您从类路径的哪个部分加载了该类。 - gabuzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接