在我的程序中,我在JSch包的文档中使用了an example的改编版,该文档描述了如何将文件从远程服务器复制到本地计算机。虽然该程序似乎工作,但文件似乎在复制过程中被破坏,当我尝试从bash播放它时,我收到一条错误,上面写着“播放FAIL格式:无法打开输入文件`79_97_729.wav” :WAVE:找不到RIFF标题“。
我的复制方法如下:
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 :(得分: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
修改源文件/目标文件的位置时使用此单元测试,它应该可以工作。它适合我。