java - 使用完整路径或类路径将文件作为流读取
问题描述
我有一个方法getMyFilePath()
可以将目录的路径作为String
.
它可以返回一个类路径:\com\mypackage\configdir\
也可以返回完整路径:C:\configdir\
我想修改下面的代码,以便它可以处理上述两种情况:
public void myMethod() {
String myConfigDirPath = getMyFilePath();
File configFile = new File(myConfigDirPath + "myConfig.txt");
try (InputStream is = new FileInputStream(configFile)) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
myMethod()
当路径已满时运行正常,即当路径为类路径时在线C:\configdir\
给出以下错误,InputStream
即\com\mypackage\configdir\
:
java.io.FileNotFoundException: \com\mypackage\configdir\myConfig.txt
(The system cannot find the path specified)
如何修改myMethod()
以使其适用于两种类型的路径?
解决方案
您错误地使用了术语“类路径”。类路径是目录和/或 jar 文件的列表,用于在运行时或编译时解析类和资源。
适当的术语\com\mypackage\configdir\myConfig.txt
是资源。 当它在源代码树中时它可能是一个文件,但是如果您尝试将程序打包为 jar 文件,它将在 jar 存档中并且根本不是文件,因此您无法使用 FileInputStream 读取它。
使用getResourceAsStream方法读取资源,该方法专门用于检索与应用程序捆绑的静态数据:
File configFile = new File(myConfigDirPath + "myConfig.txt");
try (InputStream is = new BufferedInputStream(
configFile.exists()
? new FileInputStream(configFile)
: MyApplication.class.getResourceAsStream(
configFile.toString().replace('\\', '/')))) {
// do something
}
通过将配置读取逻辑移动到单独的私有方法可以使其更清晰:
File configFile = new File(myConfigDirPath + "myConfig.txt");
if (configFile.exists()) {
try (InputStream is = new BufferedInputStream(
new FileInputStream(configFile))) {
readConfigurationFrom(is);
}
} else {
String configResourcePath =
configFile.toString().replace('\\', '/')))) {
InputStream configResource =
MyApplication.class.getResourceAsStream(configResourcePath);
if (configResource == null) {
throw new ConfigurationException(
"Cannot find the file \"" + configFile + "\""
+ " or the resource \"" + configResourcePath + "\"");
}
try (InputStream is = new BufferedInputStream(configResource)) {
readConfigurationFrom(is);
}
}
一些附加说明:
- 资源被指定为相对 URL,例如
/com/mypackage/configdir/myConfig.txt
. 在所有平台上, URL始终使用正斜杠 (/
)。 - 您应该始终使用 BufferedInputStream(或 BufferedReader)读取文件或资源。它比直接从文件中读取单个字节要快得多。
推荐阅读
- windows - 如何在谷歌云 Windows 实例上安装 xampp?
- ios - 核心数据-[Decodable.Address initWithCoder:]:发送到实例的无法识别的选择器
- jboss - Jboss ON 安装等待服务器
- r - 在下一个 mutate_at 中选择由 mutate_at 创建的正确列
- matlab - 如何在matlab中将高斯噪声添加到3D数据中
- c# - 从 Web api 反序列化 DateTime
- sml - 机器学习多态函数
- sql - 查找每个月的第一个和最后一个工作日sql
- c# - C# '1' 附近的语法不正确
- android - 如何在 Ratting Bar 中对全明星 android 进行评分?