2017-04-02 1 views
0

Ich benutze die Java-Implementierung von SSH, JSCH, um eine scp von Remote zu lokalen zu tun. Nach dem JSCH-Beispielcode zu scpfrom kann ich Dateien empfangen. Ich habe dieselbe Implementierung wie im obigen Link verwendet.SCP eine binäre Datei mit JSCH

Problem: Komprimierte Dateien/Fotos sind beschädigt. Textdateien erscheinen gleich. Wenn ich jedoch eine Binärdatei (z. B. .tgz) sende, beschwert sich der Dekomprimierer, dass die Datei beschädigt ist. Ich vermute, das ist ein binäres vs ascii Problem. Liegt das daran, dass ich die Daten in Java schreibe? Wie erhalte und schreibe ich Binärdateien mit JSCH richtig?

Der Code, den ich geschrieben habe -

private void executeCommand(String username, String pwd, String hostname, int port) 
     throws JSchException, IOException { 
    JSch jSch = new JSch(); 
    Session session = jSch.getSession(username, hostname, port); 
    session.setPassword(pwd); 

    Properties properties = new Properties(); 
    properties.put("StrictHostKeyChecking", "no"); 
    session.setConfig(properties); 

    session.connect(); 

    ChannelExec channelExec = (ChannelExec) session.openChannel("exec"); 
    channelExec.setCommand("scp -f /home/rish/haha.txt"); 

    OutputStream outputStream = channelExec.getOutputStream(); 
    DataInputStream inputStream = new DataInputStream(channelExec.getInputStream()); 
    DataOutputStream fos; 

    channelExec.connect(); 

    byte[] buf = new byte[1024]; 

    buf[0] = 0; 
    outputStream.write(buf, 0, 1); 
    outputStream.flush(); 

    while (true) { 
     int c = checkAck(inputStream); 
     if (c != 'C') { 
      break; 
     } 

     // read '0644 ' 
     inputStream.read(buf, 0, 5); 

     long filesize = 0L; 
     while (true) { 
      if (inputStream.read(buf, 0, 1) < 0) { 
       // error 
       break; 
      } 
      if (buf[0] == ' ') break; 
      filesize = filesize * 10L + (long) (buf[0] - '0'); 
     } 

     String file = null; 
     for (int i = 0; ; i++) { 
      inputStream.read(buf, i, 1); 
      if (buf[i] == (byte) 0x0a) { 
       file = new String(buf, 0, i); 
       break; 
      } 
     } 

     // send '\0' 
     buf[0] = 0; 
     outputStream.write(buf, 0, 1); 
     outputStream.flush(); 

     // String fileName = "/data/data/" + getPackageName() + "/crearofile" + new Random().nextInt(100) + ".txt"; 
     String fileName = "/data/data/rish.crearo.trial/haha.txt"; 

     File file1 = new File(fileName); 
     if (file1.exists()) file1.delete(); 
     if (file1.createNewFile()) Log.d(TAG, "File created"); 
     else Log.d(TAG, "File not created"); 

     // read a content of lfile 
     fos = new DataOutputStream(new FileOutputStream(fileName)); 

     String count; 
     while ((count = inputStream.readUTF()) != null) { 
      System.out.println(count); 
      fos.writeBytes(count); 
     } 
     fos.close(); 

     if (checkAck(inputStream) != 0) { 
      System.exit(0); 
     } 

     inputStream.close(); 
     // send '\0' 
     buf[0] = 0; 
     outputStream.write(buf, 0, 1); 
     outputStream.flush(); 
    } 

    session.disconnect(); 
} 
+0

die oben hinzuzufügen, ich habe meine Inputstreams und outputstreams um einen Datainputstream/Dataoutputstream versucht wickeln. Hat nicht geholfen! –

+0

Bitte geben Sie genaues Minimum Stück Code + Datenquellen/Dateien, die Ihr Problem reproduziert –

+0

Haben Sie http://stackoverflow.com/questions/40066370/jsch-scp-file-transfer-using-exec-channel? –

Antwort

0

Der Code, den Sie geschrieben haben, ist nicht das gleiche wie in ScpFrom.java example.

Sie können natürlich nicht inputStream.readUTF() auf Binärdateien verwenden. UTF ist eine Textkodierung. Jeder Versuch, Binärdateien mit einer beliebigen Codierung zu interpretieren, wird diese verfälschen (oder in diesem Fall bricht der UTF-Decoder binäre Daten ab und beendet die Dateiübertragung vorzeitig).

Eigentlich kann dieser Code nicht einmal für Textdateien funktionieren, da Sie die Größe der heruntergeladenen Daten nicht überprüfen (Sie verwenden nie den Wert filesize). Sie können also über das Dateiende hinauslesen. Es kann jedoch zufällig funktionieren, da der UTF-Decoder nach dem Dateiinhalt auf NULL-Terminator brechen kann.

(Ich verstehe, dass dies wahrscheinlich tatsächlich war Sie versuchen, etwas anderes Problem zu umgehen)