Problema puntando ad un NAS con un java.io.File

di il
41 risposte

41 Risposte - Pagina 2

  • Re: Problema puntando ad un NAS con un java.io.File

    Dimenticavo: se vuoi elencare tutto il contenuto, non usare " *.* ", ma usa solo " * ", altrimenti non ti verranno elencate le directory (il pattern "*.*" matcha solo i file che hanno un'estensione).

    Quindi:

    for (FileIdBothDirectoryInformation f : share.list("Directory", "*")) {
        System.out.println("File : " + f.getFileName());
    }

    Questo codice presuppone che dentro alla share esista una directory chiamata "Directory" e ne elenca tutto il contenuto (sottodirectory + files).

  • Re: Problema puntando ad un NAS con un java.io.File

    22/09/2025 - SpiritoLibero ha scritto:

    Questi warning compaiono perchè, tra le librerie, non hai messo la libreria SLF4J, che è una libreria di logging che SMB4J può usare se la trova in classpath: va tutto bene, ti sta dicendo che non c'è una libreria di logging ed eventuali log informativi non verranno scritti da nessuna parte. Non è nulla di bloccante.

    Eh, ma io ho scaricato i file che mi hai indicato.
    Mi puoi dire il nome completo della libreria che servirebbe per il logging e da dove scaricarla? Perché non riesco a trovarla.

    22/09/2025 - SpiritoLibero ha scritto:

    Ovvero le due directory standard.

    Ok, per le directory standard, ma le altre perché non me le mostra?

    A questo punto però mi nasce un ulteriore domanda.
    Come faccio a fare la copia di alcuni files dal disco del pc al NAS se per accedere al disco del pc devo usare una libreria differente da quella per accedere al NAS?

    In pratica che istruzione o struttura di istruzioni dovrei utilizzare?

    Hai per caso un esempio da mostrarmi?

  • Re: Problema puntando ad un NAS con un java.io.File

    22/09/2025 - SpiritoLibero ha scritto:

    Dimenticavo: se vuoi elencare tutto il contenuto, non usare " *.* ", ma usa solo " * ", altrimenti non ti verranno elencate le directory (il pattern "*.*" matcha solo i file che hanno un'estensione).

    Quindi:

    for (FileIdBothDirectoryInformation f : share.list("Directory", "*")) {
        System.out.println("File : " + f.getFileName());
    }

    Questo codice presuppone che dentro alla share esista una directory chiamata "Directory" e ne elenca tutto il contenuto (sottodirectory + files).

    Ok, grazie, ho appena provato ma mi elenca solo le sottodirectory e i file contenuti nella "Directory" ma non nelle sottodirectory, ovvero si ferma solo al primo livello.
    Tra l'altro alla prima prova un file di testo me l'ha messo in una posizione casuale in mezzo alle directory, ora invece li elenca in ordine di data di ultima modifica.
    C'è qualcos'altro che mi sfugge? C'è forse da indicare qualche altro parametro?

  • Re: Problema puntando ad un NAS con un java.io.File

    22/09/2025 - ZioCrick ha scritto:

    Eh, ma io ho scaricato i file che mi hai indicato.
    Mi puoi dire il nome completo della libreria che servirebbe per il logging e da dove scaricarla? Perché non riesco a trovarla.

    Ma non te ne devi preoccupare: è una libreria (credo anche piuttosto corposa) che generalmente viene usata dai framework più grossi (io non la uso): se è presente può usufruirne, altrimenti non se ne fa nulla. Ripeto: puoi tranquillamente ignorare quei warning.

    22/09/2025 - ZioCrick ha scritto:

    Ok, grazie, ho appena provato ma mi elenca solo le sottodirectory e i file contenuti nella "Directory" ma non nelle sottodirectory, ovvero si ferma solo al primo livello.

    Ed è corretto. Esattamente come il metodo list o listFiles della classe java.io.File.

    Se vuoi andare in profondità dovrai chiedere di andare a leggere il contenuto della sotto-directory che ti interessa.

    Tra l'altro alla prima prova un file di testo me l'ha messo in una posizione casuale in mezzo alle directory, ora invece li elenca in ordine di data di ultima modifica.
    C'è qualcos'altro che mi sfugge? C'è forse da indicare qualche altro parametro?

    La documentazione non specifica in quale ordine vengano elencati i file, ma avendo un oggetto di tipo List lo puoi ordinare come ti pare usando un Comparator.

    Io, ad esempio, dopo aver ottenuto il listato, lo ordino in questo modo:

    Collections.sort(lista, ordinatore);

    Dove "lista" è l'oggetto List<FileIdBothDirectoryInformation> e "ordinatore" è un oggetto di una classe che implementa Comparator<FileIdBothDirectoryInformation> il quale mi ordina gli oggetti a mio gusto (ad esempio, questo comparatore ordina gli elementi per nome):

    public class OrdinatoreFiles implements Comparator<FileIdBothDirectoryInformation> {
        @Override
        public int compare(FileIdBothDirectoryInformation f1, FileIdBothDirectoryInformation f2) {
            return f1.getFileName().toLowerCase().compareTo( f2.getFileName().toLowerCase() );
        }
    }
  • Re: Problema puntando ad un NAS con un java.io.File

    22/09/2025 - SpiritoLibero ha scritto:

    Se vuoi andare in profondità dovrai chiedere di andare a leggere il contenuto della sotto-directory che ti interessa.

    Ok, infatti nel mio programma originale ho usato la ricorsione.

    Grazie per l'esempio sull'ordinamento della lista.

    Ora, tornando al mio problema iniziale: come faccio a fare la copia di files dal disco del pc al NAS se per accedere al disco del pc devo usare la libreria java.io.File mentre per accedere al NAS devo usare la smbj?

    In pratica che istruzione o struttura di istruzioni dovrei utilizzare?

    Hai per caso un esempio da mostrarmi?

  • Re: Problema puntando ad un NAS con un java.io.File

    Per copiare un file dal disco del PC al Nas dovrai seguire questi 4 passaggi:

    1) Ottenere un oggetto di tipo com.hierynomus.smbj.share.File che punti al file di destinazione sul Nas (come per l'oggetto java.io.File è semplicemente un segnaposto)
    2) Dall'oggetto com.hierynomus.smbj.share.File ottieni l'OutputStream dove andrai a scrivere il contenuto del file
    3) Apri il file sorgente in lettura, ottenendo un InputStream, leggi dall'InputStream e scrivi nell'OutputStream
    4) Chiudi tutti gli stream.

    Un esempio pratico:
    Supponiamo che tu voglia copiare il file "/home/utente/miofile.pdf" all'interno della directory "Backup" che si trova nella radice della share del Nas (quindi, per capirci, finirà in smb://<tuo-ip-nas>/NomeShare/Backup).

    java.io.File fileSRC = new java.io.File("/home/utente/miofile.pdf");
    com.hierynomus.smbj.share.File fileDST = 
       share.openFile("Backup/miofile.pdf",                              // Path
                      EnumSet.of(AccessMask.GENERIC_WRITE),              // Access Mask
                      null,                                              // Attributes
                      SMB2ShareAccess.ALL,                               // Share access
                      SMB2CreateDisposition.FILE_CREATE,                 // Create disposition
                      EnumSet.of(SMB2CreateOptions.FILE_RANDOM_ACCESS)   // Create Options
       );
    
    OutputStream os = null;
    FileInputStream fis = null;
    try {
       fis = new FileInputStream( fileSRC );
       os = fileDST.getOutputStream();
    
       int byteReads = 0;
       byte[] buffer = new byte[4096];
       while((byteReads = fis.read(buffer)) >= 0) {
          os.write(buffer, 0, byteReads);
       }
       os.flush();
    } catch (Exception e) {
       e.printStackTrace();
    } finally {
       if (fis != null) {
          try { fis.close(); } catch (Exception e) { }
       }
       if (os != null) {
          try { os.close(); } catch (Exception e) { }
       }
    }

    Se preferisci, puoi usare un try-with-resources, ovviamente, al posto di gestire manualmente la chiusura nel finally.

  • Re: Problema puntando ad un NAS con un java.io.File

    22/09/2025 - SpiritoLibero ha scritto:

    Per copiare un file dal disco del PC al Nas dovrai seguire questi 4 passaggi:

    Caro SpiritoLibero sei un amico! ;-)
    Grazie mille per l'esempio!  


    EDIT: Il problema che avevo segnalato ieri sera è magicamente sparito stamattina dopo il reboot e la riapertura di NetBeans.

    Ti posso dire, con vero piacere, che il mio primo esperimento di copia di un file con il tuo programma di esempio HA FUNZIONATOI!!! :-)

    L'unica cosa che ho scoperto è che mi esegue la copia solo se il percorso delle diretctory esiste già sul NAS di destinazione.

    Come posso fare invece a creare la cartella sul NAS in cui copiare il file?
    Se riesciamo a risolvere anche questa cosa ho finalmente tutti gli elementi per portare avanti il mio programma! ;-)

  • Re: Problema puntando ad un NAS con un java.io.File

    Acc!  

    Ho appena scoperto che il programma va in errore anche se il file di destinazione esiste già!

    Invece con la Files.copy potevo specificare il parametro StandardCopyOption.REPLACE_EXISTING e sovrascriverlo.

    Questa opzione mi è indispensabile.

    C'è una soluzione?

    EDIT: Ho scoperto l'uso dell'opzione SMB2CreateDisposition.FILE_OVERWRITE_IF che permette di creare o sovrascrivere un file!

    Adesso mi resta da capire come creare una cartella.

  • Re: Problema puntando ad un NAS con un java.io.File

    Per poter copiare un file all'interno di una directory, quest'ultima deve ovviamente esistere.

    Se non esiste, va creata.

    La classe DiskShare possiede proprio il metodo mkdir() che prende una stringa contenente il percorso (completo) alla directory da creare.

    Nella documentazione non è specificato, ma credo sia necessario che tutto l'albero specificato nel path esista affinchè la directory possa essere creata; ad esempio, se voglio creare la directory "Backup/MioPC/Backup-2025-09-24/" bisogna che esista la sub-directory "MioPC" all'interno della directory "Backup"; non credo che la libreria sia in grado di costruire con una sola chiamata tutto l'albero nel caso non esistano le directory parent (puoi provare, magari lo fa, la documentazione non dice nulla a riguardo).

  • Re: Problema puntando ad un NAS con un java.io.File

    24/09/2025 - SpiritoLibero ha scritto:

    Per poter copiare un file all'interno di una directory, quest'ultima deve ovviamente esistere.

    Se non esiste, va creata.

    La classe DiskShare possiede proprio il metodo mkdir() che prende una stringa contenente il percorso (completo) alla directory da creare.

    Grazie per le ulteriori indicazioni.

    In questi giorni sto cercando di capire come costruire la struttura del mio programma per la copia sui NAS e altri pc in LAN mantenendo la logica usata per le copie sui dischi USB, ma è un casino perché a parte il metodo mkdir() che va bene, gli altri metodi o non sono simili a quelli del java.io.File o restituiscono i dati in formati differenti.

    Ti farò sapere appena avrò risolto o se avrò ulteriori difficoltà. ;-)

  • Re: Problema puntando ad un NAS con un java.io.File

    24/09/2025 - SpiritoLibero ha scritto:

    Nella documentazione non è specificato, ma credo sia necessario che tutto l'albero specificato nel path esista affinchè la directory possa essere creata; ad esempio, se voglio creare la directory "Backup/MioPC/Backup-2025-09-24/" bisogna che esista la sub-directory "MioPC" all'interno della directory "Backup"; non credo che la libreria sia in grado di costruire con una sola chiamata tutto l'albero nel caso non esistano le directory parent (puoi provare, magari lo fa, la documentazione non dice nulla a riguardo).

    Caro @SpiritoLibero sono felice di annunciare che finalmente sono riuscito a realizzare la parte di programma che esegue le copie dei file sui NAS, con un algoritmo ricorsivo simile a quello usato con la Files.copy

    Sono contentissimo, anche se l'algoritmo con smbj è decisamente più lento del Files.copy.

    Grazie mille per l'aiuto!  Pizza pagata quando vuoi. :-)

  • Re: Problema puntando ad un NAS con un java.io.File

    AIUTOOO!!!!

    Come dicevo sono riuscito a creare la parte di programma per gestire le copie sui NAS, ma ora sono in un incubo!
    Avevo il problema che quando i file da copiare erano pochi andava bene, ma quando nelle cartelle da copiare ci sono migliaia di files diventa di una lentezza esasperante perché per ogni file da copiare deve fare la scansione di tutti i file già presenti nella cartella di destinazione per trovare se il singolo file esiste già e se la sua data di ultima modifica è più vecchia della versione da copiare dal disco del pc. 
    In pratica diventava lento come se dovessi copiare tutti i file presenti. 
    Allora mi sono inventato un algoritmo che non ha bisogno di eseguire la scansione di tutti i file migliaia di volte.
    Questo perché la libreria smbj non ha un metodo per verificare direttamente se un certo file esiste nella cartella di destinazione. 

    Ora però Java sta facendo una cosa assurda!

    Questo test che dovrebbe eseguire la copia del file solo se il tempo di ultima modifica del file di origine è maggiore del relativo tempo del file di destinazione funziona a casaccio!

                if ((lOrigTime > lDestTime) CopyLANFile(ds, fiFile.getPath(), sDest);

    Ovvero ci sono dei file che vengono copiati comunque anche se il test da come risultato un valore falso!!!  È ASSURDO!!!

    Le variabili lOrigTime e lDestTime sono delle long che contengono lOrigTime = (long)fiFile.lastModified(); ed equivalente per il file destinazione.

    Facendomi stampare i due valori a runtime la loro differenza è sempre negativa, eppure alcuni file vengono copiati ugualmente! 

    Cosa devo fare??????

  • Re: Problema puntando ad un NAS con un java.io.File

    02/10/2025 - ZioCrick ha scritto:

    Questo perché la libreria smbj non ha un metodo per verificare direttamente se un certo file esiste nella cartella di destinazione. 

    Veramente la classe DiskShare possiede proprio il metodo fileExists( filePath ) che ritorna true se il percorso passato come parametro (filePath) esiste.

    02/10/2025 - ZioCrick ha scritto:

    Le variabili lOrigTime e lDestTime sono delle long che contengono lOrigTime = (long)fiFile.lastModified(); ed equivalente per il file destinazione.

    Il metodo lastModified() esiste per la classe java.io.File, non per la gestione SMBJ: gli oggetti di tipo FileIdBothDirectoryInformation possiedono il metodo getChangeTime() che ritorna un FileTime il quale possiede il metodo toEpochMillis() che ritorna la data di ultima modifica in millisecondi (equivalente a lastModified())

    Questo mi porta a pensare che ti stia incartando da qualche parte.

    02/10/2025 - ZioCrick ha scritto:

    Cosa devo fare??????

    Direi che devi postare un po' più di codice per capire cosa sta andando male...

  • Re: Problema puntando ad un NAS con un java.io.File

    03/10/2025 - SpiritoLibero ha scritto:

    Veramente la classe DiskShare possiede proprio il metodo fileExists( filePath ) che ritorna true se il percorso passato come parametro (filePath) esiste.

    Il metodo lastModified() esiste per la classe java.io.File, non per la gestione SMBJ: gli oggetti di tipo FileIdBothDirectoryInformation possiedono il metodo getChangeTime() che ritorna un FileTime il quale possiede il metodo toEpochMillis() che ritorna la data di ultima modifica in millisecondi (equivalente a lastModified())

    Si scusa mi sono espresso male.

    Ho visto che la DiskShare ha il metodo fileExists ma non ha un metodo per ricavare la data di ultima modifica del file, cosa per me è fondamentale, perché lo scopo di tutto il programma è proprio quello di eseguire il backup dei soli file modificati di recente rispetto all'ultimo backup.

    Ecco perché uso FileIdBothDirectoryInformation per usare il getChangeTime.

    Ma per questo devo fare il famoso ciclo:

    for (FileIdBothDirectoryInformation f : share.list("Directory", "*")) {

    che mi va a scandire le migliaia di file contenute nella "Directory"!

    E allora mi sono inventato un algoritmo che inizia scorrendo una sola volta la share.list per confrontare le date delle cartelle di destinazione con quelle delle cartelle di origine e poi restano da copiare solo i file nuovi presenti all'origine. Per cui la cosa si è complicata un tantino ma funziona.

    Quello che non funziona è che il test di cui sopra sembra non funzionare sempre, perché certi file me li copia ugualmente anche se non hanno variato la data di ultima modifica, ovvero il test sulle variabili lOrigTime e lDestTime sembra funzionare in modo casuale.

    Direi che devi postare un po' più di codice per capire cosa sta andando male...

    Eh, non è così semplice, perché uso molte mie librerie, per cui dovrei postare dei sorgenti lunghissimi.
    Devo create un esempio ridotto all'osso, che non faccia uso delle mie librerie, ma richiede tempo.

    Se però conosci un modo alternativo al FileIdBothDirectoryInformation per ricavare la data di ultima modifica dei file, per favore fammelo sapere, che magari mi bypassa il problema. ;-)

  • Re: Problema puntando ad un NAS con un java.io.File

    Sono andato a rileggermi per bene uno dei tuoi ultimi interventi e ho visto questo:

    02/10/2025 - ZioCrick ha scritto:

    per ogni file da copiare deve fare la scansione di tutti i file già presenti nella cartella di destinazione per trovare se il singolo file esiste già e se la sua data di ultima modifica è più vecchia della versione da copiare dal disco del pc.

    Secondo me il problema è proprio qui: perchè andare a rileggere tutta la directory per ogni file?

    Nella mia testa la cosa dovrebbe funzionare più o meno così:

    1) Esamino la directory "sorgente" e creo un elenco di tutto il suo contenuto (di primo livello, non mi importa del contenuto delle subdirectory).

    2) Esamino la directory di controparte sulla share: se non esiste la creo e so che tutto il contenuto della sorgente deve essere copiato.

    3) Se la controparte esiste, creo un elenco di tutto il suo contenuto (solo file, non directory; se l'elenco è vuoto so che devo copiare tutta la lista in sorgente).

    4) Per ciascun oggetto della lista sorgente cerco la controparte nella lista destinazione: se non la trovo, l'elemento è da copiare, se la trovo verifico i timestamp e agisco di conseguenza.

    Il punto 4 è tutto lavoro che viene fatto in memoria (la sorgente è stata letta una sola volta e la destinazione pure).

    In questo processo mi occupo solo dei file perchè le directory andranno elaborate in modo ricorsivo.

    Ovviamente, questo meccanismo si occupa solo di copiare i file nuovi/modificati da sorgente a destinazione, non va a fare considerazioni su eventuali file eliminati dalla sorgente.

    Ho buttato giù un programmino di prova per verificare il discorso dei timestamp e non ho nessun tipo di problema: i file nuovi e modificati vengono correttamente copiati, mentre quelli non modificati (tra sorgente e destinazione) vengono saltati.

Devi accedere o registrarti per scrivere nel forum
41 risposte