2012-02-14 15 views
1

JSchを使ってJavaでファイル/ディレクトリの同期を行うことはできますか?リモートのLinuxマシンからローカルのWindowsマシンにディレクトリを同期させる必要があります。これは可能ですか?JSchを使用したJavaでのファイル/ディレクトリ同期?

-Tivakar

+0

あなたがより詳細にこのタスクを説明できますか?プログラマチックに同期するか、アプリソリューションをお探しですか?シンクではどういう意味ですか? –

+0

同期は同期です。私はプログラム的にやりたかった。私は自分のLinuxマシンにディレクトリを持っていて、ディレクトリ内のファイルをローカルのWindowsマシンにダウンロード/同期したかったのです。このプロセスを開始する「同期」というボタンがあるので、私はプログラム的にやりたいと思っていました。 – Tivakar

+0

私にとって_sync_は、リモートホストからすべての新規および変更されたファイルをダウンロードし、ローカルディレクトリから新規および変更されたファイルをアップロードすることを意味します。しかし、それは私です。とにかく - あなたはあなたの答えを持っています:) –

答えて

2

SCPサーバからファイルをダウンロードする最も簡単な方法は、JSCHとともにCommons VFSを使用している:

import java.io.*; 
import org.apache.commons.io.FileUtils; 
import org.apache.commons.vfs2.*; 

public class CopyRemoteFile { 
    public static void copyRemoteFiles(String host, String user, String remotePath, String localPath) throws IOException { 
     FileSystemOptions fsOptions = new FileSystemOptions(); 
     SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no"); 
     SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions, 
       new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") }); 
     DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager(); 
     String uri = "sftp://" + user + "@" + host + "/" + remotePath; 

     FileObject fo = fsManager.resolveFile(uri, fsOptions); 

     FileObject[] files = fo.getChildren(); 
     for (FileObject file : files) { 
        // We will be dealing with the files here only 
      if (file.getType() == FileType.FILE) { 
       FileUtils.copyInputStreamToFile(file.getContent().getInputStream(), 
         new File(localPath + "/" + file.getName().getBaseName())); 
      } 
      file.close(); 
     } 

     fo.close(); 

     fsManager.close(); 
    } 
} 

それはちょうど私が私のWikiに入った例なので、派手な何も。しかし、fsManagerを閉じると、同じVMで再び開くことができなくなることに注意してください。

上記の例ではJSchクラスはインポートされませんが、クラスパスに入れておく必要があります。

上記の例では、リモートホストでの認証にプライベートキーを使用しています。パスワードを入力してuriを変更することで、簡単に変更できます。

あなたは同期ファイルに必要がある場合は、ローカル・ファイル・システム(またはDB、または情報の他のソース)と、リモートファイル上のファイルの日付を比較することができます

import java.io.*; 
import org.apache.commons.io.*; 
import org.apache.commons.vfs2.*; 
import org.apache.commons.vfs2.impl.*; 
import org.apache.commons.vfs2.provider.sftp.*; 

public class CopyRemoteFile { 
    public static void copyRemoteFiles(final String host, final String user, final String remotePath, final String localPath) 
      throws IOException { 
     FileSystemOptions fsOptions = new FileSystemOptions(); 
     SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no"); 
     SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions, 
       new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") }); 
     DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager(); 
     String uri = "sftp://" + user + "@" + host + "/" + remotePath; 

     FileObject fo = fsManager.resolveFile(uri, fsOptions); 

     FileObject[] files = fo.getChildren(); 
     for (FileObject file : files) { 
      // We will be dealing with the files here only 
      File newFile = new File(localPath + "/" + file.getName().getBaseName()); 
      if (file.getType() == FileType.FILE && newFile.lastModified() != file.getContent().getLastModifiedTime()) { 
       FileUtils.copyInputStreamToFile(file.getContent().getInputStream(), newFile); 
       newFile.setLastModified(file.getContent().getLastModifiedTime()); 
      } 
      file.close(); 
     } 

     fo.close(); 

     fsManager.close(); 
    } 
} 
+0

コードにLukaszありがとうございました。正確には、同期のために "リモートホストから新しいファイルと変更されたファイルをすべてダウンロードし、ローカルディレクトリから新しいファイルと変更されたファイルをアップロードします。"次のコードは、ファイルが変更されていない場合でも、すべてのファイルをリモートからローカルにコピーします。私は変更されていないファイルをダウンロードしたくありません。どのように私はこれを達成することができますか? – Tivakar

+1

お願いします。APIをお読みください。それはすべてそこにある。 'File.getContent()。getLastModifiedTime()'は必要な情報を与えます。したがって、これらの2つを比較することで、ファイルが変更されたかどうかの情報を得ることができます。そして、あなたは、ローカルファイル、DBやストアの何らかのソースをチェックすることができます。ちょうどパス、名前、最後に変更された時間が必要です。 –

+0

おかげでLukasz.Really helpful – Tivakar

-1

ルックat:http://the-project.net16.net/Projekte/projekte/Projekte/Programmieren/sftp-synchronisierung.html

プログラム全体のアップロードがあります。ここ は同期パートです:

import java.io.File; 
 
import java.io.FileNotFoundException; 
 
import java.util.ArrayList; 
 
import java.util.Vector; 
 

 
import com.jcraft.jsch.ChannelSftp.LsEntry; 
 
import com.jcraft.jsch.SftpException; 
 

 
/* 
 
* This is the heart of the whole Program. I hope, the descriptions are precise enought. 
 
*/ 
 
public class Sync{ 
 
\t public String ServerPath; 
 
\t public File LocalFolder; 
 
\t public sFTPclient client; 
 
\t public ArrayList<String> serverContentList; 
 
\t public ArrayList<String> pathList; 
 
\t \t 
 
\t public Sync(File local, String to, sFTPclient client){ 
 
\t \t this.LocalFolder = local; 
 
\t \t this.ServerPath = to; 
 
\t \t this.client = client; 
 
\t } 
 
\t 
 
\t /* 
 
\t * Executed once. Sets the Server Directory if it exists. 
 
\t * If the local folder doesn't exist on the Server, it creates it. 
 

 
\t */ 
 
\t public void setServerDirectory() throws SftpException{ 
 
\t \t try{ 
 
\t \t \t client.sftpChannel.cd(ServerPath); 
 
\t \t }catch(Exception e){ 
 
\t \t \t GUI.addToConsole(ServerPath + " don't exist on your server!"); 
 
\t \t } 
 
\t \t 
 
\t \t String serverFolder = ServerPath.substring(ServerPath.lastIndexOf('/')+1, ServerPath.length()); 
 
\t \t if(!LocalFolder.getName().equals(serverFolder)){ 
 
\t \t \t try{ 
 
\t \t \t \t client.sftpChannel.mkdir(LocalFolder.getName()); 
 
\t \t \t \t client.sftpChannel.cd(LocalFolder.getName()); 
 
\t \t \t } catch (Exception e){ 
 
\t \t \t \t client.sftpChannel.cd(LocalFolder.getName()); 
 
\t \t \t } 
 
\t \t \t this.ServerPath = ServerPath + "/" + LocalFolder.getName(); 
 
\t \t \t GUI.setNewServerFolder(ServerPath); 
 
\t \t } 
 
\t \t serverContentList = new ArrayList<String>(); 
 
\t \t pathList = new ArrayList<String>(); 
 
\t \t 
 
\t } 
 
\t 
 
\t //The contentlist contains all Filenames, that should be synchronized 
 
\t public void setToContentList(String ServerFolder) throws SftpException{ 
 
\t \t @SuppressWarnings("unchecked") 
 
\t \t Vector<LsEntry> fileList = client.sftpChannel.ls(ServerFolder); 
 
\t \t int size = fileList.size(); 
 
\t \t for(int i = 0; i < size; i++){ 
 
\t \t \t if(!fileList.get(i).getFilename().startsWith(".")){ 
 
\t \t \t \t serverContentList.add(fileList.get(i).getFilename()); 
 
\t \t \t \t pathList.add(ServerFolder); 
 
\t \t \t } 
 
\t \t } 
 
\t } 
 
\t 
 
\t /* 
 
\t * Deletes the synchronized elements from the Lists 
 
\t */ 
 
\t public void deleteFromLists(String name){ 
 
\t \t int \t position = serverContentList.lastIndexOf(name); 
 
\t \t \t \t 
 
\t \t if(position >= 0){ \t 
 
\t \t \t serverContentList.remove(position); 
 
\t \t \t pathList.remove(position); 
 
\t \t } 
 
\t } 
 
\t 
 
\t /* 
 
\t * Main function for synchronizing. Works recursive for local folders. 
 
\t */ 
 
\t @SuppressWarnings("unchecked") 
 
\t public void synchronize(File localFolder, String ServerDir) throws SftpException, FileNotFoundException{ 
 
\t \t if(client.sftpChannel.pwd() != ServerDir){ 
 
\t \t \t client.sftpChannel.cd(ServerDir); 
 
\t \t } 
 
\t \t setToContentList(ServerDir); 
 
\t \t 
 
\t \t File[] localList = localFolder.listFiles(); 
 
\t \t Vector<LsEntry> ServerList = client.sftpChannel.ls(ServerDir); 
 
\t \t ServerList.remove(0); ServerList.remove(0); 
 
\t \t 
 
\t \t /* 
 
\t \t * Upload missing Files/Folders 
 
\t \t */ 
 
\t \t int size = localList.length; 
 
\t \t for(int i = 0; i < size; i++){ 
 
\t \t \t if(localList[i].isDirectory()){ 
 
\t \t \t \t if(checkFolder(localList[i], ServerDir)){ 
 
\t \t \t \t \t synchronize(localList[i], ServerDir + "/" + localList[i].getName()); 
 
\t \t \t \t \t deleteFromLists("SubFolder"); 
 
\t \t \t \t }else { 
 
\t \t \t \t \t newFileMaster(true, localList[i], ServerDir); 
 
\t \t \t \t } 
 
\t \t \t } else { 
 
\t \t \t \t checkFile(localList[i], ServerDir); 
 
\t \t \t } 
 
\t \t \t deleteFromLists(localList[i].getName()); 
 
\t \t } 
 
\t } 
 
\t 
 
\t /* 
 
\t * Deletes all files on the server, which are not in the local Folder. Deletes also all missing folders 
 
\t */ 
 
\t public void deleteRest() throws SftpException, FileNotFoundException{ 
 
\t \t int size = serverContentList.size(); 
 
\t \t for(int i = 0; i < size; i++){ 
 
\t \t \t client.sftpChannel.cd(pathList.get(i)); 
 
\t \t \t newFileMaster(false, null, serverContentList.get(i)); 
 
\t \t } 
 
\t } 
 
\t 
 
\t /* 
 
\t * Copy or delete Files/Folders 
 
\t */ 
 
\t public void newFileMaster(boolean copyOrNot, File sourcePath, String destPath) throws FileNotFoundException, SftpException{ 
 
\t \t FileMaster copy = new FileMaster(copyOrNot, sourcePath, destPath, client.sftpChannel); 
 
\t \t copy.runMaster(); 
 
\t } 
 
\t 
 
\t /* 
 
\t *Useful to find errors - Prints out the content-List every time you call the method. 
 
\t *If you have Problems, call it before and after every changes of the serverContentList! 
 
\t */ 
 
\t /*public void printServerContent(){ 
 
\t \t System.out.println("SERVER-Content: " + "\n"); 
 
\t \t for(int i = 0; i < serverContentList.size(); i++){ 
 
\t \t \t System.out.println(serverContentList.get(i) + " in " + pathList.get(i)); 
 
\t \t } 
 
\t }*/ 
 
\t 
 
\t /* 
 
\t * Looks ond the server, if the file is there. If not, or the local file has changed, it copies the file on the server. 
 
\t */ 
 
\t public void checkFile(File file, String path) throws SftpException, FileNotFoundException{ 
 
\t \t client.sftpChannel.cd(path); 
 
\t \t 
 
\t \t if(!serverContentList.contains(file.getName())){ 
 
\t \t \t newFileMaster(true, file, ServerPath); 
 
\t \t } else { 
 
\t \t \t Long localTimeStamp = file.lastModified(); 
 
\t \t \t Long timeStamp = client.sftpChannel.stat(file.getName()).getATime()*1000L; 
 

 
\t \t \t if(localTimeStamp > timeStamp){ 
 
\t \t \t \t newFileMaster(false, null, path + "/" + file.getName()); 
 
\t \t \t \t newFileMaster(true, file, path); 
 
\t \t \t } 
 
\t \t } 
 
\t \t deleteFromLists(file.getName()); 
 
\t } 
 
\t 
 
\t /* 
 
\t * The same as the checkFile function. But it returns a boolean. (Easier to handle in the synchronized funtion) 
 
\t * Don't check, if the folder has changed (I think this can't be the case) 
 
\t */ 
 
\t public boolean checkFolder(File folder, String path) throws SftpException{ 
 
\t \t client.sftpChannel.cd(path); 
 
\t \t if(serverContentList.contains(folder.getName())){ 
 
\t \t \t return true; 
 
\t \t }else { return false; } 
 
\t } 
 
\t 
 
}

関連する問題