2011-02-10 3 views
4

この質問の文脈は、私が書いた豚のスクリプトでmaxmind java apiを使用しようとしていることです。しかし、どちらかについて知っていることが質問に答える必要があるとは思いません。ファイルへのパスを必要とするコンストラクタがある場合、それがjarファイルにパッケージ化されている場合、どうすれば "偽"できますか?

maxmind APIには、GeoIP.datというファイルへのパスが必要なコンストラクタがあります。これは、必要な情報を持つカンマ区切りのファイルです。

私は、APIを含むjarファイルとクラスをインスタンス化して使用するラッピングクラスを持っています。私の考えは、jarファイルにGeoIP.datファイルをパッケージ化し、jarファイルのリソースとしてアクセスすることです。問題は、コンストラクターが使用できるパスを作成する方法がわかりません。

APIを見てみると、これは彼らがファイルをロードする方法である:私はので、私は必要に応じて、この仕事をするためにAPI自体を編集することを嫌うないけど、知らないことを貼り付ける

public LookupService(String databaseFile) throws IOException { 
    this(new File(databaseFile)); 
} 


public LookupService(File databaseFile) throws IOException { 
    this.databaseFile = databaseFile; 
    this.file = new RandomAccessFile(databaseFile, "r"); 
    init(); 
} 

をどのように私はそのような機能を再現することができます。理想的には、私はそれをファイル形式にしたいと思っています。そうしないと、APIを編集するのはかなり手間がかかります。

これは可能ですか?

+0

が含まれていorg.foo.bar.utilあなたはパッケージを持っていると仮定すると

は、ファイルが実際に読み込まれているソースをよく見を持っています。その方法を無効にすることはできますか? –

+0

私の目標は、クラスパス内の何かからファイルfを得ることができるようにすることです。私がそれに就くことができれば、残りの仕事をするために物事を変えることができます。 –

答えて

1

classloader.getResource(...)メソッドを使用してクラスパスでファイルルックアップを実行します。これにより、JARファイルからファイルが取得されます。

これは、読み込みを無効にするために既存のコードを変更する必要があることを意味します。それを行う方法の詳細は、既存のコードと環境に大きく依存します。場合によっては、サブクラスをフレームワークにサブクラス化して登録することができます。それ以外の場合は、クラスパスに沿ったクラスロードの順序を決定し、クラスパスに "以前の"同じマークされたクラスを配置する必要があります。

2

試してみてください。

new File(MyWrappingClass.class.getResource(<resource>).toURI()) 
+0

これはjarファイルエントリで動作しますか? –

+0

jarが有効なクラスパスに含まれている場合は、ネットワーク経由、ファイルシステム上、またはクラスパス内のリソースを表すURIを持つことができます。私はこの提案について同様にしました。しかし、それはしばらくしており、私は特定の詳細または2つを見逃す可能性があります。しかし、これ(またはそれに近いもの)は、自分のクラスパス内のjarファイルに対して機能するはずです。 –

+0

私はsrc/test/resourcesのリソースにアクセスするために少なくともユニットテストでこれを使用しました – Puce

2

は、一時ファイルにデータをダンプし、それに一時ファイルを養います。

File tmpFile = File.createTempFile("XX", "dat"); 
tmpFile.deleteOnExit(); 

InputStream is = MyClass.class.getResourceAsStream("/path/in/jar/XX.dat"); 
OutputStream os = new FileOutputStream(tmpFile) 

read from is, write to os, close 
+0

これは最善の方法かもしれないと感じています... jarファイルのリソースを一時ファイルにダンプするにはどうしたらいいですか? –

1

ここでは、maxmind geoIPの使用方法を示します。

私たちは、GeoIPCity.datファイルをクラウドに入れ、プロセスを起動するときにクラウドロケーションを引数として使用します。 我々はGeoIPCity.dataファイルを取得し、新しいLookupServiceを作成するコードは次のとおりです。

ここ
if (DistributedCache.getLocalCacheFiles(context.getConfiguration()) != null) { 
    List<Path> localFiles = Utility.arrayToList(DistributedCache.getLocalCacheFiles(context.getConfiguration())); 
    for (Path localFile : localFiles) { 
     if ((localFile.getName() != null) && (localFile.getName().equalsIgnoreCase("GeoIPCity.dat"))) { 
      m_geoipLookupService = new LookupService(new File(localFile.toUri().getPath())); 
     } 
    } 
} 

は我々のプロセス本の

$HADOOP_HOME/bin/hadoop jar /usr/lib/COMPANY/analytics/libjars/MyJar.jar -files hdfs://PDHadoop1.corp.COMPANY.com:54310/data/geoip/GeoIPCity.dat -libjars /usr/lib/COMPANY/analytics/libjars/geoiplookup.jar

重要なコンポーネントを実行するために使用するコマンドの簡略版でありますMindMaxコンポーネントを実行するためのファイルは、-files-libjarsです。これらはGenericOptionsParserの一般的なオプションです。

-files <comma separated list of files> specify comma separated files to be copied to the map reduce cluster
-libjars <comma separated list of jars> specify comma separated jar files to include in the classpath.

私はどこでも私のプロジェクトでは、それへの参照を見つけることができませんので、私はHadoopのはGenericOptionsParserを使用していることを仮定しています。:)

あなたは可能性があり、そのは-files引数を使用して指定した上でGeoIPCity.datを置く場合、それはマッパーは、その後setup機能で取得することができ、ローカルキャッシュに入れられます。それはsetupにある必要はありませんが、マッパーごとに1回だけ行う必要がありますので、置くのに最適です。 次に、-libjars引数を使用してgeoiplookup.jar(またはあなたの名前をあなたが呼んだもの)を指定します。それを使用することができます。私たちはgeoiplookup.jarをクラウドに置いていません。私はhadoopが必要に応じて瓶を配布するという前提に縛られています。

私はすべてが意味を成就することを願っています。私はhadoop/mapreduceにかなり精通していますが、プロジェクトでmaxmind geoipコンポーネントを使う部分は書いていませんでしたので、私がここにある説明をするのに十分理解できるように少し掘り下げなければなりませんでした。

EDIT:-filesおよび-libjars -filesの追加の説明files引数は、Hadoop分散キャッシュを介してファイルを配布するために使用されます。上記の例では、Max Mindのgeo-ipデータファイルをHadoop分散キャッシュ経由で配布しています。ユーザーのIPアドレスを適切な国、地域、都市、タイムゾーンにマップするには、Max Mind geo-ipデータファイルにアクセスする必要があります。 APIでは、分散処理環境では実現できないデータファイルがローカルに存在する必要があります(クラスター内のどのノードがデータを処理するかは保証されません)。適切なデータを処理ノードに配布するために、Hadoop Distributed Cacheインフラストラクチャを使用します。 GenericOptionsParserとToolRunnerは、自動的に-file引き数を使用してこれを容易にします。配信するファイルは、クラウド(HDFS)で利用可能である必要があります。 -libjars -libjarsは、map-reduceジョブに必要な追加の依存関係を配布するために使用されます。データファイルと同様に、ジョブが実行されるクラスタ内のノードに依存ライブラリをコピーする必要があります。 GenericOptionsParserとToolRunnerは、自動的に-libjars引き数を使用してこれを容易にします。

2

1つの推奨方法は、Distributed Cacheをjarにバンドルするのではなく、使用することです。

GeoIP.datを圧縮してhdfs:// host:port/path/GeoIP.dat.zipにコピーすると、そして、豚のコマンドにこれらのオプションを追加します。

pig ... 
    -Dmapred.cache.archives=hdfs://host:port/path/GeoIP.dat.zip#GeoIP.dat 
    -Dmapred.create.symlink=yes 
... 

そしてLookupService lookupService = new LookupService("./GeoIP.dat");をファイルには、各ノード上のタスクにローカルに存在するとして、あなたのUDFで動作するはずです。

+2

Pig 0.9.0以来、 'EvalFunc'インターフェースはメソッド' getCacheFiles'を持っていて、HDFSパスのリストを与えることができます。対応するファイルは、例えば、 'FileReader fr = new FileReader(" ./ some.file ");で分散キャッシュからアクセスできます。 [PIG-1752](https://issues.apache.org/jira/browse/PIG-1752)を参照してください。 – maxjakob

2

これは私に適しています。それはGeoLiteCity.dat

URL fileURL = this.getClass().getResource("org/foo/bar/util/GeoLiteCity.dat"); 
File geoIPData = new File(fileURL.toURI()); 
LookupService cl = new LookupService(geoIPData, LookupService.GEOIP_MEMORY_CACHE); 
関連する問題