0

发送端 - 它在 android 中,它是 AsyncTask、doInBackground 的一部分。基本上,它将文件名、大小和图像数据发送到服务器端。

                InetAddress serverIP = InetAddress.getByName(IP);
                Socket client = new Socket(serverIP,SERVER_PORT);
                System.out.println("Connected to Server\n");
                System.out.println(imgFile.length());
                //sending name of the file
                PrintWriter name = new PrintWriter(new OutputStreamWriter(client.getOutputStream()),true);
                name.println(fileName);
                name.flush();
                //sending size of the file
                name.println(imgFile.length());
                name.flush();

                //sending body
                DataInputStream imgBodyIn = new DataInputStream(new FileInputStream(imgFile));
                DataOutputStream imgBodyOut = new DataOutputStream(client.getOutputStream());
                byte[] buffer = new byte[BUFFER_SIZE];
                int len;
                long filesize = imgFile.length();
                while(filesize >=0&& (len=imgBodyIn.read(buffer,0,(int)Math.min(buffer.length,filesize)))>0){
                    imgBodyOut.write(buffer,0,len);
                    filesize-=len;
                }
                name.close();
                imgBodyIn.close();
                imgBodyOut.flush();
                imgBodyOut.close(); 
                client.close();

接收方

          //receiving name
          BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));             
          String name = in.readLine();
          System.out.println("Name of the File : " + name+".JPG");
          //receiveing size info
          String size = in.readLine();
          System.out.println("Size of the File :"+size +"bytes");

          //storing file
          File f = new File("/home/ubuntu", name+".JPG");
          FileOutputStream output = new FileOutputStream(f);

          int len=0;
          long received=0;
          byte[] buf = new byte[BUFFER];
        while(received<=Long.parseLong(size)&&(len=sock.getInputStream().read(buf))>0)
         {  

            output.write(buf,0,len);
            received +=len;
            System.out.print("Receiving.."+received +"/"+size+"\r");


         }    
         output.flush();
         output.close();
         in.close();
         System.out.println("\n"+name+".JPG received");
         System.out.println("Size received :"+f.length()+"bytes");

当我尝试发送文件时,会传输正确的大小信息和名称。但是,我无法收到完整的文件;缺少一些字节。我使用的缓冲区大小是 1024。

样品运行:

 Waiting for client to connect..
Client Accepted

Name of the File : P1011474.JPG
Size of the File :714438bytes
Receiving..712997/714438
P1011474.JPG received
Size received :712997bytes

socket closed
4

1 回答 1

0

很可能是BufferedReader在接收端,它包含一个内部缓冲区,以在从流中读取时提高性能。请参阅Javadoc

从字符输入流中读取文本,缓冲字符,以便高效读取字符、数组和行。

因此,它不仅会阅读两行,还不如在两行之后提前阅读。因此,您附加的二进制图像的一部分也可能被缓冲。然后,当您尝试直接从InputStream包装中读取二进制数据时DataInputStream,您将不会收到已在BufferedReader实例中缓冲的字节。

我建议您不要使用 aPrintWriter而是直接使用 from 的方法写入文件名和长度DataOutputStream,例如:

out.writeUTF(fileName);
out.writeLong(imgFile.length());

在接收方使用read*,DataInputStream而不是BufferedReader. 如果要缓冲,请将套接字包装InputStreamBufferedInputStream

 DataInputStream dis = new DataInputStream(
     new BufferedInputStream(socket.getInputStream()));
 String fileName = dis.readUTF();
 long fileLength = dis.readLong();
 // now read file contents from stream

顺便说一句,您不必这样做:

imgBodyIn.read(buffer,0,(int)Math.min(buffer.length,filesize))

从文件中读取图像时,只需执行以下操作:

 imgBodyIn.read(buffer, 0, buffer.length)

流/文件的结尾被识别并read()返回读取的字节长度,所以你不需要做Math.min().

于 2013-07-02T18:23:32.627 回答