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();
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM