私は、大きなリソースフォルダー(数千の小さな画像を含む構造)へのアクセスが必要なプロジェクトに取り組んでいます。クライアントは、ネイティブインストール(アプリの実行に必要なJVMを含む)を介してアプリを提供したいと考えています。彼は、そのリソースをアプリ内のフォルダーとしてパックしたくありません。これは、最終ユーザーのハードドライブに元のフォルダーと同じ大きさのフォルダー構造が作成されるためです(フォルダーは多くのスペースを必要としませんが、小さなファイルがたくさんあります)。さらに、フォルダをコピーするだけで簡単に盗むことができます。これを考えると、jarファイルがインストール可能でないことがわかっている限り、すべてのアプリをリソースフォルダーとともにjarファイルにパッケージ化することはできません。別の要件は、クライアントがプログラムに新しい機能を追加するために、インストールされたアプリフォルダー構造にいくつかのファイルを追加するための特定の柔軟性を必要とすることです。
それらをjarファイルにパックし、ビルドパスに含めてアクセスしようとしましたが、さまざまなサイトで行ったすべての調査を行っても失敗しました。getResources()を何百万もの方法で試しましたが、jarファイル内に単純なディレクトリを取得することは不可能でしたが、jar外のフォルダから取得するのは非常に簡単です。ディレクトリに含まれるファイルのリストを取得するには、ディレクトリにアクセスする必要があります。
この時点に到着しました。私はこの問題に最善の方法で直面しているかどうかを自問し始めたので、皆さんに質問したいと思います。この要件を備えたネイティブJavaアプリに必要なリソースをどのようにパッケージ化しますか?
ある種の暗号化プロセスを作成して、すべての情報を含む単一のファイルを作成し、実行時に必要に応じて一時的に復号化することも考えていますが、これに対処するためのより簡単でクリーンな方法があると思います。
前もって感謝します
編集:あなたが求めたように、私は私が試したもののコードを追加しています:
これがプロジェクトの構造です
project
├───src
│ ├───main
│ │ └───java
│ │ ├───model <--- where my class is
│ │ ├───controllers
│ │ ├───utilities
│ │ └───views
│ ├───resources <--- this is where is (formerly) accessed the content i need
| | ├─── jarfile.jar <--- i've placed file here and included to build path
│ │ └───-various folders and files -
│ └───test
└───target
jarファイル内にはパッケージsrc.resources.blalblabaがあり、この中に必要なフォルダーがあります。
方法1:
getResourcesがjarファイル「。」を置き換えます。「/」を使用してパスで試行:「src / resources / blablabla / folderINeed」、「src / resources / src / resources / blablabla」(重複の可能性があるため)、「folderINeed」、「blablabla / folderINeed」-> URIは常にメッセージ「null」を含むNullPointerException
public void loadContent(String contentPath) throws Exception
{
File resources= null;
File[] listFiles = null;
URI uri = getClass().getClassLoader().getResource(contentPath).toURI();
resources= new File(uri);
listFiles = resources.listFiles();
//do some file proccessing and load them
}
方法2:使用されたパス "folderINeed"、 "src / resources / blablabla / folderINeed"、 "blablabla / folderINeed"、 "../../../ resources / blablabla / folderINeed" <--- URLはnullを返しますが、少なくとも、NullPointerExceptionは発生しません。
public void loadContent(String contentPath) throws Exception
{
// conseguimos todas las carpetas de animaciones
File resources;
File[] listFiles = null;
URL url = MyClass.class.getResource(contentPath);
if (url == null) {
// error - missing folder
} else {
resources = new File(url.toURI());
listFiles = resources.listFiles();
}
}
方法3:クラスJarFileを使用した複雑なコードで、私には機能せず、フォルダーではなく単純なファイルを取得するように指示されていました。ここで入手
私の苦悩:
@Joop Egenが彼の回答で言ったように、私の問題の1つは、プロジェクト内のフォルダー構造でした。リソースフォルダーをsrc / main /フォルダーに配置するというMavenの規則に従っていませんでした。これは、私が試したすべてのソリューションに、リソースフォルダーを取得するために必要なスコープがなかったためです。
jarファイルがjavaでどのように機能するのかわかりませんでした。javaの場合、.jarファイルは、その中のすべてのファイルへのjarエントリのコレクション(javaのコレクションではありません)です。私の1つのケースでは、.jarファイルはEclipseエクスポートウィザードを使用して作成され、フォルダーへの参照はなく、ファイルへの参照のみが含まれていました。したがって、すべてのコンテンツを含むフォルダを取得することは単純に不可能です。
java JarFileクラスを使用してコンテンツを管理しましたが、このクラスはjavaFileクラスのようにファイルを管理するメソッドを提供していません。したがって、他の種類のファイルを使用する場合ほど簡単ではありません。
私が行ったこと: .jar内のすべてのファイルエントリを読み取り、関心のあるものを区別するためのコードを開発しました。そして、それらをアプリ内のディレクトリに抽出します。これを行うことで、私はそれらに標準でアクセスでき、必要に応じて、アプリケーションを閉じたときにディレクトリを削除するだけで済みます。私はそれらをjarから直接使用しようとしましたが、jarファイルはzipファイルであるため、OSがzipファイルで行うように、内部ファイルをjarからどこかに追加する必要があります。一時ディレクトリである場合もそうでない場合もあります。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.FileUtils;
public class App
{
public static void main(String[] args)
{
try
{
//needed attributes
String pathToJar = "./src/main/blablalba/fileName.jar";
String folderYouWantToRetrieveFromTheJar = "/folderIWant";
String pathOfFilesWithinTheJar="src/resources/blablabla/"+folderYouWantToRetrieveFromTheJar+"/";
String tempDirectoryWhereExtract="./src/main/resources/temp";
//creating the temp directory
File tempDirectoryReference = new File(tempDirectoryWhereExtract);
if (!tempDirectoryReference.exists())
{
Files.createDirectory(tempDirectoryReference.toPath());
}
//searching what entries i need
JarFile jar = new JarFile(pathToJar);
final Enumeration<JarEntry> entries = jar.entries();
List<JarEntry> targetEntries = new ArrayList<>();
while (entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
//if the entry is what i need
if (entry.getName().startsWith(pathOfFilesWithinTheJar))
{
targetEntries.add(entry);
}
}
//extract every target entry from the .jar
for (JarEntry entry : targetEntries)
{
//in order to copy the structure i will get only the point where folderIWant is present
int index = entry.getName().indexOf(folderYouWantToRetrieveFromTheJar);
String newTemporaryPath = tempDirectoryReference.getPath().toString()+"/"+entry.getName().substring(index);
extractFileFromJar(jar, entry, new File(newTemporaryPath));
}
jar.close();
//(optional) clean after use
FileUtils.deleteDirectory(tempDirectoryReference);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void extractFileFromJar (JarFile jarFile, JarEntry targetEntry, File destinyPath)
{
try
{
if (!destinyPath.getParentFile().exists())
{
createFolderStructure(destinyPath);
}
else
{
Files.createFile(destinyPath.toPath());
}
InputStream inputStream = jarFile.getInputStream(targetEntry);
FileOutputStream outputStream = new java.io.FileOutputStream(destinyPath);
while (inputStream.available() > 0) {
outputStream.write(inputStream.read());
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static void createFolderStructure(File destinyPath)
{
File parentPath = destinyPath.getParentFile();
try
{
if (parentPath.exists())
{
Files.createFile(destinyPath.toPath());
}
else
{
Files.createDirectories(destinyPath.getParentFile().toPath());
Files.createFile(destinyPath.toPath());
}
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加