Newsgroup: it.comp.java
Titolo: Trasportare file in una socket: help!

Salve a tutti e Buon 2002!
Ho necessità di trasportare file qualsiasi attraverso una socket. In pratica
ho creato una coppia di programmini client e server. Il server aspetta una
connessione (monothread, normale, per ora) e il client si connette, richiede
un file (il cui nome si digita da input), e il server lo spedisce. Fine. Il
problema è che i file non-ASCII (mp3, jpg, etc.) vengono irrimediabilmente
corrotti nella trasmissione, mentre nessun problema per i file di testo. Di
sicuro è qualcosa che ha a che vedere con la socket, perchè le classi che
uso per accedere ai file funzionano se le uso in un unico programma. Ecco il
programmino Copya, che semplicemente copia un file in un altro e funziona a
meraviglia:
 public static void main(String[] args) throws IOException {
 File inputFile = new File(args[0]);
 File outputFile = new File(args[1]);
 System.out.println("Copio il file " + args[0] + "nel file "+ args[1]+ ".");
        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outputFile);
        int c;
        while ((c = in.read()) != -1){  // Va bene leggere un intero alla
volta? Non c'è un modo più efficiente? Cmq funge
           out.write(c);}
        in.close();
        out.close();
Il programma che invece NON funziona è questo (solo parti importanti):
SERVER
 ServerSocket serverSocket = null;
 serverSocket = new ServerSocket(4444);
  Socket clientSocket = serverSocket.accept();
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
        BufferedReader in = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
        String nomeFile;
        nomeFile=in.readLine();
        System.out.println("Ho ricevuto la richiesta del file: "+nomeFile);
        File inputFile = new File(nomeFile);
        FileInputStream ingresso = new FileInputStream(inputFile);
        int c;
        while ((c = ingresso.read()) != -1) out.write(c);
        }
  System.out.println("Upload Terminato!");
        ingresso.close();
        out.close();
        in.close();
        clientSocket.close();
        serverSocket.close();
    }
}
Penso che il problema sia nell'oggetto out, che in effetti identifica la
socket "in uscita" dove mando gli int che leggo dal file. Ho notato che gli
int dall'altra parte della socket in effetti non sempre sono gli stessi, e
infatti il file viene corrotto. Ma che classe devo usare?
Riporto anche il client:
CLIENT
 Socket echoSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;
            echoSocket = new Socket("localhost", 4444);
            out = new PrintWriter(echoSocket.getOutputStream(), true);
            in = new BufferedReader(new
InputStreamReader(echoSocket.getInputStream()));
 BufferedReader stdIn = new BufferedReader(new
InputStreamReader(System.in));
 String nomeFile;
 System.out.println("Inserire nome file da scaricare:");
 nomeFile=stdIn.readLine();
 out.println(nomeFile);
 System.out.println("Download in corso...");
 File inputFile = new File(nomeFile+"3");
 FileOutputStream scrittura = new FileOutputStream(inputFile);
 int c;
 while ((c = in.read()) != -1)            scrittura.write(c);
 scrittura.close();
 out.close();
 in.close();
 stdIn.close();
 echoSocket.close();
    }
}
Sperando di aver fatto capire il problema, visto che sono ancora agli esordi
con Java; aspetto consigli e ringrazio in anticipo.

 
PrintWriter e BufferedReader sono specifici per flussi di caratteri.
Puoi usare direttamente InputStream ed OutputStream:
import java.io.*;
import java.net.*;
public class ByteClient
{
	public static void main(String[] args)throws Exception
	{
		Socket sock=new Socket("localhost",4444);
		InputStream in=sock.getInputStream();
		int oneByte=-1;
		while((oneByte=in.read())!=-1)
			System.out.println(oneByte);
		in.close();
		sock.close();
	}
}
class ByteServer
{
	public static void main(String[] args)throws Exception
	{
		ServerSocket serv=new ServerSocket(4444);
		Socket sock=serv.accept();
		OutputStream out=sock.getOutputStream();
		for(int i=0;i<256;i++)
			out.write(i);
		out.close();
		sock.close();
		serv.close();
	}
}
Esistono anche i metodi InputStream.read(byte[]) e
OutputStream.write(byte[]) che potrebbero fare al caso tuo.
HTH,
Mauri.
P.s.: tutto ciò è così ben documentato che...
-- 
La forza di gravità è un falso mito,
è la Terra che succhia!

Ehm, praticamente serializzazione in tre thread differenti:)
Quello che voglio consigliarti č passare direttamente alla serializzazione
dell'oggetto java.io.File, se devi passare tra i due processi solo files.
Secondo me č il modo migliore per non incasinarsi l'esistenza.
Giuseppe

 P.s.: tutto ciň č cosě ben documentato che...
Lo so sicuramente č semplicissimo trovare info su queste classi ma,
nonostante io abbia manuali e manualetti, e abbia letto numerosi articoli su
Internet, ho trovato sempre info frammentarie e anche abbastanza confuse...
Un altro favore (x favore;-) ho notato che il trasferimento č abbastanza
lento... Non c'č un modo per trasferire il file piů rapidamente? Magari
leggendo i byte a gruppi e non uno a uno...
Grazie!

leggendo i byte a gruppi e non uno a uno...
import java.io.*;
import java.net.*;
public class ByteServer
{
	public static void main(String[] args)throws Exception
	{
		byte[] chunk=new byte[256];
		for(int i=0;i<256;i++)
			chunk[i]=(byte)i;
		ServerSocket serv=new ServerSocket(4444);
		Socket sock=serv.accept();
		OutputStream out=sock.getOutputStream();
		out.write(chunk);
		out.close();
		sock.close();
		serv.close();
	}
}
class ByteClient
{
	public static void main(String[] args)throws Exception
	{
		byte[] chunk=new byte[256];
		Socket sock=new Socket("localhost",4444);
		InputStream in=sock.getInputStream();
		int len=in.read(chunk);
		for(int i=0;i<len;i++)
			System.out.println(chunk[i]);
		in.close();
		sock.close();
	}
}
Ma mi sa che il bottleneck lo troverai sulla rete, quando uscirai da
localhost, quindi la performance non cambierà.
Ah, occhio che ora il client stampa dei byte, (da -128 a 127) anzichè
degli int (0 - 255).
Good luck,
Mauri.
