java大数据处理-千万级FTP下载

本文介绍使用commons-net-ftp工具处理FTP大数据量的关键步骤,包括使用NLST命令列目录到文件、分批处理避免内存溢出、断点续传、处理磁盘空间不足等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、说明本文使用的是 commons-net-ftp-2.0.jar 的 ftp工具
 
2、FTP大数据量处理的关键所在 - 列目录到文件 ,即发送标准的FTP命令NLST,把远程ftp执行目录下的所有文件名通过流的形式下载到本地文件,然后根据文件名去下载文件.
  可以通过apache 发送ftp命令 "NLST" 的方式列目录到文件中去
 
面看一下简单的实现
 
?
# DS_LIST_CMD = NLST
public File sendNlistAndListToFile(String command,String localPathName) throws   IOException
       {
               try {
                       return client.createFile(command, localPathName);
               } catch (IOException e) {
                       log.error(e);
           throw new IOException( "the command " +command + " is incorrect" );
               }
       }
 
           
 
            十万级别以上的数据量的话 千万不要使用下面这种方式,如果真的全部创建成FTPFile对象...你的内存会爆掉..
             
?
FTPFile[] dirList = client.listFiles();
  
3、从2中生成的文件中读取要下载的文件名,当然你可以分批次从文件中读取 要下载的文件名到内存的list当中 .,或者读取一个文件名就下载一个文件, 不要把所有的数据都加载到内存 ,如果很多的话会出问题
 
            大数据库操作的过程中,如果有100W条记录,列出来的目录文件的大小 100M以上,如果数据量操作千万,生成的文件肯定会大于1G,这个时候要是全部加载到内存...肯定会溢出了..
 
 
4、关于文件的断点续传,apache的ftp包中支持的非常的好,这个也是文件下载的核心代码----关于文件的断点续传, 获得ftp文件的大小和本地文件的大小进行判断,然后使用ftp提供的断点续传功能
 
            下载文件一定要使用二进制的形式
            
?
client.enterLocalPassiveMode(); // 设置为被动模式
ftpclient.binary();  // 一定要使用二进制模式
 
           
   
 
?
/** 下载所需的文件并支持断点续传,下载后删除FTP文件,以免重复
          * @param pathName 远程文件
          * @param localPath 本地文件
          * @param registerFileName 记录本文件名称目录
          * @param size 上传文件大小
          * @return true 下载及删除成功
          * @throws IOException
          * @throws Exception
          */
         public boolean downLoad(String pathName, String localPath) throws IOException {
                 boolean flag = false ;
                 File file = new File(localPath+ ".tmp" ); //设置临时文件
                 FileOutputStream out = null ;
                 try {
                     client.enterLocalPassiveMode(); // 设置为被动模式
                     client.setFileType(FTP.BINARY_FILE_TYPE); //设置为二进制传输
                         if (lff.getIsFileExists(file)){ //判断本地文件是否存在,如果存在并且长度小于FTP文件的长度时断点续传;返之新增
                                 long size = this .getSize(pathName);
                                 long localFileSize = lff.getSize(file);
                                 if (localFileSize > size){
                                         return false ;
                                 }
                                 out = new FileOutputStream(file, true );
                                 client.setRestartOffset(localFileSize);
                                 flag = client.retrieveFile( new String(pathName.getBytes(),client.getControlEncoding()),out);  
  
                                 out.flush();
                         } else {
                                 out = new FileOutputStream(file);
                                 flag = client.retrieveFile( new String(pathName.getBytes(),client.getControlEncoding()),out);  
  
                                 out.flush();
                         }  
  
                 } catch (IOException e){
                         log.error(e);
             log.error( "file download error !" );
                         throw e;
                 } finally {
                         try {
                                 if ( null !=out)
                                 out.close();
                                 if (flag)
                                         lff.rename(file, localPath);
                         } catch (IOException e){
                                 throw e;
                         }
                 }
                 return flag;
         }
     /**
          * 获取文件长度
          * @param fileNamepath 本机文件
          * @return
          * @throws IOException
          */
         public long getSize(String fileNamepath) throws IOException{
                 FTPFile [] ftp = client.listFiles( new String(fileNamepath.getBytes(),client.getControlEncoding()));
                 return ftp.length== 0 ? 0 : ftp[ 0 ].getSize();
         }  
  
         检测本地文件是否已经下载,如果下载文件的大小.  
  
        /**
          *获取文件的大小
          * @param file
          * @return
          */
         public long getSize(File file){
                 long size = 0 ;
                 if (getIsFileExists(file)){
                         size = file.length();
                 }
                 return size;
         }
 
5、 关于磁盘空间已满的问题,这个也是下载文件的时候经常碰见的情况,大家可以使用如下的方式进行处理
 
       java虚拟机对于磁盘空间已满,在英文环境下的  linux aix 机器上 一般报
       There is not enough space in the file system
       中文环境下 一般报 "磁盘空间已满"
       大家可以使用下面的代码进行验证
       
  
?
//linux aix There is not enough space in the file system  
// window There is not enough space in the file system
  if (e.toString().contains( "enough space" )||e.toString().contains( "磁盘空间已满" ))
  {
          log.error( " There is not enough space on the disk " );
          Runtime.getRuntime().exit( 0 );
  }
                  摘自: http://www.javady.com/index.php/117.html       
 

转载于:https://www.cnblogs.com/wh-king/articles/2505723.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值