2017-10-06 3 views
0

Ich versuche einen manuellen HTTP-Client (mit Sockets) zusammen mit einem Cache zu erstellen und ich kann nicht herausfinden, warum die Dateien nicht richtig auf Platte gespeichert werden. Es funktioniert ziemlich gut für HTML-Dateien, aber scheint nicht für andere Dateitypen zu funktionieren, die nicht textbasiert sind wie .gif. Kann mir jemand sagen warum? Ich bin ziemlich neu im HTTP-Protokoll und Socket-Programmierung im Allgemeinen.HTTP Handbuch Client schreibt nicht richtig auf Platte JAVA

Die Schleife, um die Antwort zu ergreifen.

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++; 
     } 

    } 

Der Code zum Analysieren der Antwort und Schreiben der Datei auf die Festplatte.

 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

Weil Sie ein Byte in ein Zeichen konvertieren und das nicht für Stream von Binärdaten funktioniert. – breezee

+0

Wenn ich es als ein Byte belasse, bekomme ich eine Reihe von Zahlen sogar in einer HTML-Datei – shadowforce100

Antwort

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

Das Problem ist hier. Es soll lauten:

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

Das Problem ist, dass ein Byte von 0xff im Eingang wird die int als 0xff zurückgeführt wird, sondern auf die byte als -1, so dass Sie es von Ende Strom zu unterscheiden sind nicht in der Lage .

Und Sie sollten ein FileOutputStream, keine FileWriter verwenden, und Sie sollen nicht akkumulieren möglicherweise binäre Daten in ein String oder StringBuffer oder irgendetwas mit char zu tun. Sobald Sie das Ende des Headers erreicht haben, sollten Sie eine öffnen und einfach mit dem Kopieren von Bytes beginnen. Verwenden Sie gepufferte Streams, um all dies effizienter zu machen.

Nicht viel Punkt in einer dieser gegeben, dass HttpURLConnection bereits existiert.

+0

Nach dem Fixieren des Leer-Byte-Index-Zählers funktioniert IT PERFEKT. – shadowforce100