2012-05-10 6 views
10

Stavo solo testando JCIFS per accedere alle condivisioni di Windows. È molto lento al punto di essere completamente inutilizzabile.JCIFS: il recupero dei file è troppo lento per essere utilizzabile

import jcifs.smb.*; 

class First { 
    public static void main(String[] args) throws Exception { 
    try { 
     //jcifs.Config.setProperty("jcifs.netbios.wins", "192.168.1.220"); 
     NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain.com", "Administrator", "password"); 

     SmbFile f = new SmbFile("smb://10.17.15.12/Share/xml/file.xml", auth); 
     SmbFileInputStream in = new SmbFileInputStream(f); 
     byte[] b = new byte[8192]; 
     int n; 
     while((n = in.read(b)) > 0) { 
     System.out.write(b, 0, n); 
     } 
    } catch (SmbException smbe) { 
     System.err.println(smbe.getNtStatus()); 
     System.err.println(smbe.toString()); 
     System.err.println(smbe.getCause()); 
    } 
    } 
} 

Ci vuole molto tempo per l'uscita iniziale e le letture successive sono anche molto lente. Qualche idea su come usarlo? Tutte le alternative con cui posso scrivere codice Java per accedere alle condivisioni Windows in modo portatile sono anch'esse benvenute

risposta

18

Ho trovato da qualche parte che SmbFileInputStream non esegue il proprio buffering e quindi il motivo per cui è lento. Wrapping SmbFileInputStream in BufferedInputStream ha risolto il problema.

SmbFile sFile = new SmbFile(path, authentication); 

BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(sFile)); 
+2

So che questa è una vecchia risposta, ma il collegamento sorgente sembra essere obsoleto. – Vish

2

Se è possibile fare affidamento su "qualcos'altro" per montare la condivisione come directory locale per voi, quindi leggere i file nel la condivisione montata in Java dovrebbe essere portatile.

Anche se questa non è una soluzione reale, varrebbe la pena provare questo per vedere se si ottiene una velocità di lettura più elevata. Una velocità di lettura significativamente più veloce potrebbe farti cambiare idea dell'importanza relativa della portabilità. E se non ottieni una significativa accelerazione, allora saprai che JCIFS non è da incolpare ...

15

Nel mio caso, spingendo i file in una condivisione di Windows tramite JCIFS era troppo lento per essere utilizzabili.

La soluzione si è rivelata definire la proprietà

 
-Djcifs.resolveOrder=DNS 

La default inclusion di BCAST - radio una query di nomi NetBIOS a 255.255.255.255 - è stato inutilmente risultante in un lungo ritardo. (. Link qui sopra de-incorniciato dal top-level API docs)

+0

Questa è una grande scoperta! – Xolve

+1

Grazie! Certo calci il mio fondo per una settimana .... – Glenn

+3

jcifs.Config.setProperty ("resolveOrder", "DNS"); salvato anche la mia vita! Grazie!! – Exceptyon

2

Quello che ho notato è che JCIFS fa "qualcosa" (afair jcifs.smb.SmbTransport.checkStatus(..)) per ogni pezzo si legge -. Cioè per ogni blocco che viene letto nel buffer Questo significa che utilizzando un BufferedInputStream potrebbe davvero accelerare le cose, ma il vero problema esiste ancora. Solo non si verifica più spesso di prima e quindi ha un impatto minore sul tempo complessivo ..

Aiuta molto a impostare "jcifs.util .loglevel = 3 "e guarda cosa c'è di veramente sbagliato!

Nel mio caso ho dovuto impostare "jcifs.smb.client.dfs.disabled=false" alla fine, come "jcifs.resolveOrder=DNS" non ha aiutato ..

1

Anche con i suggerimenti esistenti ho ancora trovato JCIFS troppo lento per lo streaming di video sulla mia rete locale. Sembra che si tratti del sovraccarico per buffer letto dalla rete, anche leggendo in buffer di grandi dimensioni JCIFS stesso aveva una dimensione del buffer limitata che rappresentava il problema.

Se si guarda in https://jcifs.samba.org/src/patches/ c'è una patch, LargeReadWrite.patch. Dovrai applicare la patch e ricostruire il codice per usarlo, ma ha fatto una grande differenza per me.

+0

Eccellente scoperta :-) – Xolve

0

La soluzione aggiunta da @ Xolve0 ha funzionato anche per me. Il problema del buffer nel SmbFileInput è anche presente quando si tenta di scrivere file. Ho utilizzato lo stesso BufferedInputStream(new SmbFileInputStream(sFile)) per ridurre l'esecuzione del tempo da 90 secondi a meno di un secondo per un file di testo normale.

Un modo rapido per identificare questo problema specifico consiste nel tracciare il tempo tra l'apertura del percorso JCIFS e la scrittura del file stesso.