在Android应用程序中访问WordNet字典文件

问题描述:

我在Android中编写文字游戏。这是我的第一个应用程序,所以我的知识几乎不存在。在Android应用程序中访问WordNet字典文件

我想要做的是使用JWI访问WordNet词典。这需要指定WordNet字典的文件路径。

从我读过的内容来看,Android的“资产”不能通过简单的文件路径获得,但JWI需要初始化WordNet字典API的是URL字典文件的磁盘位置。

那么,什么是最佳行动方案?我应该在启动时将资产复制到android设备上的已知文件夹中吗?我想不出更好的办法,但对我来说这似乎完全愚蠢。

任何帮助感激地收到。

+1

的JWI只接受文件路径作为输入,而不是Java流?哇。如果情况确实如此,这是一个设计很差的图书馆。 –

+0

JWI查找一个目录,然后打开其中的文件,我相信。 – sanbikinoraion

+0

我想在JWI邮件列表上发布一个问题,询问他们是否有Stream接口(或者只是查看API)。如果没有,那么我想你必须将它复制到存储的某个地方。 –

我有同样的问题(对于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://*.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!"); 
    } 
}