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!");
}
}
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ę. –
JWI szuka katalogu, a następnie otwiera w nim pliki, jak sądzę. – sanbikinoraion
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. –