2010-05-08 12 views
19

Quando eseguo un'applicazione Java che dovrebbe leggere da un file in Eclipse, ottengo un java.io.FileNotFoundException, anche se il file si trova nella directory corretta. Posso compilare ed eseguire l'applicazione dalla riga di comando bene; il problema si verifica solo in Eclipse, con più di un progetto e un'applicazione. C'è un'impostazione che ho bisogno di cambiare nelle configurazioni di esecuzione o costruire percorsi per farlo trovare correttamente il file?Java non trova il file quando esegue Eclipse

+1

senza vedere il vostro codice, non possiamo dirvi cosa potrebbe succedere –

risposta

28

Il problema è più probabile che l'applicazione utilizza un percorso relativo. Come dice @BalusC, i percorsi relativi possono essere problematici. Ma IMO, va troppo lontano quando dice "[y] ou dovrebbe mai utilizzare i percorsi relativi a roba java.io".

Quando un'applicazione apre un file utilizzando (ad esempio) il costruttore FileInputStream(File), i relativi percorsi sono risolti relativi alla "directory corrente" in un processo descritto come segue in javadoc per File.getAbsolutePath().

[...] Altrimenti questo percorso è risolto in modo dipendente dal sistema. Sui sistemi UNIX, un percorso relativo viene reso assoluto risolvendolo contro la directory utente corrente. Sui sistemi Microsoft Windows, un percorso relativo viene reso assoluto risolvendolo contro la directory corrente dell'unità denominata dal nome del percorso, se presente; in caso contrario, viene risolto contro la directory utente corrente.

Così immediatamente, vediamo che la nozione di "directory corrente" ha sfumature diverse su piattaforme Windows e UNIX. Il secondo problema è che in Java puro non è possibile scoprire definitivamente quale sia la directory corrente, e certamente non è possibile cambiarla per la JVM corrente usando puro Java. (Quando la JVM si avvia, la proprietà di sistema "user.dir" è impostato nella directory corrente, ma non c'è niente di fermare un'applicazione di modificare la proprietà quindi non si può del tutto affidamento su di esso. Inoltre, cambia "user.dir" cambia solo il modo in cui il percorso vuoto viene risolto, non percorsi relativi in ​​generale.)

che cosa si deve fare?

  • Una possibilità è quella di utilizzare percorsi assoluti per fare riferimento a file. Questo è affidabile in (quasi) tutti i casi, ma l'utilizzo di percorsi assoluti può essere problematico se l'utente deve inserire il nome del percorso, oppure se è necessario evitare percorsi assoluti cablati (o configurati).

  • Una seconda opzione è quella di utilizzare percorsi relativi classpath e individuare i file relativi alla directory di installazione dell'applicazione. Funziona se è quello che devi fare, ma presenta un problema se devi passare un File ad un metodo di libreria. Inoltre, non aiuta se stai cercando di trovare le preferenze dell'applicazione dell'utente. (In generale, inserire le preferenze utente nella directory di installazione è un errore ...)

  • Una terza opzione è denominare un file relativo ad una directory assoluta che si ottiene da qualche altra parte; per esempio. new File(System.getProperty("home.dir"), "foo/bar");.

  • L'opzione finale consiste nell'utilizzare i percorsi relativi e presupporre che l'utente conosca la directory corrente. Per molte applicazioni che l'utente esegue dalla riga di comando, questa è la soluzione giusta.

Nel caso particolare di Eclipse, esiste una soluzione semplice. Vai alla "configurazione di esecuzione" che stai utilizzando per avviare l'applicazione, aprire la scheda "Argomenti" e fare clic sul pulsante di opzione "Altro". Quindi inserire un percorso assoluto come directory di lavoro per l'applicazione avviata. Quando viene avviata la JVM secondaria, avrà la directory di lavoro specificata come directory corrente.

+0

Grazie per il tuo aiuto! – derekerdmann

+0

Si è verificato un problema con la mia app avviata da Eclipse che non è in grado di leggere alcuni file delle proprietà presenti nella radice del mio progetto.Dopo aver provato a impostare la directory di lavoro in esecuzione configurazione su $ {workspace_loc}/myproject/bin ha funzionato !. – Krishnaraj

+0

@Krishnaraj - Questo è quello che ho detto nell'ultimo paragrafo della mia risposta :-) –

6

Quando si crea un'applicazione predefinita Java in Eclipse, si ottiene questa struttura di directory:

./ProjectName/ - directory principale
./ProjectName/bin/ - directory di output, contenente .class file
./ProjectName/src/ - directory di origine, che contiene i file .java

Se le richieste di applicazione "./data.txt" cercherà per esso relativo alla directory radice. Questa è la "directory di lavoro" e può essere configurata nella scheda degli argomenti come da risposta di Martin sopra.

Hai detto che funziona dalla riga di comando? Questo è probabile perché sei all'interno delle cartelle bin o src quando esegui il file binario java. La directory di lavoro in questo caso è quella in cui al momento il prompt dei comandi è all'interno. Se, ad esempio, si entra nella directory/src /, ad esempio javac *.java, quindi si eseguono i file da lì, si cercherà "./data.txt" all'interno della directory/src /. Se vai nella directory/bin/ed esegui la tua applicazione da lì, cercherà il file relativo alla directory/bin /.

+0

Grazie per il vostro aiuto. I file di testo che mi servono esistono nella directory/bin /, quindi non sembra essere il problema. Giocherò con i percorsi relativi e vedrò cosa posso ottenere. – derekerdmann

2

È necessario mai utilizzare i percorsi relativi nel materiale java.io. Il percorso diventerebbe dipendente dalla directory di lavoro corrente, che dipende dal modo in cui è stata avviata l'applicazione e quindi non è di per sé la stessa su tutti gli ambienti. Questo non è controllabile dall'interno dell'applicazione Java. Problemi di portabilità! Usa sempre percorsi assoluti. Quindi ad es. c:/path/to/file.ext o /path/to/file.ext (con la barra iniziale) per UNIX e consorts (o anche Windows quando la lettera del disco è irrilevante).

Ogni volta che si desidera spedire alcuni file insieme alla propria applicazione, è prassi comune collocarli nel classpath . In questo modo puoi semplicemente usare ClassLoader#getResource() per ottenere la sua posizione. Restituisce un URL. È possibile utilizzare URL#toURI() o URL#getPath() e passarlo al costruttore di java.io.File e quindi utilizzarlo ulteriormente nel modo usuale.

Nel progetto Eclipse, la cartella src (dove si trova l'origine Java) è fondamentalmente la radice del classpath. Inoltre, ovviamente, copre anche tutti gli altri progetti e le cartelle (esterne) che vengono prese nel progetto Build Path.

Supponendo che hai inserito il file particolare nel radice del classpath:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
URL url = classLoader.getResource("file.ext"); 
File file = new File(url.getPath()); 
FileInputStream input = new FileInputStream(file); 
// ... 

Si può anche utilizzare ClassLoader#getResourceAsStream() per ottenere direttamente un InputStream:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
InputStream input = classLoader.getResourceAsStream("file.ext"); 
// ... 

Se è collocato all'interno di un pacchetto, allora si può semplicemente utilizzare i consueti percorsi:

URL url = classLoader.getResource("com/example/file.ext"); 
// ... 

o

InputStream input = classLoader.getResourceAsStream("com/example/file.ext"); 
// ... 
+0

un'applicazione di riga di comando non GUI può essere ragionevolmente progettata per utilizzare percorsi relativi. L'avvertenza è che l'utente deve capire il concetto di "directory corrente", e il programmatore deve capire come questo mappa il comportamento delle librerie di I/O Java. –

+0

@Stephen: è sicuramente possibile, dovrai solo complicarti con percorsi relativi, ma non è raccomandato. L'utilizzo del classpath lo rende più robusto. – BalusC

+0

dipende da cosa sta facendo l'applicazione. Ad esempio, se sta manipolando file forniti dall'utente, l'approccio del percorso di classe ha poco senso. –

1

Supponendo che l'utente non inserisca il percorso completo del file nel file e inserisca qualcosa come "myfilenameonly". File file = new File(".", args[0]) è necessario in questo caso a individuare il file (prestando attenzione al primo argomento passato).

Tutte le piattaforme: File.getParent() non restituisce il directory padre, deve restituire ".." o il nome della directory genitore in un modo specifico del file system.

Se si crea il file "myfilenameonly" senza specificare il percorso completo alla directory in cui si trova, il File.getParent(), per esempio, ritorna null.

Vedi ancora: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=1228537

2

ho avuto un problema simile, ho messo i miei file in una cartella denominata cobolcopybooks all'interno della cartella src e provato ad accedere al loro interno il mio progetto utilizzando classloader.getResource ("cobolcopybooks/demostud. cob ") ma stavo ottenendo un'eccezione di puntatore nullo, l'ho provato diverse volte pulendo e costruendo gli spazi di lavoro dopo diversi tentativi falliti mi sono reso conto che non stavo aggiornando il progetto per consentire ai file di essere costruiti insieme al progetto. questi file dovrebbero essere visibili insieme ad altri file di classe come in fase di esecuzione, la directory radice sarà bin directory e sta cercando quei file lì.

8

Un'altra opzione è semplicemente capire a quale directory si indirizza il "percorso corrente" nel proprio ambiente, qualunque esso sia. Una volta capito, puoi scegliere la soluzione da lì. Forse è quello di utilizzare un percorso relativo appropriato alla posizione del file o riposizionare il file.

File testFile = new File(""); 
    String currentPath = testFile.getAbsolutePath(); 
    System.out.println("current path is: " + currentPath); 
+1

Questo non è l'ideale nel codice di spedizione, ma è sicuramente utile come codice di debug per vedere cosa sta pensando la tua applicazione sta succedendo. – Steve

Problemi correlati