2つのリソースフォルダーがあります。
src-ここに私の.Javaファイルがあります
リソース-これは、フォルダー(パッケージ)に整理されたリソースファイル(画像、.properties)です。
そのリソースフォルダーに別の.propertiesファイルをプログラムで追加する方法はありますか?
私はこのようなものを試しました:
public static void savePropertiesToFile(Properties properties, File propertiesFile) throws IOException {
FileOutputStream out = new FileOutputStream(propertiesFile);
properties.store(out, null);
out.close();
}
それが作成される前:
new File("/folderInResources/newProperties.properties");
しかし、ファイルシステム上でそのパスを探します。どのようにすれば、リソースフォルダーを強制的に検索できますか?
[〜#〜] edit [〜#〜]:それが何であるかについてお話させてください。 GUIアプリケーションがあり、2つの言語(リソースフォルダー内の2つの.propertiesファイル)をサポートしています。ここで、ユーザーがアプリケーションを簡単に翻訳できるオプションを追加しました。ユーザーが終了したら、新しい.propertiesをディスクの隠しフォルダーに保存し、そこから読み取ります。しかし、現在の言語(resourcesフォルダー)の横に新しい.propertiesファイル(新しい言語)を保存できることを望んでいました。私は、ディスクからリソースを読み込む方法と、リソースフォルダーのデフォルトのリソースを読み込む方法を知っている静的なメッセージクラスを持っています。しかし、ユーザーがこの.jarファイルを他のマシンで取得した場合、それらは.jarファイル内ではなく、そのコンピューターのディスク上にあるため、その新しい言語はありません。
他の人が述べたように、リソースはClassLoaderを通じて取得されます。しかし、現在の2つの対応で強調できなかったのは、次の点です。
Java.lang.ClassLoader
_を拡張することによってユーザーまたは他の誰かが実装する可能性のあるすべてのものにすることができます。ショートバージョン:しないでください。 「リソースを取得できるリソースのようなもののリポジトリ」という概念のためのより抽象的なインターフェースと、「リソースを取得できるが、追加できるリソースのようなもののリポジトリ」のサブインターフェースを記述します。後者は、両方ともClassLoader.getContextClassLoader().getResource()
を使用して(クラスパスを検索するため)実装し、それが失敗した場合は、他のメカニズムを使用して、プログラムが特定の場所から追加したものを取得します。
コンパイルされたサブフォルダーのメインプロジェクトフォルダー( "/ target/classes"、 "target/test-classes")を切り取り、プロジェクトフォルダーを再構築するための基本的なパスを取得します。
import Java.io.File;
import Java.io.IOException;
import Java.net.URISyntaxException;
public class SubfolderCreator {
public static void main(String... args) throws URISyntaxException, IOException {
File newResourceFolder = createResourceSubFolder("newFolder");
}
private static File createResourceSubFolder(String folderName) throws URISyntaxException, IOException {
Java.net.URL url = SubfolderCreator.class.getResource("/EXISTING_SUBFOLDER/");
File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile();
String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0];
File testResultsFolder = new File(projectFolder + "src/test/resources/" + folderName);
if (!testResultsFolder.exists()) {
testResultsFolder.mkdir();
}
return testResultsFolder;
}
}
Java 8ソリューション
Path source = Paths.get(this.getClass().getResource("/").getPath());
Path newFolder = Paths.get(source.toAbsolutePath() + "/newFolder/");
Files.createDirectories(newFolder);
これにより、リソースフォルダに新しいフォルダが確実に作成されます。しかし、ターゲットランタイムに新しいフォルダが見つかります。
これは、ProjectName/target/test-classes/newFolderになります。このコードをテストケースで実行している場合。それ以外の場合は、ターゲット/クラスになります
Src/resourcesで新しいフォルダーを見つけようとしないでください。確かにtarget/test-classesまたはtarget/classesにあります。
問題は、クラスパスに複数のルートディレクトリが含まれている可能性があるため、既存のファイルまたはディレクトリがないと、格納するルートディレクトリを区別するのが難しいことです。
既存のファイルがロードされている場合。
File existingFile = ...;
File parentDirectory = existingFile.getParentFile();
new File(parentDirectory, "newProperties.properties");
それ以外の場合は、リソースディレクトリで一意であることがわかっているディレクトリのハンドルを取得してみてください。 (これが機能するかどうかはわかりません)
URL url = this.getClass().getResource("/parentDirectory");
File parentDirectory = new File(new URI(url.toString()));
new File(parentDirectory, "newProperties.properties");
次のコードは、クラスファイルとともにclasses
ディレクトリに書き込みます。
他の人が指摘したように、クラスファイルの上書きには注意してください。新しいファイルを別のディレクトリに配置するのが最善です。ただし、そのディレクトリはすでに存在している必要があります。それを作成するには、ソースのリソース内にサブディレクトリを作成します。空のファイルが含まれている可能性があります。例えば src\main\resources\dir\empty.txt
。
public class WriteResource {
public static void main(String[] args) throws FileNotFoundException {
String thing = "Text to write to the file";
String dir = WriteResource.class.getResource("/").getFile();
//String dir = WriteResource.class.getResource("/dir").getFile();
OutputStream os = new FileOutputStream(dir + "/file.txt");
final PrintStream printStream = new PrintStream(os);
printStream.println(thing);
printStream.close();
}
}
これでうまくいきますが、厳密に制御された環境の外でこれを展開することに不安を感じます。許可されていない人がclasses
ディレクトリに書き込むという考えはあまり好きではありません!
リソースはクラスローダーを介してロードされ、デフォルトのクラスローダーは大量にキャッシュします。
非静的ファイルシステムからリソースを読み取るには、必要な動作を備えた独自のクラスローダーが必要です。