2012-07-26 75 views
0

在我的程序中,我在文檔中使用了an example改編的JSch軟件包,它描述瞭如何將文件從遠程服務器複製到本地計算機。雖然該程序似乎可以正常工作,但在複製過程中文件似乎已損壞,並且當我嘗試從bash播放它們時,出現一個錯誤消息:「播放失敗格式:無法打開輸入文件79_97_729.wav」 :WAVE:找不到RIFF標題「。如何在java中將wav文件從一個目錄複製到另一個目錄?

我的複製方法如下:

public void copyFile(File file, String newName) throws JSchException, IOException{ 

    String prefix = null; 
    if (new File(destination).isDirectory()){ 
     prefix = destination + File.separator; 
    } 

    JSch jsch = new JSch(); 
    Session session = jsch.getSession("username", "network"); 
    session.setUserInfo(new MyUserInfo()); 
    session.connect(); 

    String command = "scp -f " + file.getAbsolutePath(); 
    Channel channel = session.openChannel("exec"); 
    ((ChannelExec)channel).setCommand(command); 

    OutputStream out = channel.getOutputStream(); 
    InputStream in = channel.getInputStream(); 

    channel.connect(); 

    byte[] buf = new byte[1024]; 

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

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

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

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

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

     // read a content of lfile 
     fos=new FileOutputStream(prefix == null ? destination : prefix + newName); 
     int foo; 
     while(true){ 
      if(buf.length<filesize) foo=buf.length; 
      else foo=(int)filesize; 
      foo=in.read(buf, 0, foo); 
      if(foo<0){ 
       // error 
       break; 
      } 
      fos.write(buf, 0, foo); 
      filesize-=foo; 
      if(filesize==0L) break; 
     } 
     fos.close(); 
     fos=null; 

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

    session.disconnect(); 
} 

是否有某種適應我可以做控制的事實,我複製文件以WAV格式?任何幫助,將不勝感激!

+0

你只是在同一臺機器上從一個目錄複製到另一個目錄?或者這是通過網絡傳輸的? – Lucas 2012-07-26 20:00:48

+0

@盧卡斯,在我看來,這是通過網絡傳輸。看起來你正在通過做所有這些瘋狂的東西來破壞文件。爲什麼不使用[this](http://www.java2s.com/Code/Java/File-Input-Output/copyCompletelyInputStreaminputOutputStreamoutput.htm) – 2012-07-26 20:05:08

+0

與原始文件相比,結果文件的大小是多少? – jtahlborn 2012-07-26 20:10:43

回答

0

這是我用:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.regex.Pattern; 


import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 


import com.jcraft.jsch.Channel; 
import com.jcraft.jsch.ChannelExec; 
import com.jcraft.jsch.JSchException; 
import com.jcraft.jsch.Session; 

public class Scp { 
    private static final Logger log = LoggerFactory.getLogger(Scp.class); 
    private static final Pattern validMode = Pattern.compile("^[0-8]{3,4}$"); 
    private Session session; 
    private String message; 
    private String mode = "0664"; 
    private int bufferSize = 1024; 

    public Scp(Session session) { 
     log.trace("creating scp object"); 
     this.session = session; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public String getMode() { 
     return mode; 
    } 

    public int send(String localPath, String remotePath) 
      throws JSchException, IOException { 
     log.trace("copying '{}' to '{}'", localPath, remotePath); 
     int ack = 0; 

     Channel channel = null; 
     try { 
      channel = session.openChannel("exec"); 
      ((ChannelExec) channel).setCommand(new StringBuilder("scp -p -t ") 
        .append(remotePath).toString()); 
      OutputStream channelOut = channel.getOutputStream(); 
      InputStream channelIn = channel.getInputStream(); 

      channel.connect(); 

      if ((ack = checkAck(channelIn)) != 0) return ack; 

      File localFile = new File(localPath); 
      channelOut.write(new StringBuilder("C") 
        .append(mode) 
        .append(" ") 
        .append(localFile.length()) 
        .append(" ") 
        .append(localFile.getName()) 
        .append("\n") 
        .toString().getBytes()); 
      channelOut.flush(); 

      if ((ack = checkAck(channelIn)) != 0) return ack; 

      FileInputStream fileIn = new FileInputStream(localFile); 
      try { 
       byte[] buffer = new byte[bufferSize]; 
       int bytesRead; 
       while ((bytesRead = fileIn.read(buffer, 0, bufferSize)) >= 0) { 
        channelOut.write(buffer, 0, bytesRead); 
       } 

       // finish the stream by writing a null terminator 
       buffer[0] = 0; 
       channelOut.write(buffer, 0, 1); 
       channelOut.flush(); 
      } 
      finally { 
       if (fileIn != null) { 
        try { 
         fileIn.close(); 
        } 
        catch (Exception e) { 
         log.warn("failed to close filehandle: {}", e); 
        } 
       } 
       fileIn = null; 
      } 

      if ((ack = checkAck(channelIn)) != 0) return ack; 
     } 
     finally { 
      if (channel != null && channel.isConnected()) { 
       channel.disconnect(); 
      } 
     } 

     message = "success"; 
     return ack; 
    } 

    private int checkAck(InputStream in) throws IOException { 
     int b = in.read(); 

     if (b == 1 || b == 2) { 
      StringBuilder builder = new StringBuilder(); 
      int c; 
      while ((c = in.read()) != '\n') { 
       builder.append((char) c); 
      } 
      message = builder.toString(); 
     } 

     return b; 
    } 

    public void setBufferSize(int bufferSize) { 
     this.bufferSize = bufferSize; 
    } 

    /** 
    * Sets the mode of the destination file. By default, it is 0664. 
    * 
    * @param mode 
    *   The mode to set the destination file to. 
    */ 
    public void setMode(String mode) { 
     if (!validMode.matcher(mode).matches()) { 
      throw new IllegalArgumentException("invalid mode, must be 3 or 4 octal numbers (/^[0-8]{3,4}$/)"); 
     } 
     this.mode = (mode.length() == 3) ? ("0" + mode) : mode; 
    } 
} 

它工作可靠傳送所有類型的媒體。

---------- ----------編輯

下面是一個單元測試,證明這個工程的wav文件:

import static org.junit.Assert.assertTrue; 


import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.security.NoSuchAlgorithmException; 
import java.util.Arrays; 


import javax.crypto.NoSuchPaddingException; 


import org.junit.Test; 
import org.mitre.asias.sch.Scp; 


import com.jcraft.jsch.JSch; 
import com.jcraft.jsch.JSchException; 
import com.jcraft.jsch.Session; 


public class ScpTest { 
    @Test 
    public void testScpWav() throws JSchException, IOException, NoSuchAlgorithmException, NoSuchPaddingException { 
     String dotSshDir = "C:/Cygwin/home/me/.ssh"; 
     JSch jsch = new JSch(); 
     jsch.setKnownHosts(dotSshDir + "/known_hosts"); 
     jsch.addIdentity(dotSshDir + "/id_dsa"); 

     Session session = jsch.getSession("me", "localhost"); 
     session.connect(); 

     Scp scp = new Scp(session); 
     scp.send("data/SpeechOn.wav", "/tmp/"); 

     assertTrue(Arrays.equals(readFileFully("data/SpeechOn.wav"), readFileFully("C:/Cygwin/tmp/SpeechOn.wav"))); 
    } 

    public byte[] readFileFully(String fileName) throws IOException { 
     InputStream is = null; 
     try { 
      is = new FileInputStream(new File(fileName)); 
      ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

      int nRead; 
      byte[] data = new byte[16384]; 

      while ((nRead = is.read(data, 0, data.length)) != -1) { 
       buffer.write(data, 0, nRead); 
      } 

      buffer.flush(); 

      return buffer.toByteArray(); 
     } 
     finally { 
      if (is != null) { 
       is.close(); 
      } 
     } 

    } 
} 

你應該能夠使用這個單元測試來修改源/目標文件的位置dotSshDir,它應該工作。它爲我做。

+0

我只是試圖將其插入我的代碼中,但當我嘗試播放生成的wav文件時,我收到了有關RIFF標頭的相同錯誤。 – user1491920 2012-07-27 14:57:19

+0

@ user1491920,它可能是一個dos2unix,或unix2dos的東西? – Lucas 2012-07-27 16:27:45

+0

@ user1491920我添加了一個單元測試,我用它來保證我的代碼可以傳輸wav文件。 – Lucas 2012-07-27 18:11:42

相關問題