2017-04-05 91 views
3

我需要在SFTP文件夾中獲取文件名的遞歸列表。現在我用下面的代碼:使用JSch在SFTP中列出前N個文件

private void getFilesRecursive(List<LsEntry> fileList, List<FileDto> response, String dirParentName, 
     SftpManagerWithPool manager) throws SftpException { 
    for (LsEntry file : fileList) { 
     if (!file.getAttrs().isDir()) { 
      response.add(new FileDto(file.getFilename(), StorageType.FOLDER.getName(), 
        new Attributes(file.getAttrs().getATime(), file.getAttrs().getMTime(), 
          file.getAttrs().getAtimeString(), file.getAttrs().getMtimeString(), 
          file.getAttrs().getPermissionsString(), getPathWitoutRootDirectoryt(dirParentName), 
          file.getAttrs().getSize(), file.getAttrs().isDir()))); 
     } else if (file.getAttrs().isDir() && !".".equals(file.getFilename())) { 
      List<LsEntry> files = manager.listFiles(context.getBasePath().concat("/") 
        .concat(dirParentName.concat("/").concat(file.getFilename()))); 
      getFilesRecursive(files, response, dirParentName.concat("/").concat(file.getFilename()), manager); 
     } 
    } 
} 

public List<FileDto> getFiles() throws ServiceException { 
    Session session = null; 
    SftpManagerWithPool manager = null; 
    try { 
     session = getSession(); 
     manager = new SftpManagerWithPool(session); 
     manager.connect(); 
     List<FileDto> response = new ArrayList<>(); 
     List<LsEntry> files = manager 
       .listFiles(context.getBasePath().concat("/").concat(context.getPathToProcess())); 
     getFilesRecursive(files, response, context.getPathToProcess(), manager); 
     return response; 
    } catch (Exception e) { 
     throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage(), 
       e.getLocalizedMessage()); 
    } finally { 
     if (manager != null) { 
      manager.disconnect(); 
      try { 
       returnSession(session); 
      } catch (Exception e) { 
       throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage(), 
         e.getLocalizedMessage()); 
      } 
     } 
    } 
} 

以下是SftpManagerWithPool方法:

@SuppressWarnings("unchecked") 
public List<LsEntry> listFiles(String pathFrom) throws SftpException { 
    if (c == null || session == null || !session.isConnected() || !c.isConnected()) { 
     throw new SftpException(ErrorCode.LIST_FILES.ordinal(), "Connection to server is closed. Open it first."); 
    } 
    String filePath = pathFrom + "/"; 
    return c.ls(filePath); 
} 

工作一切良好,用不超過5k的文件,但是當我們有更多的文件,它需要大量的的時間,並導致超時。

我的問題是,我怎樣才能使用c.ls(filePath);方法列出文件夾中的前N個文件?我在尋找類似Linux shell命令的東西ls -U | head -4

----編輯-----

我修改我的方法listFiles如下,但我仍然沒有得到更好的性能:

public List<LsEntry> listFiles(String pathFrom, int top) throws SftpException { 
     if (c == null || session == null || !session.isConnected() || !c.isConnected()) { 
      throw new SftpException(ErrorCode.LIST_FILES.ordinal(), "Connection to server is closed. Open it first."); 
     } 
     String filePath = pathFrom + "/"; 
     List<LsEntry> response = new ArrayList<>(); 
     c.ls(filePath, new LsEntrySelector() { 

      @Override 
      public int select(LsEntry record) { 
       if (response.size() <= top) { 
        response.add(record); 
        return LsEntrySelector.CONTINUE; 
       } else { 
        return LsEntrySelector.BREAK; 
       } 
      } 
     }); 
     return response; 
    } 

太謝謝你了:)

回答

2

使用這個overload of ChannelSftp.ls method that takes LsEntrySelector interface

public void ls(String path, LsEntrySelector selector) 

執行LsEntrySelector.select來收集文件條目。一旦你有足夠的人,讓它返回BREAK

+0

但它返回無效如何獲得文件列表? –

+0

將'LsEntrySelector.select'中的名稱收集到某個容器(例如'Vector')。 –

+0

請檢查我的編輯,我做了你所說的,它看起來像在工作,但我仍然沒有通過列出文件獲得更好的性能,有沒有其他方法?需要3分鐘來列出文件 –