2013-01-20 11 views
5

Piszę grę słów w systemie Android. To moja pierwsza aplikacja, więc moja wiedza prawie nie istnieje.Dostęp do plików dyktowanych WordNet w aplikacji Android

Co chcę zrobić, to użyć JWI, aby uzyskać dostęp do słownika WordNet. Wymaga to określenia ścieżki pliku słownika WordNet.

Z tego, co przeczytałem, "zasoby" Androida nie są dostępne za pośrednictwem prostej ścieżki do pliku, ale to, czego JWI wymaga do zainicjowania słownika API WordNet, to adres URL lokalizacji dysku plików słownika.

Jaki jest najlepszy sposób postępowania? Czy powinienem skopiować zasoby w czasie uruchamiania do znanego folderu na urządzeniu z Androidem? Nie mogę wymyślić lepszego sposobu, ale wydaje mi się to całkowicie głupie.

Każda pomoc otrzymana z wdzięcznością.

+1

JWI tylko akceptuje ścieżki plików jako dane wejściowe, a nie strumienie Java? Łał. To naprawdę źle zaprojektowana biblioteka, jeśli tak jest naprawdę. –

+0

JWI szuka katalogu, a następnie otwiera w nim pliki, jak sądzę. – sanbikinoraion

+0

Zamiast tego opublikuję pytanie na liście adresowej JWI z pytaniem, czy ma on interfejs Stream (lub po prostu przejrzyj interfejs API). Jeśli nie, myślę, że będziesz musiał skopiować go gdzieś w magazynie. –

Odpowiedz

0

mam ten sam problem (dla webapp pomost jednak i nie android) i próbował te dwa podejścia, jednak bezskutecznie:

JWNL.initialize(this.getClass().getClassLoader().getResourceAsStream("wordnet_properties.xml"); 
dict = Dictionary.getInstance(); 

Tutaj powodzeniem ładuje wordnet_properties.xml ale nie może uzyskać dostępu do słownika, który jest wskazywany przez plik właściwości.

Korzystanie folder słownika bezpośrednio:

String dictPath = "models/en/wordnet/dict/"; 
URL url = this.getClass().getClassLoader().getResource(dictPath); 
System.out.println("loading wordnet from "+url); 
dict = new RAMDictionary(url, ILoadPolicy.NO_LOAD); 

Tutaj pojawia się słownik URL być jar:file:/home/myusername/.m2/repository/package/1.0-SNAPSHOT/commons-1.0-SNAPSHOT.jar!/models/en/wordnet/dict/. Wordnet jednak nie akceptuje protokół słoika i daje mi błąd:

java.lang.IllegalArgumentException: URL source must use 'file' protocol 
    at edu.mit.jwi.data.FileProvider.toFile(FileProvider.java:693) 
    at edu.mit.jwi.data.FileProvider.open(FileProvider.java:304) 
    at edu.mit.jwi.DataSourceDictionary.open(DataSourceDictionary.java:92) 
    at edu.mit.jwi.RAMDictionary.open(RAMDictionary.java:216) 

Mój następny dochodzenie będzie utworzyć podklasę do RAMDictionary lub coś podobnego, proszę mi powiedzieć, czy znalazłeś rozwiązanie w międzyczasie.

PS: Właśnie napisałem do programisty wiadomość e-mail z prośbą o pomoc po tym, jak spróbowałem przepisać FileProvider, aby zamiast tego użyć zasobów, ale po jednej lub dwóch godzinach zrezygnowałem, ponieważ kod wywołuje tak wiele innych kodów, które działają tylko z plikami . Będę Cię na bieżąco!

P.P.S .: Otrzymałem od dewelopera odpowiedź, że zasadniczo nie jest możliwe w przypadku strumieni, ponieważ nie oferują one dostępu losowego, który jest konieczny. Zaproponował jednak, aby zaimplementować rozwiązanie do załadowania go w całości w pamięci RAM, jeśli jest to naprawdę konieczne, ale zużywałoby to około 500 MB i wydaje mi się, że to za dużo dla aplikacji na Androida, więc sądzę, że najlepiej jest rozpakować go gdzieś.

PS: Oto moja rozpakowanie rozwiązanie (można zastąpić sprawozdania System.out.println sprawozdania z rejestratora jeśli używasz rejestrowanie lub ich usunięcia, jeśli ich nie lubię):

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.URISyntaxException; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 

/** Allows WordNet to be run from within a jar file by unpacking it to a temporary directory.**/ 
public class WordNetUnpacker 
{ 
    static final String ID = "178558556719"; // minimize the chance of interfering with an existing directory 
    static final String jarDir = "models/en/wordnet/dict"; 

    /**If running from within a jar, unpack wordnet from the jar to a temp directory (if not already done) and return that. 
    * If not running from a jar, just return the existing wordnet directory. 
    * @see getUnpackedWordNetDir(Class)*/ 
    static File getUnpackedWordNetDir() throws IOException 
    {return getUnpackedWordNetDir(WordNetUnpacker.class);} 

    /**If running from within a jar, unpack wordnet from the jar to a temp directory (if not already done) and return that. 
    * If not running from a jar, just return the existing wordnet directory. 
    * @param clazz the class in whose classloader the wordnet resources are found. 
    * @see getUnpackedWordNetDir()**/ 

    static File getUnpackedWordNetDir(Class clazz) throws IOException 
    { 
     String codeSource = clazz.getProtectionDomain().getCodeSource().getLocation().getPath(); 
     System.out.println("getUnpackedWordNetDir: using code source "+codeSource); 
     if(!codeSource.endsWith(".jar")) 
     { 
      System.out.println("not running from jar, no unpacking necessary"); 
      try{return new File(WordNetUnpacker.class.getClassLoader().getResource(jarDir).toURI());} 
      catch (URISyntaxException e) {throw new IOException(e);} 
     } 
     try(JarFile jarFile = new JarFile(codeSource)) 
     { 
      String tempDirString = System.getProperty("java.io.tmpdir"); 
      if(tempDirString==null) {throw new IOException("java.io.tmpdir not set");} 
      File tempDir = new File(tempDirString); 
      if(!tempDir.exists()) {throw new IOException("temporary directory does not exist");} 
      if(!tempDir.isDirectory()) {throw new IOException("temporary directory is a file, not a directory ");} 
      File wordNetDir = new File(tempDirString+'/'+"wordnet"+ID); 
      wordNetDir.mkdir(); 
      System.out.println("unpacking jarfile "+jarFile.getName()); 
      copyResourcesToDirectory(jarFile, jarDir, wordNetDir.getAbsolutePath()); 
      return wordNetDir; 
     }  
    } 
    /** Copies a directory from a jar file to an external directory. Copied from <a href="http://stackoverflow.com/a/19859453/398963">Stack Overflow</a>. */ 
    public static void copyResourcesToDirectory(JarFile fromJar, String jarDir, String destDir) throws IOException 
    { 
     int copyCount = 0; 
     for (Enumeration<JarEntry> entries = fromJar.entries(); entries.hasMoreElements();) 
     { 
      JarEntry entry = entries.nextElement(); 
      if(!entry.getName().contains("models")) continue; 
      if (entry.getName().startsWith(jarDir) && !entry.isDirectory()) { 
       copyCount++; 
       File dest = new File(destDir + "/" + entry.getName().substring(jarDir.length() + 1)); 
       File parent = dest.getParentFile(); 
       if (parent != null) { 
        parent.mkdirs(); 
       } 

       FileOutputStream out = new FileOutputStream(dest); 
       InputStream in = fromJar.getInputStream(entry); 

       try { 
        byte[] buffer = new byte[8 * 1024]; 

        int s = 0; 
        while ((s = in.read(buffer)) > 0) { 
         out.write(buffer, 0, s); 
        } 
       } catch (IOException e) { 
        throw new IOException("Could not copy asset from jar file", e); 
       } finally { 
        try { 
         in.close(); 
        } catch (IOException ignored) {} 
        try { 
         out.close(); 
        } catch (IOException ignored) {} 
       } 
      } 
     } 
     if(copyCount==0) System.out.println("Warning: No files copied!"); 
    } 
} 
Powiązane problemy