2017-10-06 45 views
0

我想建立一個手動HTTP客戶端(使用套接字)以及緩存,我似乎無法弄清楚爲什麼這些文件沒有正確保存到磁盤。它對HTML文件非常有用,但似乎無法用於其他類型的文件,如基於.gif的文本。有誰能告訴我爲什麼?我對HTTP協議和Socket編程一般都很陌生。HTTP手動客戶端沒有正確寫入磁盤JAVA

循環獲取響應。

InputStream inputStream = socket.getInputStream(); 
    PrintWriter outputStream = new PrintWriter(socket.getOutputStream()); 

    ArrayList<Byte> dataIn = new ArrayList<Byte>(); 
    ArrayList<String> stringData = new ArrayList<String>(); 

    //Indices to show the location of certain lines in arrayList 
    int blankIndex = 8; 
    int lastModIndex = 0; 

    int byteBlankIndex = 0; 

    try 
    { 
     //Get last modified date 
     long lastMod = getLastModified(url); 
     Date d = new Date(lastMod); 

     //Construct the get request 
     outputStream.print("GET "+ "/" + pathName + " HTTP/1.1\r\n"); 
     outputStream.print("If-Modified-Since: " + ft.format(d)+ "\r\n"); 
     outputStream.print("Host: " + hostString+"\r\n"); 
     outputStream.print("\r\n"); 
     outputStream.flush(); 

     //Booleans to prevent duplicates, only need first occurrences of key strings 
     boolean blankDetected = false; 
     boolean lastModDetected = false; 

     //Keep track of current index 
     int count = 0; 

     int byteCount = 0; 

     //While loop to read response 
     String buff = ""; 
     byte t; 
     while ((t = (byte) inputStream.read()) != -1) 
     { 
      dataIn.add(t); 
      //Check for key lines 

      char x = (char) t; 
      buff = buff + x; 

      //For the first blank line (signaling the end of the header) 
      if(x == '\n') 
      { 
       stringData.add(buff); 

       if(buff.equals("\r\n") && !blankDetected) 
       { 
        blankDetected = true; 
        blankIndex = count; 
        byteBlankIndex = byteCount + 2; 
       } 

       //For the last modified line 
       if(buff.contains("Last-Modified:") && !lastModDetected) 
       { 
        lastModDetected = true; 
        lastModIndex = count; 
       } 

       buff = ""; 
       count++; 
      } 
      //Increment count 
      byteCount++; 
     } 

    } 

通過響應解析並將文件寫入磁盤的代碼。

 String catalogKey = hostString+ "/" + pathName; 

     //Get the directory sequence to make 
     String directoryPath = catalogKey.substring(0, catalogKey.lastIndexOf("/") + 1); 

     //Make the directory sequence if possible, ignore the boolean value that results 
     boolean ignoreThisBooleanVal = new File(directoryPath).mkdirs(); 

     //Setup output file, and then write the contents of dataIn (excluding header) to the file 
     PrintWriter output = new PrintWriter(new FileWriter(new File(catalogKey)),true); 

     for(int i = byteBlankIndex + 1 ; i < dataIn.size(); i++) 
     { 
      output.print(new String(new byte[]{ (byte)dataIn.get(i)}, StandardCharsets.UTF_8)); 
     } 


     output.close(); 
+0

因爲您正在將字節轉換爲字符,並且不適用於二進制數據流。 – breezee

+0

如果我把它作爲一個字節,我甚至可以在HTML文件上得到一系列數字 – shadowforce100

回答

1
byte t; 
while ((t = (byte) inputStream.read()) != -1) 

的問題是在這裏。它應該閱讀:

int t; 
while ((t = inputStream.read()) != -1) 
{ 
    byte b = (byte)t; 
    // use b from now on in the loop. 

的問題是,在輸入的0xff字節將被返回給int0xff,但對byte爲-1,所以你無法從流的末尾區別。

而且你應該使用FileOutputStream,不是FileWriter,你不應該潛在的二進制數據積累到StringStringBuffer或任何與char。只要你有頭到尾,你應該打開FileOutputStream,並開始複製字節。使用緩衝流來提高效率。

因爲HttpURLConnection已經存在,所以沒有太大的意義。

+0

也修復了空白字節索引計數器之後,IT WORKS PERFECT。 – shadowforce100