JAva:jarパッケージのプロファイルを読み込む方法


文書ディレクトリ
  • 概要
  • 定義インタフェース
  • JarFileによる
  • の読み出し
  • URLにより
  • を読み取る.
  • ClassLoader
  • を通過
  • まとめ

  • 概要
    プログラミングの場合、jarパッケージのファイルを読み込む必要がある場合があります.この場合、クラスローダを使用してプロファイルを読み込むのとは異なり、この場合jarパッケージに配置すれば読み込むことができますが、プロファイルはjarパッケージになくてもいいので、Class-Pathに置けばいいので、この場合、Class-Pathのプロファイルを読み込むということをもっと望んでいます.今日説明したのはjarパッケージのファイルを読み込むことです.このような需要は多くないかもしれませんが、私は出会って、いくつかを発見して、今日はすべて羅列して分かち合います.現在3種類あります.
  • JarFile
  • URL
  • ClassLoader

  • インタフェースの定義
    いくつかの方法があるので、インタフェースを直接定義します.
    public interface JarReader {
         
       /**
         *   jar     
         * @param jarPath   jar   
         * @param file  jar       
         * @return      ,       ,             。
         * @throws IOException
         */
        String readFromJar(String jarPath,String file) throws IOException;
    }
    

    jarパッケージリーダー、jarパッケージのファイルが読み込まれます.
    JarFileによる読み込み
    JarFileはjavaが持参したjarパッケージを読み取るAPIで、多くの人が使ったはずなので、私は直接コードを貼りました.
    public class JarFileJarReader implements JarReader {
         
    
        @Override
        public String readFromJar(String jarPath,String file) throws IOException {
         
            JarFile jarFile=null;
            try {
         
                jarFile=new JarFile(jarPath);
                JarEntry jarEntry=jarFile.getJarEntry(file);
                InputStream input=jarFile.getInputStream(jarEntry);
                return IOUtils.toString(input,"UTF-8");
            } catch (IOException e) {
         
                throw e;
            } finally {
         
                IOUtils.closeQuietly(jarFile);
            }
        }
    }
    

    コードも簡単で、最後にjarFileというオブジェクトを閉じなければならないことに重点を置いています.中間の入力ストリームは閉じなくてもいいです.
    しかし、私はこのコードを書く前に、私の個人的な経験から言えば、JarFileはリストファイル(MANIFEST.MF)を読み取るためのものが多いようです.このような状況が多いのを見たのかもしれませんが、もちろんその用途はそれだけではありません.そこで、リストファイルを読むコードを書きました.
    public void getManiFest(String jarPath) throws IOException {
         
            JarFile jarFile=null;
            try {
         
                jarFile=new JarFile(jarPath);
                Manifest manifest=jarFile.getManifest();
                if (manifest!=null){
         
                    //  Class-Path
                    String classPaths = (String) manifest.getMainAttributes().get(new Attributes.Name("Class-Path"));
                    if (classPaths != null && !classPaths.isEmpty()) {
         
                        String[] classPathArray = classPaths.split(" ");
    
                    }
                    //  JDK  
                    String jdkVersion = (String) manifest.getMainAttributes().get(new Attributes.Name("Build-Jdk"));
    
                    //         ,  Main-Class  
                }
    
            } catch (IOException e) {
         
                throw e;
            } finally {
         
                IOUtils.closeQuietly(jarFile);
            }
        }
    

    URLで読み取る
    JAvaが持参したURLはjarの中のファイルを読み取ることをサポートしており、プロトコルはjarで、表示方式は「/!」jarパッケージとファイルを区別します.コードは次のとおりです.
    public class URLJarReader implements JarReader {
         
        @Override
        public String readFromJar(String jarPath, String file) throws IOException {
         
            JarURLConnection jarURLConnection=null;
            try {
         
                URL fileUrl=ParseUtil.fileToEncodedURL(new File(jarPath));
                URL jarUrl=new URL("jar", "", -1, fileUrl + "!/");
                URL moduleUrl = new URL(jarUrl, ParseUtil.encodePath(file, false));
                jarURLConnection = (JarURLConnection)moduleUrl.openConnection();
                return IOUtils.toString(jarURLConnection.getInputStream(),"UTF-8");
            } catch (IOException e) {
         
                throw e;
            } finally {
         
                if (jarURLConnection!=null){
         
                    try {
         
                        jarURLConnection.getJarFile().close();
                    } catch (IOException ignore) {
         
                    }
                }
            }
        }
    }
    

    ParseUtilのいくつかの方法はjavaソースコードを見たときに見たもので、不規則なファイルパスを処理するために使われています.私がURLを使い始めたばかりの頃、メモリが漏れたファイルが現れました.読み取りが終わった後、jarパッケージが占有され、削除できませんでした.さっきから入力ストリームを閉じましたが、役に立たなかったです.次にクラスローダにcloseメソッドがあることを考えて、見てみると、上記のコードのfinallyブロックのコードが見つかりました.これで占用問題を解決できるので、よく見ると、getJarFile.close()なので、本質的にはJarFileを閉じて、上と同じです.
    ClassLoader経由
    これも私たちが普段プロファイルを読み込む方法を参考にして、ClassLoaderを借りて読みます.
    public class ClassLoaderJarReader implements JarReader {
         
        @Override
        public String readFromJar(String jarPath, String file) throws IOException{
         
            URLClassLoader urlClassLoader=null;
            try {
         
                URL fileUrl=ParseUtil.fileToEncodedURL(new File(jarPath));
                urlClassLoader=new URLClassLoader(new URL[]{
         fileUrl},null);
                InputStream inputStream=urlClassLoader.getResourceAsStream(file);
                if (inputStream==null){
         
                    throw new FileNotFoundException("not find file:"+file+" in jar:"+jarPath);
                }else{
         
                    return IOUtils.toString(inputStream,"UTF-8");
                }
            } catch (IOException e) {
         
                throw e;
            } finally {
         
                IOUtils.closeQuietly(urlClassLoader);
            }
        }
    }
    

    コードも簡単なので、最後にClassLoaderをオフにすればいいです.クラスローダの読み取り方法については、以前から見ていましたが、本質的には上記の2つの方法を組み合わせてファイルを読み取ることを使用しています.
    まとめ
    このいくつかの方法は、実は何の違いもありません.開発の観点から言えば、3つ目がお勧めです.javaが持っている機能なので、完備していて、簡単で、間違いにくいです.そして、内部では前の2つを使っています.しかし、資源消費の面から言えば、前の2つが優位に立つべきだと推測していますが、私もこれにこだわらず、研究していません.
    jarのjarのファイルを読み込む別のニーズがあるかもしれませんが、これはいくつかのシーンで使用されます.少なくともspring-bootは確かに使われていて、ずっと前にその実現を見たことがあります.それはURLを書き直して、複数の「/!」をサポートしました.式は、このような状況をサポートすることができます.