2013-01-20 41 views
5

我在Android中編寫文字遊戲。這是我的第一個應用程序,所以我的知識幾乎不存在。在Android應用程序中訪問WordNet字典文件

我想要做的是使用JWI訪問WordNet詞典。這需要指定WordNet字典的文件路徑。

從我讀過的內容來看,Android的「資產」不能通過簡單的文件路徑獲得,但JWI需要初始化WordNet字典API的是URL字典文件的磁盤位置。

那麼,什麼是最佳行動方案?我應該在啓動時將資產複製到android設備上的已知文件夾中嗎?我想不出更好的辦法,但對我來說這似乎完全愚蠢。

任何幫助感激地收到。

+1

的JWI只接受文件路徑作爲輸入,而不是Java流?哇。如果情況確實如此,這是一個設計很差的圖書館。 –

+0

JWI查找一個目錄,然後打開其中的文件,我相信。 – sanbikinoraion

+0

我想在JWI郵件列表上發佈一個問題,詢問他們是否有Stream接口(或者只是查看API)。如果沒有,那麼我想你必須將它複製到存儲的某個地方。 –

回答

0

我有同樣的問題(對於Web應用程序碼頭然而,而不是Android)和想這些兩種方法,但是沒有成功:

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

這成功加載wordnet_properties.xml但它不能訪問是字典由屬性文件指向。

直接使用字典文件夾:

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); 

這裏我得到的詞典網址爲jar:file:/home/myusername/.m2/repository/package/1.0-SNAPSHOT/commons-1.0-SNAPSHOT.jar!/models/en/wordnet/dict/。然而WORDNET不接受罐子協議,並給我的錯誤:

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) 

我的下一個調查將是創建一個子類來RAMDictionary或類似的東西,請告訴我,如果你發現了其間的解決方案。

PS:我剛寫了一封郵件尋求幫助,之後我試圖重寫FileProvider來使用資源,但一兩個小時後我放棄了,因爲代碼調用了太多的其他代碼也只能用於文件。我會讓你保持最新!

P.P.S .:我收到了開發人員的回答,說它主要不適用於流,因爲它們不提供必要的隨機訪問。不過,他提出實施一個解決方案,將所有內容加載到RAM中,如果真的有必要,但這會花費大約500 MB,我認爲這對於Android應用來說太多了,所以我想最好是將它解壓到某個地方。

PS:這是我的拆包溶液(您可以記錄語句代替System.out.println語句,如果你使用記錄或刪除他們,如果你不喜歡他們):

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!"); 
    } 
} 
相關問題