25

OK、ファイルの指定されたディレクトリをソケット経由で転送しようとして、ディレクトリ オブジェクトを arraylist から削除して、ファイルだけが残るようにし、それらを同じソケット経由で 1 つずつ転送します。ここの arraylist はファイルのみで満たされ、ディレクトリはありません。クライアントとサーバーのそれぞれの受信コードと送信コードを次に示します。すべてのデータが最初のファイルに書き込まれていることを除いて、コードはエラーなしで正常に実行されます。後続のファイルはサーバー フォルダーに作成されますが、それらは 0 バイトです。任意の入力をいただければ幸いです。

これは、ファイルを受信するためのサーバー コードです。

public void receive(){


    try {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
//read the number of files from the client
        int number = dis.readInt();
        ArrayList<File>files = new ArrayList<File>(number);
        System.out.println("Number of Files to be received: " +number);
        //read file names, add files to arraylist
        for(int i = 0; i< number;i++){
            File file = new File(dis.readUTF());
            files.add(file);
        }
        int n = 0;
        byte[]buf = new byte[4092];

        //outer loop, executes one for each file
        for(int i = 0; i < files.size();i++){

            System.out.println("Receiving file: " + files.get(i).getName());
            //create a new fileoutputstream for each new file
            FileOutputStream fos = new FileOutputStream("C:\\users\\tom5\\desktop\\salestools\\" +files.get(i).getName());
            //read file
            while((n = dis.read(buf)) != -1){
                fos.write(buf,0,n);
                fos.flush();
            }
            fos.close();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

    }


}

これは、ファイルを送信するためのクライアント コードです。

public void send(ArrayList<File>files){

    try {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        System.out.println(files.size());
//write the number of files to the server
        dos.writeInt(files.size());
        dos.flush();

        //write file names 
        for(int i = 0 ; i < files.size();i++){
            dos.writeUTF(files.get(i).getName());
            dos.flush();
        }

        //buffer for file writing, to declare inside or outside loop?
        int n = 0;
        byte[]buf = new byte[4092];
        //outer loop, executes one for each file
        for(int i =0; i < files.size(); i++){

            System.out.println(files.get(i).getName());
            //create new fileinputstream for each file
            FileInputStream fis = new FileInputStream(files.get(i));

            //write file to dos
            while((n =fis.read(buf)) != -1){
                dos.write(buf,0,n);
                dos.flush();

            }
            //should i close the dataoutputstream here and make a new one each time?
        }
        //or is this good?
        dos.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}
4

3 に答える 3

28

read()-1 が返されるまでソケットを読み取っています。これがストリーム終了条件 (EOS) です。ピアが接続を閉じると、EOS が発生します。1つのファイルの書き込みが終了したときではありません。

各ファイルの前にファイル サイズを送信する必要があります。ファイル数については、すでに同様のことを行っています。次に、そのファイルのバイト数を正確に読み取るようにします。

String filename = dis.readUTF();
long fileSize = dis.readLong();
FileOutputStream fos = new FileOutputStream(filename);
while (fileSize > 0 && (n = dis.read(buf, 0, (int)Math.min(buf.length, fileSize))) != -1)
{
  fos.write(buf,0,n);
  fileSize -= n;
}
fos.close();

readUTF()これらすべてをthrows 時に終了するループで囲むことができますEOFException。もちろん逆に、データを送信する前に送信者writeUTF(filename)に電話する必要があります。writeLong(filesize)

于 2012-04-29T07:37:33.487 に答える
2

私はこのようにしました、それは完全に機能しています、あなたは見てみることができます:

送信

byte[] done = new byte[3];
String str = "done";  //randomly anything
done = str.getBytes();
for (int i = 0; i < files.size(); i++) {
    System.out.println(files.get(i).getName());
    FileInputStream fis = new FileInputStream(files.get(i));
    while ((n = fis.read(buf)) != -1) {
        dos.write(buf, 0, n);
        System.out.println(n);
        dos.flush();
    }
    //should i close the dataoutputstream here and make a new one each time?                 
    dos.write(done, 0, 3);
    dos.flush();
}
//or is this good?
dos.close();

受け取る

for (int i = 0; i < files.size(); i++) {
    System.out.println("Receiving file: " + files.get(i).getName());
    //create a new fileoutputstream for each new file
    fos = new FileOutputStream("C:\\users\\tom5\\desktop\\salestools\\" + files.get(i).getName());
    //read file
    while ((n = dis.read(buf)) != -1 && n != 3) {
        fos.write(buf, 0, n);
        fos.flush();
    }
    fos.close();
}
于 2012-04-29T07:37:57.027 に答える