zoukankan      html  css  js  c++  java
  • java实现读取ftp服务器上的csv文件

    定义ftp操作接口

    import java.io.InputStream;
    import java.util.List;
    import org.apache.commons.net.ftp.FTPClient;
    
    /**
     * FTP服务器操作*/
    public interface iFtpServU {
        public FTPClient ftp(String ip, String user, String password);
        public List<String[]> csv(InputStream in);
    }

    接口实现类

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.SocketException;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.List;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPReply;
    import com.csvreader.CsvReader;
    
    /**
     * FTP服务器操作具体实现*/
    public class FtpServUImpl implements iFtpServU {
        /** 本地字符编码 */
        private static String LOCAL_CHARSET = "GBK";
        // FTP协议里面,规定文件名编码为iso-8859-1
        private static String SERVER_CHARSET = "ISO-8859-1";
    
        /**
         * 
         * <b>登录ftp 返回ftpClient事件<b>
         * 
         * @param ip
         *            ftp所在ip
         * @param user
         *            登录名
         * @param password
         *            密码
         */
        public FTPClient ftp(String ip, String user, String password) {
            FTPClient ftpClient = new FTPClient();
            try {
                ftpClient.connect(ip);
    
                if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                    if (ftpClient.login(user, password)) {
                        if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
                                "OPTS UTF8", "ON"))) {// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                            LOCAL_CHARSET = "UTF-8";
                        }
                        ftpClient.setControlEncoding(LOCAL_CHARSET);
                        ftpClient.enterLocalPassiveMode();// 设置被动模式
                        // ftpClient.setFileType(getTransforModule());// 设置传输的模式
    
                    }
                }
    
                // ftpClient.login(user, password);
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (!ftpClient.isConnected()) {
                ftpClient = null;
            }
    
            return ftpClient;
        }
    
        /**
         * <b>将一个IO流解析,转化数组形式的集合<b>
         * 
         * @param in
         *            文件inputStream流
         */
        public List<String[]> csv(InputStream in) {
            List<String[]> csvList = new ArrayList<String[]>();
            if (null != in) {
                CsvReader reader = new CsvReader(in, ',', Charset.forName("GBK"));
                try {
                    // 遍历每一行,若有#注释部分,则不处理,若没有,则加入csvList
                    while (reader.readRecord()) {
                        if (!reader.getValues()[0].contains("#"))// 清除注释部分
                        {
                            csvList.add(reader.getValues());
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                reader.close();
            }
            return csvList;
        }
    
    }

    业务场景中,调用ftp发生在对账操作,用户通过输入交易笔数、csv文件名,从而判断ftp服务器上是否存在该文件,如果存在该文件,则首先获取文件中的内容条数,与输入的笔数数值比较,一致的话就继续获取csv文件内容与系统数据库中进行比较、对账,从而完成对账操作。

    import java.io.InputStream;
    import java.util.List;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPFile;
    //配置文件工具类
    import com.online.charge.customer.deployconfig.util.DeployConfigUtil;
    
    /**
     * @ClassName: QueryFtpFilesUtils
     * @Description: 获取Ftp上文件列表
     *
     */
    public class QueryFtpFilesUtils {
        /**
         * 获取Ftp客户端
         * 
         * @return
         */
        public static FTPClient getFtpClient() {
            String ip = DeployConfigUtil.getInterfaceDeployConfig().getFtpUrl();
            String userName = DeployConfigUtil.getInterfaceDeployConfig()
                    .getFtpUserName();
            String userPassword = DeployConfigUtil.getInterfaceDeployConfig()
                    .getFtpPassword();
            // 通过配置文件获取ip,username,password
            FTPClient ftpClient = getiFtpServU().ftp(ip, userName, userPassword);
            return ftpClient;
        }
    
        /**
         * 获取ftp接口服务
         * 
         * @return
         */
        private static iFtpServU getiFtpServU() {
            return new FtpServUImpl();
        }
    
        /**
         * 获取明细条数
         * 
         * @param fileName
         *            csv文件名称 如:0320180908110523.csv 文件的名称为 0320180908110523
         * @return 明细条数
         */
        public static Integer getFtpFileCount(String fileName) {
            Integer count = 0;
            boolean isContain = Boolean.FALSE;
            FTPClient ftpClient = getFtpClient();
            List<String[]> fileList = null;
            if (null != ftpClient) {
                try {
                    FTPFile[] file = ftpClient.listFiles();
                    if (file == null || file.length <= 0) {
                        return -1;
                    }
                    // 遍历所有文件,匹配需要查找的文件
                    for (int i = 0; i < file.length; i++) {
                        // 匹配到则进入
                        if (file[i].getName().equals(fileName.concat(".csv"))) {
                            isContain = Boolean.TRUE;
                            // 将匹配到的文件流传入接口,转化成数组集合
                            InputStream in = ftpClient.retrieveFileStream(file[i].getName());
                            fileList = getiFtpServU().csv(in);
                            in.close();
                        }
                    }
                    if (!isContain) {
                        return -1;
                    }
                    if (CollectionUtils.isNotEmpty(fileList) && fileList.size() > 0) {
                        count = fileList.size();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return count;
        }
    
        /**
         * 获取FTP文件内容
         * 
         * @param fileName
         * @return
         */
        public static void getFtpFileContent(String fileName,
                List<String[]> fileContent) {
            FTPClient ftpClient = getFtpClient();
            if (null != ftpClient) {
                try {
                    FTPFile[] file = ftpClient.listFiles();
                    // 遍历所有文件,匹配需要查找的文件
                    for (int i = 0; i < file.length; i++) {
                        // 匹配到则进入
                        if (file[i].getName().contains(fileName)) {
                            InputStream in = ftpClient.retrieveFileStream(file[i].getName());
                            fileContent.addAll(getiFtpServU().csv(in));
                            in.close();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    }

    在测试中,遇到能够通过 listFiles方法获取到ftp服务器上的文件列表,但调用 retrieveFileStream方法获取文件内容失败(返回不是null),网上找了很多方法,尝试都失败,现总结如下:

    // 匹配到则进入
    if (file[i].getName().equals(fileName.concat(Constant.ACCOUNT_FILE_EXTENDS_NAME))) {
              isContain = Boolean.TRUE;
    // 1.设置主动模式
    //ftpClient.enterLocalPassiveMode();                                           
    // 2.文件类型问题,设置文件类型
    //ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 
    // 3.编码问题,设置编码
    //InputStream in = ftpClient.retrieveFileStream(new String(file[i].getName().getBytes("UTF-8"),"ISO-8859-1"));
    InputStream in = ftpClient.retrieveFileStream(file[i].getName());
    // 将匹配到的文件流传入接口,转化成数组集合
      fileList = getiFtpServU().csv(in);
      in.close();
    // 4.流关闭之后获取返回状态          
    //ftpClient.completePendingCommand();
    }

    怀疑是 retrieveFileStream方法调用Socket获取流中间出现的问题,但问题目前无法定位(读者如果知道原因麻烦不吝赐教!)

    为解决该问题,换了个思路:因为ftp上的文件都有数据,且输入的笔数都大于0,所以当确定ftp上确实有该文件时,首先还是调用 retrieveFileStream方法以流的方式获取该文件,转换为数组后判断,如果长度为0,就说明获取文件内容失败,此时换种方法:使用 retrieveFile方法将ftp服务器上的文件下载到本地,通过io流来获取其内容。实现方法如下:

        // 匹配到则进入
        if (file[i].getName().equals(fileName.concat(".csv"))) {
            isContain = Boolean.TRUE;
            // 将匹配到的文件流传入接口,转化成数组集合
            InputStream in = ftpClient.retrieveFileStream(file[i].getName());
            fileList = getiFtpServU().csv(in);
            in.close();
            if(fileList.size() == 0){
                //下载ftp文件到本地
                String osFileName = "G:/ftpFiles/"+file[i].getName();
                File localFile = new File(osFileName);
                OutputStream os = new FileOutputStream(localFile);
                ftpClient.retrieveFile(file[i].getName() , os);
                os.close();
                
                InputStream ins = new FileInputStream(new File(osFileName));
                fileList = getiFtpServU().csv(ins);
                ins.close();
            }
        }
  • 相关阅读:
    C++ 使用老牌库xzip & unzip对文件进行压缩解压
    第一次玩蛇,有点紧张。
    fiddler 抓取手机http/https包
    disk或者Partition镜像的制作
    VS2013+phread.h环境配置
    C++ 浅谈 strlen 与 sizeof的区别
    Qt 显示网页的控件
    Qt error: C2236: 意外的标记“class”。是否忘记了“;”?
    初识MySQL——人生若如初相逢
    【学习笔记】HTML基础:列表、表格与媒体元素
  • 原文地址:https://www.cnblogs.com/zjfjava/p/9611194.html
Copyright © 2011-2022 走看看