2014-05-13 4 views
1

안드로이드 클라이언트에서 자바 서버로 이미지를 보내려고합니다. 보내는 이미지의 크기는 약 99kb이지만, 서버는 항상 몇 kb 이하, 때로는 98, 때로는 96 이상을 읽습니다. 그 데이터가 손실 된 이유와 어떻게 이미지를 적절한 방식으로 보낼 수 있는지 알고 싶습니다. 제발 도와주세요 :)안드로이드 클라이언트에서 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와 Buffers는 함께 잘 작동하지 않습니다 .. 버퍼에 데이터를 읽으려고하기 전에 데이터를 훔쳐서는 안되는 데이터를 "훔칠"수 있습니다. 예를 들어 어떤 종류의 버퍼링 된 리더를 사용하여 서버 쪽에서 입력을 읽는다면 버퍼가 다른 부분 일 것이라고 생각하기 때문에 버퍼가 해당 부분의 이미지의 "시작"부분에서 일부 부분을 훔칩니다. 당신은 항상 ..의 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

'파일 대상이 존재 함을 신뢰하지 않습니다'. 'new FileOutputStream()'을 사용하여 파일을 만듭니다. 디렉토리가 있다고 가정하고 있습니다. – EJP

1

, ...

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

... 전체 이미지를 실제로 읽는 중입니까? 따라서 서버 측 에서처럼 루프가 필요합니다.

+0

흠, 좋은 지적입니다. 잠시 후에 확인하겠습니다. –

+0

리피도가 언급했듯이, read는 모든 바이트를 한 번에 반환하지 않을 수 있으며 반환되는 실제 크기를 확인해야합니다. 요청한 양보다 적 으면 다시 읽으십시오. 기본적으로 전체 읽기를 반복하십시오. http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#read%28byte[],%20int,%20int%29 – Raghu

+0

불행히도 그것에 관한 것이 아닙니다.내가 몇 번 체크 아웃했습니다, 클라이언트 쪽에서 메서드를 읽을 항상 올바른 바이트 수를 반환합니다. –

관련 문제