2013-04-15 3 views
1

서버에서 일부 파일을 다운로드하기 위해 다음 코드를 작성했지만이 코드가 전체 응답 (inputStream)을 읽지 못하는 것이 문제입니다. 파일 크기는 7.5MB이고 매번 5.5MB를 얻는 반면 어도비 리더는 파일이 손상되었다고 불평합니다. 내가 잘못 여기서 뭐하는 거지URLConnection inputStream이 완전히 읽히지 않습니다.

모든 아이디어를 여기에 코드

import java.net.URLConnection; 
public class Downloader { 
URL url; 
public Downloader(){ 
    try { 

     url = new URL("https://d396qusza40orc.cloudfront.net/algs4partI/slides%2F13StacksAndQueues.pdf"); 
     FileOutputStream outStream; 
     ObjectOutputStream oStream; 
     try { 
      URLConnection con = url.openConnection(); 
      InputStream inStream = con.getInputStream(); 
      outStream = new FileOutputStream("data.pdf"); 
      oStream = new ObjectOutputStream(outStream); 
      int bytesRead; 
      int totalBytesRead = 0; 
      byte[] buffer = new byte[100000]; 
      while((bytesRead = inStream.read(buffer)) > 0){ 

       //outStream.write(buffer, 0 , bytesRead); 
       oStream.write(buffer, 0, bytesRead); 
       buffer = new byte[100000]; 
       totalBytesRead += bytesRead; 
      } 
      System.out.println("Total Bytes read are = " + totalBytesRead); 
      oStream.close(); 
      outStream.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
public static void main(String[] args){ 
    Downloader d = new Downloader(); 
} 

}는 무엇입니까? 미리 감사드립니다.

+2

'ObjectOutputStream'을 사용하는 이유가 있습니까? –

+0

파일의 실제 크기는 5,383KB입니다. 그리고'ObjectOutputStream'을 제거하고'FileInputStream'에 쓰는 것은 나를 위해 완벽하게 작동했습니다. –

+1

읽을 때마다 새 버퍼를 만들 필요가 없습니다. 당신은 단지 가비지 컬렉터를위한 작업을 만들고 있습니다. – EJP

답변

1

자바 객체를 직렬화하지 않을 때 ObjectOutputStream을 사용하고 싶지는 않습니다.

라인

//outStream.write(buffer, 0 , bytesRead); 

을 취소합니다 주석과

oStream.write(buffer, 0, bytesRead); 

그래서 제거 :

while((bytesRead = inStream.read(buffer)) > 0){ 

    outStream.write(buffer, 0 , bytesRead);   
    buffer = new byte[100000]; // this line is useless 
    totalBytesRead += bytesRead; 
} 

은 전부 ObjectOutputStream 제거하십시오. 파일 크기는 7.5 MB가 아니라 5.25 MB (5,511,685 바이트)입니다.

+0

제안한대로 FileOutputStream으로 변경하면 매력처럼 작동합니다! 맨 아래, ObjectOutputStream을 없앴습니다 :) 대단히 감사합니다. – KMH

+0

이것이 현재의 문제를 변경하지는 않지만 루프 내에서 byte []를 재 할당하는 것은 아무런 도움이되지 않습니다. – GPI

+0

그래, 도망 갔을 때 나는 그것을 제거했다. –

1

InputStream URL 연결에서 가져온 것은 모든 바이트가 한 번에 도착한다고 보장하지 않습니다. 네트워크를 통해 전송되므로 읽기 속도가 네트워크보다 높을 수 있습니다. 메서드 read()은 메서드의 현재 실행시 읽은 바이트 수를 반환합니다. 0을 반환하면 정보는 현재 사용할 수 없지만 나중에 사용할 수 있습니다.

메서드 read()은 스트림 끝을 나타내는 -1을 반환합니다. 결론 : if 명세서의 > 0>= 0으로 변경하십시오.

+0

'read()'가 -1을 반환하면 루프가 멈 춥니 다. 'read()'가 0을 반환하면, 루프는 멈출 것이다. 나는 그가 덮인다고 생각한다. –

+1

사실, 이것이 도움이되지 않을 것이라고 생각합니다. javadoc에 따르면'read' 메서드는'-1'을 반환하거나 1 또는 bytes를 읽습니다. 따라서 0보다 큰 수를 반환합니다. –

+0

@StephenC의 주석'이 메서드는 입력 데이터를 사용할 수있을 때까지 차단합니다. , 파일의 끝이 감지되거나 예외가 throw됩니다. [출처] (http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read (byte [])) – thegrinner

0

문제점은 ObjectOutputStream을 사용중인 것입니다. 이것은 PDF 리더가 기대하거나 요구하지 않는 Java 객체 직렬화 형식으로 출력을 인코딩합니다.

일반 FileOutputStream을 사용하면 올바르게 작동합니다.

+0

그래, 맞아! 고맙습니다 :) – KMH