2012-09-27 72 views
4

用來工作的Java 6下的優質下面的代碼(或更早),但它停止更新到JRE 7(Java 7中)之後的工作。Java 7的URL連接故障

的URL是一個FTP文件:

ftp://ftp-private.ncbi.nlm.nih.gov/pubchem/.fetch/96/4133257873201306969.sdf.gz

這裏是輸出我得到:

應用程序/八位字節流 -1 [Ljava.lang。 StackTraceElement的; @ 5419f97c

這裏是我的代碼:

public static void store(URL url, File targetFile){ 
    try 
    { 
    System.out.println(url); 
    URLConnection uc = url.openConnection(); 
    String contentType = uc.getContentType(); 
    System.out.println(contentType); 
    int contentLength = uc.getContentLength(); 
    System.out.println(contentLength); 
    Settings.setDownloadSize(contentLength); 
    if (contentType.startsWith("text/") || contentLength == -1) { 
     throw new IOException("This is not a binary file."); 
    } 
    InputStream raw = uc.getInputStream(); 
    InputStream in = new BufferedInputStream(raw); 
    byte[] data = new byte[contentLength]; 
    int bytesRead = 0; 
    StatusPanel.updateProgrssBar(bytesRead); 
    int offset = 0; 
    while (offset < contentLength) { 
     bytesRead = in.read(data, offset, data.length - offset); 
     if (bytesRead == -1) { 
      break; 
     } 
     offset += bytesRead; 
     StatusPanel.updateProgrssBar(offset); 
    } 
    in.close(); 

    if (offset != contentLength) { 
     throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes"); 
    } 

    FileOutputStream out = new FileOutputStream(targetFile); 
    out.write(data); 
    out.flush(); 
    out.close(); 
    //StatusPanel.setStatus("File has been stored at " + targetFile.toString()); 
    //System.out.println("file has been stored at " + targetFile.toString()); 
} 

內容長度返回-1:

Area: API: Networking 
Synopsis: Server Connection Shuts Down when Attempting to Read Data When http Response Code is -1 

如何使這個代碼與Java 7兼容?

說明:作爲錯誤修正爲CR 6886436的結果是,在HTTP協議處理程序將關閉到發送沒有有效的HTTP狀態行的響應的服務器的連接。發生這種情況時,嘗試讀取該連接上的數據會導致IOException。

例如,下面的代碼是有問題的:

public static void test() throws Exception { 

..... 
HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); 
.... 

System.out.println ("Response code: " + urlc.getResponseCode()); 

/** Following line throws java.io.IOException: Invalid Http response 
* when Response Code returned was -1 
*/ 
InputStream is = urlc.getInputStream(); // PROBLEMATIC CODE 

要解決此問題,從getResponseCode方法檢查返回值並處理-1值適當地;也許通過打開一個新的連接,或者在流上調用getErrorStream。 不相容性質:行爲 RFE:7055058

這個問題肯定是用getContentLength()的方法。

隨着JRE6,該方法返回一個值,但與JRE7我得-1。基於對URLConnectionJava 7's Javadoc

+1

可能值得檢查服務器返回的內容長度,例如,通過Wireshark嗅探網絡。另外,你確定相同的代碼仍然適用於Java 6嗎?即是否已經消除了您更改爲Java 7並且停止工作的巧合? – DNA

+0

它適用於Java 6.它不是一致的。我對此100%肯定。查看添加的內容。在這種情況下,url是ftp。不是HTTP .. – lochi

回答

1

有這種情況的發生可能有兩個原因。

第一個可能的原因是,內容長度大於Integer.MAX_VALUE。要確定這是否是問題,我將使用getContentLengthLong(),因爲這會返回長整型而不是整數,如果內容長度大於Integer.MAX_VALUE getContentLength()將返回-1。此外,自Java 7以來,Java 7's URLConnection Javadoc中的getContentLength()優先使用getContentLengthLong(),「它返回一個長整型,因此更具可移植性。」如果您希望同時使用JRE 6和7,那麼我將創建一個Java 6和7包裝類,以創建一組應用程序用來與URL進行交互的方法。與應用程序的啓動腳本相比,檢查主機是否具有JRE 6或7,並根據JRE版本加載適當的包裝類。這通常是一個良好的設計,因爲它可以防止應用程序從依賴於一種特定的JRE,第三方庫或應用程序等

第二種可能性是,內容長度報頭字段不是由服務器已知的,因此getContentLength()getContentLengthLong()方法返回值-1。這就是爲什麼我建議在其他任何事情之前嘗試getContentLengthLong(),因爲它可能是最快的解決方案。如果兩個方法都返回-1,我會建議使用像[Apache JMeter] [11]這樣的應用程序來確定頭信息。這樣做的一個快速方法是讓JMeter「HTTP Proxy Server」在您的瀏覽器代理設置設置爲使用localhost作爲您爲端口設置HTTP代理服務器的地址和端口的情況下運行。記錄的信息將作爲單獨的元素本身出現,如果你擴展它們,應該有一個HTTP Header Manager,它包含每個Header的名稱和它旁邊的值。

最後,您可能想對服務器本身進行分析,看看是否有任何問題。驗證日誌看起來不錯,所有正確的進程都啓動,配置設置正確,文件仍然存在並位於正確的位置等等。也許服務器沒有設置爲對內容長度請求做出響應。此外,請驗證您的代碼是否可以在另一主機上使用JRE 7功能

我希望這些建議對您有價值,並且您能夠解決您似乎遇到的問題。我還會注意到,你真的應該考慮使用一個包裝類,並遵循你將來使用的每個第三方類的註釋,以便你遵循更好的實踐,更容易維護,比如減少你擁有的外部依賴的數量通過使用包裝類。

+0

謝謝。但是,java 7 java doc與這個問題無關。該程序是基於Java 6編寫的。它在jre 6上運行良好。對於jre 7,它不會... uc.getContentLength()返回-1。 getContentLengthLong()僅在java 7中存在.ftp文件非常小。 – lochi

+1

我永遠不會說Javadoc是無關緊要的,因爲任何人編寫代碼和Javadoc評論確定信息足夠重要,以至於程序員可能需要使用它們的代碼(例如URLConnection)。許多程序員會做的一件事就是創建包裝類,這樣如果發生變化,只要包裝被更新,程序就不會受到變化的影響。在這種情況下,您將擁有使用相同方法的包裝,但是其中一個用於Java 6,另一個用於Java 7,並確定要使用哪個方法快速檢查JRE版本。 –

+0

嗨馬特,感謝您的意見。當Sun將jre從1.3升級到1.4時,這個問題一直存在。爲什麼jre 1.7返回-1的文件內容長度仍然是一個謎。作爲臨時修復,我決定用一個不確定的進度條替換下載進度條。 – lochi