2014-05-13 64 views
1

我试图从Android客户端向Java服务器发送我的图像。我发送的图像大小约为99kb,但服务器总是读取几个kb,有时是98,有时是96,等等。我想知道为什么这些数据丢失了,如何以适当的方式发送图像。请帮助:)从Android客户端向Java服务器通过套接字发送图像时的数据丢失

代码:

Client(sending image): 
    public void sendImage(File file){ 
     try { 
      out = new PrintWriter(socket.getOutputStream(),true); 
      out.println("Image"); 
      out.println(file.length()); 
      byte[] byteArray = new byte[(int) file.length()]; 
      FileInputStream fis = new FileInputStream(file); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      bis.read(byteArray,0,byteArray.length); 
      OutputStream os = socket.getOutputStream(); 
      FilterOutputStream bos = new FilterOutputStream(os); 
      bos.write(byteArray,0,byteArray.length); 
      bos.flush(); 
      os.close(); 
      bis.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

服务器(接收图像):

if(input.equals("Image")){ 
         input = in.readLine(); 
         int fileSize = Integer.parseInt(input); 
         System.out.println("FILESIZE:" +fileSize); 
         byte[] byteArray = new byte[fileSize]; 
         FileOutputStream fileOutputStream = 
           new FileOutputStream("filename.jpg"); 
         BufferedOutputStream bos = 
           new BufferedOutputStream(fileOutputStream); 
         BufferedInputStream bis = new BufferedInputStream(in_); 
         int bytesRead = bis.read(byteArray, 0, byteArray.length); 
         int current = bytesRead; 
         do { 
           bytesRead = bis.read(byteArray, current, 
               (byteArray.length - current)); 
           if (bytesRead >= 0) { 
            current += bytesRead; 
            System.out.println(current); 
           } 
         } while (bytesRead != -1); 
         bos.write(byteArray, 0, current); 
         bos.flush(); 
         bos.close(); 
} 

编辑 问题解决了,工作代码如下:

客户端:

 public void sendImage(File file){ 
      try { 
        DataOutputStream out = new DataOutputStream(
          socket.getOutputStream()); 
        out.writeChar('I'); 
        DataInputStream dis = new DataInputStream(new FileInputStream(file)); 
        ByteArrayOutputStream ao = new ByteArrayOutputStream(); 
        int read = 0; 
        byte[] buf = new byte[1024]; 
        while ((read = dis.read(buf)) > -1) { 
         ao.write(buf, 0, read); 
        } 

        out.writeLong(ao.size()); 
        out.write(ao.toByteArray()); 
        out.flush(); 
        out.close(); 
        dis.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
     } 

服务器端:

   if(input =='I'){ 
        DataInputStream dis = new DataInputStream(clientSocket.getInputStream()); 
        long length = dis.readLong(); 
        File to = new File("filename.jpg"); 
        DataOutputStream dos = new DataOutputStream(
          new FileOutputStream(to)); 
        byte[] buffer = new byte[1024]; 
        int len, current = 0; 
        System.out.println(length); 
        while (current != length) { 
         len = dis.read(buffer); 
         dos.write(buffer, 0, len); 
         current += len; 
         System.out.println(current); 
        } 
        dis.close(); 
        dos.close(); 
       } 
+0

难道是你的服务器是在写入图像的方式吗?也许剥离一些元数据或什么?只是吐口水的想法... – Guardanis

+0

恐怕我不知道。奇怪的是,当我发送图像与bitmap.compress方法(但我不想使用位图)图像到达不受伤害。 –

+0

我想知道如果压缩版本也可能会剥离它与您的服务器'可能'一样吗? – Guardanis

回答

3

从我的个人经验PrintWriter和缓冲区不能很好地一起工作.. 作为缓冲区试图读取数据之前,你告诉它它可以“窃取”它不应该做的数据。例如,如果您使用任何种类的缓冲读取器来读取服务器端的输入,缓冲器将在发送图像的“开始”处窃取一些部分,因为它认为它只是另一条线。你总是可以尝试使用DataInputStream和DataOutputStream类,而不是..

客户:

public void sendImage(File file) { 
    try { 
     DataOutputStream out = new DataOutputStream(
       socket.getOutputStream()); 
     out.writeChar('I'); // as image, 
     DataInputStream dis = new DataInputStream(new FileInputStream(file)); 
     ByteArrayOutputStream ao = new ByteArrayOutputStream(); 
     int read = 0; 
     byte[] buf = new byte[1024]; 
     while ((read = dis.read(buf)) > -1) { 
      ao.write(buf, 0, read); 
     } 
     out.writeLong(ao.size()); 
     out.write(ao.toByteArray()); 
     out.flush(); 
     out.close(); 
     dis.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

服务器:

// assuming folder structure exists. 
public void readImage(Socket s, File to) throws IOException { 

    DataInputStream dis = new DataInputStream(s.getInputStream()); 
    char c = dis.readChar(); 
    if (c == 'I') { 
     long length = dis.readLong(); 
     DataOutputStream dos = new DataOutputStream(
       new FileOutputStream(to)); 
     byte[] buffer = new byte[1024]; 
     int len; 
     while ((len = dis.read(buffer)) != -1) { 
      dos.write(buffer, 0, len); 
     } 
     dis.close(); 
     dos.close(); 
    } 

} 
+0

非常感谢,它的工作原理! –

+1

你不是'相信文件目标存在'。你正在用'新的FileOutputStream()'来创建它。你只是假设目录存在。 – EJP

1

作为一个起点,在客户端,您还需要读取本地图像的循环,因为你确定......

bis.read(byteArray,0,byteArray.length); 

......真的在读整个图像吗?所以你也需要一个循环,就像在服务器端一样。

+0

嗯,好点,我会检查它,当我会有一个时刻。 –

+0

正如lipido提到的,read不一次就可以返回所有的字节,你需要检查返回的实际大小。如果它小于你的要求,请重新阅读。基本上把整个读取放在一个循环中。 http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read%28byte[],%20int,%20int%29 – Raghu

+0

不幸的是,这不是关于它。我已经检查了几次,客户端的读取方法总是返回正确的字节数。 –

相关问题