2017-04-05 176 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分钟来列出文件 –