Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it L'avatar di 511769
    Registrato dal
    Mar 2010
    Messaggi
    15

    [Java] Trasferimento file via socket

    Ciao a tutti!

    Sto realizzando un piccolo programma che trasferisce file via socket:in poche parole leggo un file byte per byte, metto questi byte in un array che scrivo sulla socket e li ricevo dall'altra parte.

    Parte del codice del client:
    codice:
     Socket socket = new Socket("127.0.0.1", 1234); 
     ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
     FileInputStream fis = new FileInputStream("prova.jar");
     int x = 0;
     int i = 0;     
     while((i=fis.read())!=-1)//calcolo la lunghezza esatta del file in modo da creare un array
     {                             //ad hoc
            x++;
     }
     while((i=fis.read(buf))!=-1) {}//riempo l'array con i byte del file
     byte[] buf = new byte[x];//creo l'array che conterrà i byte
     oos.write(buf);//scrivo sullo stream
     oos.flush();
    Dal lato server invece:
    codice:
     ServerSocket ss = new ServerSocket(SERVER_PORT);
     FileOutputStream fos = new FileOutputStream("prova.jar");
     Socket s = ss.accept();
     ObjectInputStream oin = new ObjectInputStream(s.getInputStream());//stream da cui               
                                                                                                  //ricevere i byte
     byte[] buf = new byte[l];//creo un array in cui mettere  byte(la lunghezza è identica a    
                                      //quello creato nel client
     oin.read(buf);//leggo i byte dallo stream e li metto nell'array
     fos.write(buf);//scrivo in un file i byte ricevuti
     fos.flush();
    Il problema è che l'array è pieno di byte tutti a zero, mentre sono sicuro che il file di partenza pieno! Sto lavorando su dei file .jar, ma siccome mi vengono trasferiti sempre dei byte a zero quando tento di aprire il file scritto dal server mi dice che non riconosce l'estensione. Mi sapreste aiutare?

  2. #2
    Utente di HTML.it L'avatar di 511769
    Registrato dal
    Mar 2010
    Messaggi
    15
    Ho scoperto il motivo dei byte zero:dimenticavo di riaprire lo stream di input.
    Ora ho un altro problema:quando tento di aprire con winzip il file jar trasferito, mi dice "inaspettata fine dell'archivio" eppure i byte li ha trasferiti tutti!

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Innanzitutto se si vuole avere la lunghezza di un file basta usare un java.io.File e il suo length().

    Leggere tutto il contenuto del file solo per determinare la lunghezza non è il massimo della furbizia .... anche per un altro motivo: ormai sei arrivato a fondo, non leggi più nulla e dovresti istanziare un nuovo FileInputStream perché non c'è modo di tornare indietro con lo stesso FileInputStream.

    Anche il fatto di leggere l'intero contenuto e metterlo in un array non è il massimo della furbizia, dipende ovviamente dalle dimensioni del file. Ma in ogni caso c'è sempre un approccio migliore.
    Che è quello di usare un array di byte di dimensioni prefissate e relativamente piccolo (es. 1024 byte o giù di lì) che fa da buffer e leggere a "blocchi" di byte. Cioè leggi un blocco da file e lo scrivi su socket, leggi un altro blocco ecc.....

    Per la questione del trasferimento client-server c'è un discorso sul "protocollo". Se l'unica informazione trasferita è proprio solo il contenuto del file ... è un conto. Cioè se il mittente invia il contenuto del file, quindi close() e basta, dall'altra parte non ci sarebbero dubbi nel capire quando lo stream è finito.
    In genere comunque è sempre bene anticipare al destinatario la dimensione di una sequenza di dati di lunghezza arbitraria. E questo tipicamente si fa inviando come "intestazione" ad esempio 4 byte che compongono un int (o 8 per un long) con la lunghezza della sequenza.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Utente di HTML.it L'avatar di 511769
    Registrato dal
    Mar 2010
    Messaggi
    15
    Originariamente inviato da andbin
    Innanzitutto se si vuole avere la lunghezza di un file basta usare un java.io.File e il suo length().

    Leggere tutto il contenuto del file solo per determinare la lunghezza non è il massimo della furbizia .... anche per un altro motivo: ormai sei arrivato a fondo, non leggi più nulla e dovresti istanziare un nuovo FileInputStream perché non c'è modo di tornare indietro con lo stesso FileInputStream.

    Anche il fatto di leggere l'intero contenuto e metterlo in un array non è il massimo della furbizia, dipende ovviamente dalle dimensioni del file. Ma in ogni caso c'è sempre un approccio migliore.
    Che è quello di usare un array di byte di dimensioni prefissate e relativamente piccolo (es. 1024 byte o giù di lì) che fa da buffer e leggere a "blocchi" di byte. Cioè leggi un blocco da file e lo scrivi su socket, leggi un altro blocco ecc.....

    Per la questione del trasferimento client-server c'è un discorso sul "protocollo". Se l'unica informazione trasferita è proprio solo il contenuto del file ... è un conto. Cioè se il mittente invia il contenuto del file, quindi close() e basta, dall'altra parte non ci sarebbero dubbi nel capire quando lo stream è finito.
    In genere comunque è sempre bene anticipare al destinatario la dimensione di una sequenza di dati di lunghezza arbitraria. E questo tipicamente si fa inviando come "intestazione" ad esempio 4 byte che compongono un int (o 8 per un long) con la lunghezza della sequenza.
    Grazie per i tuoi consigli, in ogni caso ho delineato il problema:alcuni byte pare che vadano persi o non trasferiti sulla socket. L'ho capito trasferendo un'immagine e quello che mi risulta dall'altra parte è un immagine troncata per un quarto. Cioè arrivano solo alcuni pixel dell'immagine ma non tutta! Come posso evitare questo?

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da 511769
    Come posso evitare questo?
    Rileggi quanto ho detto prima ..... c'è la soluzione a tutto quanto.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Utente di HTML.it L'avatar di 511769
    Registrato dal
    Mar 2010
    Messaggi
    15
    Originariamente inviato da andbin
    Rileggi quanto ho detto prima ..... c'è la soluzione a tutto quanto.
    Divido in tanti piccoli array il mio flusso di byte?

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da 511769
    Divido in tanti piccoli array il mio flusso di byte?
    Di array istanziato, come oggetto, ne avrai 1 solo. Chiaramente devi fare un ciclo in cui leggi un "blocco" di byte.

    E per l'altra questione, del protocollo, ripeto che in genere è preferibile anticipare al destinatario la quantità di dati che deve aspettarsi.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.