Differenza tra File.separator e barra nei percorsi


200

Qual è la differenza tra use File.separatore a normal/ in una stringa di percorso Java?

Contrariamente alla doppia \\piattaforma backslash , l'indipendenza non sembra essere la ragione, poiché entrambe le versioni funzionano con Windows e Unix.

public class SlashTest {
    @Test
    public void slash() throws Exception {
        File file = new File("src/trials/SlashTest.java");
        assertThat(file.exists(), is(true));
    }

    @Test
    public void separator() throws Exception {
        File file = new File("src" + File.separator + "trials" + File.separator + "SlashTest.java");
        assertThat(file.exists(), is(true));
    }
}

Per riformulare la domanda, se /funziona su Unix e Windows, perché si dovrebbe mai voler usare File.separator?


5
@Anello 'Ragioni storiche' come cosa?
Marchese di Lorne,

Risposte:


246

Con le librerie Java per la gestione dei file, puoi tranquillamente utilizzare /(barra, non barra rovesciata) su tutte le piattaforme. Il codice della libreria gestisce la traduzione interna di percorsi specifici della piattaforma.

Potresti voler usare File.separatornell'interfaccia utente, tuttavia, perché è meglio mostrare alle persone cosa avrà senso nel loro sistema operativo, piuttosto che ciò che ha senso per Java.

Aggiornare : non sono stato in grado, in cinque minuti di ricerca, di documentare il comportamento "puoi sempre usare una barra". Ora, sono sicuro di averlo visto documentato, ma nell'assenza di trovare un riferimento ufficiale (perché la mia memoria non è perfetta), continuerei a usarlo File.separatorperché sai che funzionerà.


2
Anche questo potrebbe essere un problema con le prestazioni, poiché ti aspetti che il separatore venga convertito in qualcos'altro in fase di esecuzione. Inoltre, non aspettarti che ciò accada in tutte le JVM non supportate là fuori.
jpabluz,

7
@TJ Crowder: "In cinque minuti di ricerche non sono stato in grado di trovare documentato il comportamento" puoi sempre usare una barra "." Non è una funzionalità di JVM, è una funzionalità dell'API di Windows NT.
Powerlord

12
@Powerlord: se lo fa anche Windows, fantastico - ma lo fa anche la libreria (non la JVM). In particolare, Fileutilizza FileSystem.normalizeovunque per "normalizzare" i percorsi ricevuti tramite l'API pubblica e quasi tutto ciò che riguarda le stringhe di percorso di file (ad esempio FileWriter(String)) viene utilizzato Filesotto le copertine.
TJ Crowder

9
Da Java7 non è più necessario utilizzare File.separator. È molto più semplice e pulito usare java.nio.file.Paths (Paths.get (prima, altro ...)) per dir a dir e dir al nome del file che si unisce.
magiccrafter,

6
@jpabluz 'Un problema con le prestazioni'! Sei serio? Considerando gli usi dei nomi dei file sul disco, l'impatto sul runtime di una traduzione è assolutamente insignificante. Dovrebbe essere supportato da qualsiasi JVM, in quanto fa parte delle specifiche di File.
Marchese di Lorne,

316

Lo usi File.separatorperché un giorno il tuo programma potrebbe essere eseguito su una piattaforma sviluppata in una terra lontana, una terra di cose strane e persone sconosciute, dove i cavalli piangono e le mucche gestiscono tutti gli ascensori. In questa terra, le persone hanno tradizionalmente usato il carattere ":" come separatore di file, e così rispettosamente la JVM obbedisce ai loro desideri.


4
Sì, Pointy ci ha davvero portati in Elbonia (spero che non abbia un taglio di capelli appuntito ;-) (gioco di
parole

4
"... e le mucche gestiscono tutti gli ascensori." Allo stesso modo non stavo bevendo un sorso del mio caffè quando l'ho letto. Brillante.
TJ Crowder

8
In un paese del genere faresti uso della nuova classe org.apache.chicken.elevators.OperatorUtility, che incorpora tutta questa follia per la tua comodità.
Cervello,

27

Sebbene l'utilizzo di File.separator come riferimento per un nome di file sia eccessivo (per coloro che immaginano terre lontane, immagino che la loro implementazione JVM sostituirà a /con un :proprio come Windows jvm lo sostituisce con a \).

Tuttavia, a volte si ottiene il riferimento al file, non lo si crea, ed è necessario analizzarlo e per poterlo fare, è necessario conoscere il separatore sulla piattaforma. File.separator ti aiuta a farlo.


11

OK ispezioniamo un po 'di codice.
File.javalinee da 428 a 435 in File.<init>:

String p = uri.getPath();
if (p.equals(""))
    throw new IllegalArgumentException("URI path component is empty");

// Okay, now initialize
p = fs.fromURIPath(p);
if (File.separatorChar != '/')
p = p.replace('/', File.separatorChar);

E leggiamo i fs/*(FileSystem)*/.fromURIPath()documenti:

java.io.FileSystem
estratto pubblico String fromURIPath (percorso stringa) Postelaborare la stringa del percorso
URI fornita, se necessario. Questo è usato su win32, ad es. Per trasformare "/ c: / foo" in "c: / foo". La stringa del percorso ha ancora dei separatori di barra; il codice nella classe File li tradurrà dopo la restituzione di questo metodo.

Questo significa FileSystem.fromURIPath()che la post elaborazione sul percorso URI è solo in Windows e perché nella riga successiva:

p = p.replace('/', File.separatorChar);

Sostituisce ogni '/' con il sistema dipendente seperatorChar, si può sempre essere sicuri che '/' sia sicuro in ogni sistema operativo.


8

Bene, ci sono più sistemi operativi di Unix e Windows (dispositivi portatili, ecc.) E Java è noto per la sua portabilità. La migliore pratica è usarlo, quindi la JVM potrebbe determinare qual è la migliore per quel sistema operativo.


La maggior parte di questi sistemi operativi esegue una variante di UNIX. I vecchi :separatori in stile Mac sono scomparsi da tempo. Sembra che tutti tranne Windows utilizzino più lo standard /. E anche Windows sembra gestire bene le barre adesso. Prova cd /windows/systemsu un sistema Windows 10 dall'unità di sistema principale. Mentre desideri comunque visualizzare i percorsi utilizzando il separatore di sistema (in modo da non confondere i tuoi utenti), puoi semplicemente usare la barra di scorrimento in /qualsiasi altro luogo e avere la certezza che il tuo codice funzionerà ovunque sia probabile che tu lo distribuisca.
Shadow Man,

7

Anche se non fa molta differenza durante il viaggio, lo fa al ritorno.

Sicuramente puoi usare '/' o '\' nel nuovo File (percorso String), ma File.getPath () ti darà solo uno di essi.


Leggera correzione ... In Windows è possibile utilizzare /la \\ barra in avanti o indietro . Ma altrove, è meglio che tu stia usando la barra /o avrai dei problemi.
Shadow Man,

6

In ritardo alla festa. Sono su Windows 10 con JDK 1.8 ed Eclipse MARS 1.
Lo trovo

getClass().getClassLoader().getResourceAsStream("path/to/resource");

funziona e

getClass().getClassLoader().getResourceAsStream("path"+File.separator+"to"+File.separator+"resource");

non funziona e

getClass().getClassLoader().getResourceAsStream("path\to\resource");

non funziona. Gli ultimi due sono equivalenti. Quindi ... ho buone ragioni per NON usare File.separator.


6
In questa riga getClass().getClassLoader().getResourceAsStream("path\to\resource");, ci sono una tabulazione ( \t) e un ritorno a capo ( \r).
Stephan,

9
Questo è uno scenario diverso dalla domanda. Il metodo getResourceAsStream di ClassLoader non accetta un percorso file, ma un nome di risorsa che può o meno essere presente nel file system ed è documentato come solo "/" come separatore del percorso delle risorse.
daiscog,

@Stephan non è divertente sfuggire lì, poiché File.separatorè una barra rovesciata. È solo nelle stringhe hardcoded in cui viene trattato come un carattere di escape in cui è necessario sfuggire alla barra rovesciata. Se hai memorizzato il personaggio in un file di testo, o in un charo Stringallora non devi fuggire una seconda volta poiché è già stato convertito nel carattere di barra rovesciata previsto. Prova questo per vedere di persona:String backslash = "\\"; System.out.println("welcome" + backslash + "to" + backslash + "reality");
Shadow Man

2
@Stephan oh, vedo ... Stavi parlando della terza riga. Hai ragione. In quella riga (una stringa codificata) dovresti sfuggire al carattere di escape. I miei occhi si fermarono alla seconda linea e all'inizio non mi accorsi nemmeno della terza linea.
Shadow Man,

3

portabilità semplice e chiara.


Sì, per la portabilità, non utilizzare la barra rovesciata. Usa la barra /o il separatore di sistema File.separator. Entrambi sembrano funzionare ovunque. Mentre File.separatorè garantito che funzioni ovunque, anche la semplice barra /sembra funzionare ovunque. Se non funziona da qualche parte, mi piacerebbe saperlo. Credo che funzionerà su tutti i sistemi. Per lo meno, devo ancora trovare un posto che /non funziona (Mac OSX, Windows, * nix, Android, iOS - Non ho controllato i Mac pre OSX che utilizzavano ":" come separatore, OS / 2, NeXT o uno qualsiasi degli altri SO davvero antichi).
Shadow Man,

1

"Java SE8 per programmatori" afferma che Java affronterà entrambi. (pagg. 480, ultimo paragrafo). L'esempio afferma che:

c:\Program Files\Java\jdk1.6.0_11\demo/jfc

analizzerà bene. Prendi nota dell'ultimo separatore (stile Unix).

È pacchiano e probabilmente soggetto a errori, ma è ciò che sostengono (Deitel e Deitel).

Penso che la confusione per le persone, piuttosto che Java, sia una ragione sufficiente per non usare questa funzionalità (mis?).


1

Come i signori hanno descritto la differenza con i dettagli della variante.

Vorrei raccomandare l'uso di Apache Commons io api, classe FilenameUtilsquando si tratta di file in un programma con la possibilità di distribuire su più sistemi operativi.


0

Il percorso per un file o una directory viene specificato utilizzando le convenzioni di denominazione del sistema host. Tuttavia, la classe File definisce costanti dipendenti dalla piattaforma che possono essere utilizzate per gestire i nomi di file e directory in modo indipendente dalla piattaforma.

Files.seperator definisce il carattere o la stringa che separa la directory e i componenti del file in un percorso. Questo separatore è '/', '\' o ':' rispettivamente per Unix, Windows e Macintosh.


Il ":" per Macintosh è antico. Dal momento che OSX, Mac utilizza anche "/" (barra) in quanto esegue una forma di UNIX con un filesystem UNIX standard sotto il cofano.
Shadow Man,


0

L'utilizzo di File.separator ha fatto sì che Ubuntu generasse file con "\" sul suo nome anziché su directory. Forse sono pigro con come sto creando file (e directory) e avrei potuto evitarlo, indipendentemente, usare "/" ogni volta per evitare file con "\" sul suo nome


0

Se si sta tentando di creare un file da un percorso pronto (salvato nel database, ad esempio) utilizzando il separatore Linux, cosa devo fare?

Forse basta usare il percorso per creare il file:

new File("/shared/folder/file.jpg");

Ma Windows usa un separatore diverso ( \). Quindi, l'alternativa è convertire il separatore di barra in piattaforma indipendente? Piace:

new File(convertPathToPlatformIndependent("/shared/folder"));

Questo metodo convertPathToPlatformIndependentprobabilmente avrà una sorta di divisione per "/" e si unirà a File.separator.

Bene, per me, non è carino per un linguaggio indipendente dalla piattaforma (giusto?) E Java già supporta l'uso di /su Windows o Linux. Ma se stai lavorando con percorsi e devi ricordare questa conversione ogni volta che questo sarà un incubo e non avrai alcun reale guadagno per l'applicazione sul futuro (forse nell'universo che @Pointy ha descritto).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.