Доступ к файлам в формате WordNet в приложении Android

Я пишу текстовую игру на Android. Это мое первое приложение, поэтому мои знания почти не существуют.

Я хотел бы использовать JWI для доступа к словарю WordNet. Для этого требуется указать путь к файлу словаря WordNet.

Из того, что я прочитал, «активы» Android недоступны с помощью простого пути к файлам, но то, что JWI требует для инициализации словарного словаря WordNet, – это URL-адрес расположения файлов словаря на диске.

Итак, каков наилучший способ действий? Должен ли я копировать активы во время запуска в известную папку на устройстве Android? Я не могу придумать лучшего способа, но это кажется мне абсолютно глупым.

Любая помощь с благодарностью получила.

У меня такая же проблема (для причала webapp, но не для 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); 

Здесь я получаю URL-адрес словаря jar:file:/home/myusername/.m2/repository/package/1.0-SNAPSHOT/commons-1.0-SNAPSHOT.jar!/models/en/wordnet/dict/ . WordNet, однако, не принимает протокол jar и дает мне ошибку:

 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 для использования ресурсов, но после одного или двух часов я сдался, потому что код вызывает столько другого кода, который также работает только с файлами. Я буду держать вас в курсе!

PPS: Я получил ответ от разработчика, говоря, что это принципиально невозможно с потоками, потому что они не предлагают произвольный доступ, который необходим. Тем не менее, он предложил реализовать решение для загрузки всего в ОЗУ, если это действительно необходимо, но это будет использовать около 500 МБ, и я предполагаю, что это слишком много для приложений для 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!"); } }