2012-11-05 10 views
5

Sto utilizzando IKVM per portare alcune librerie java nel mio progetto C#. La libreria api (StanfordNLP) richiede che venga caricato un file per addestrare i modelli statistici utilizzati dalle funzioni nlp. Il caricamento del file dal file system ha funzionato bene per settimane, ma ora vorrei aggiungere il file come risorsa incorporata in una DLL, anziché recuperarlo dal file system.Come accedere a una risorsa .net per una libreria java con porta IKVM

Il problema è che java api non trova la risorsa incorporata .net.

Ecco un frammento di codice che funziona durante il recupero di un file dal file system:

public class SNLPModel 
{ 
    public LexicalizedParser LP; 

    public SNLPModel() 
    { 
     // Using a relative file path in the target build directory 
     LP = LexicalizedParser.loadModel("models-stanford\\englishPCFG.ser.gz"); 
    } 
} 

Ma quando faccio la "englishPCFG.ser.gz" un file di risorsa incorporata in Visual Studio (usando VS2012) e modificare il codice corrispondente:

public class SNLPModel 
{ 
    public LexicalizedParser LP; 

    public SNLPModel() 
    { 
     // Using this line of code to verify that the file is being loaded as 
     // an embedded resource. Running in debug, I have verified that it is, and 
     // noted its complete name. 
     string[] s = System.Reflection.Assembly.GetExecutingAssembly() 
         .GetManifestResourceNames(); 

     java.io.InputStream modelFile = java.lang.ClassLoader 
       .getSystemResourceAsStream 
       ("FeatureExtraction.StanfordNLP_Models.englishPCFG.ser.gz"); 

     java.io.ObjectInputStream x = new java.io.ObjectInputStream(modelFile); 

     LP = LexicalizedParser.loadModel(x); 
    } 
} 

l'oggetto InputStream, modelFile, viene sempre restituito null. Ho provato varie forme della stringa di risorse, sostituendo i primi due punti (".") Con la barra ("/"), il backslash ("\") e il doppio backslash ("\\"). Sto iniziando a sospettare che java.io non possa accedere alla risorsa .net. Non sarebbe sorprendente che java api non riconosca le risorse .net, ma ho pensato che IKVM potesse fornire un bridge. Ho visto un riferimento a qualcosa chiamato IKVM.Internals.VirtualFileSystem, ma solo l'unico riferimento (http://old.nabble.com/Manual-by-name-embedded-resource-lookup--td31162421.html) e rifugio " Ho trovato le DLL di IKVM che contengono effettivamente la classe.

Qualsiasi aiuto sarebbe molto apprezzato. Sto usando:

C# .NET 4.5

di Visual Studio 2012

ultime librerie Java Stanford NLP

iKVM 7.0.4335.0

risposta

3

Non v'è alcun supporto automatico per questo nella IKVM, ma è davvero facile farlo da soli:

var asm = Assembly.GetExecutingAssembly(); 
var stream = asm.GetManifestResourceStream("FeatureExtraction.StanfordNLP_Models.englishPCFG.ser.gz"); 
var inp = new ikvm.io.InputStreamWrapper(stream); 
var x = new java.io.ObjectInputStream(inp); 
+0

Grazie per l'aiuto Jeroen! L'ho appena provato; i primi tre passaggi sembrano essere eseguiti correttamente, ma il quarto genera un'eccezione: "intestazione del flusso non valida: 1F8B0800" – user1800804

+0

Risolto l'eccezione. Il file caricato non era in un formato coerente con uno prodotto da ObjectOutputStream. Grazie ancora, Jeroen. – user1800804

0

Il ciao nt alla soluzione giusta è nell'estensione del file che hai incorporato.

Se è normale oggetto serializzato java (come english-left3words-distsim.tagger) è possibile caricare in questo modo

let model = "../english-left3words-distsim.tagger" 
use fs = new FileStream(model, FileMode.Open) 
use isw = new ikvm.io.InputStreamWrapper(fs) 
let tagger = edu.stanford.nlp.tagger.maxent.MaxentTagger(isw) 

ma se il modello ha un'estensione .gz Questo significa che il file è gzip, e si deve avvolgere flusso di input in java.util.zip.GZIPInputStream prima della deserializzazione

let model = "../englishRNN.ser.gz" 
use fs = new FileStream(model, FileMode.Open) 
use isw = new ikvm.io.InputStreamWrapper(fs) 

use ois = 
    if model.EndsWith(".gz") 
    then 
     let gzs = new java.util.zip.GZIPInputStream(isw) 
     new java.io.ObjectInputStream(gzs) 
    else new java.io.ObjectInputStream(isw) 
let lp = edu.stanford.nlp.parser.lexparser.LexicalizedParser.loadModel(ois)