中文FTP环境下,使用commons-net,FTPClient.listFiles()方法返回null的问题及解决办法



分享到:
评论(0) |2014-09-21 |发布  pfan

项目中需要从FTP上下载数据,采用了开源的commons-net包。在实际应用中发现了一个问题,有些服务器上调用ftpClient.listFiles()方法可以返回包含文件名的数组,有些服务器上此方法返回NULL。但是ftpClient.listNames()方法能返回路径中的文件名,ftpClient.delete()方法也能删除文件。 
命令行连接FTP,执行ls -l 发现返回数据日期的地方比较奇怪。 
引用
-rw-rw-rw-  1 username nobody      145  6月22 16时56 xxxxx.csv 
drw-rw-rw-  1 username nobody      145  6月22 2010 bak_dir


失败原因就是这里,commons-net包的FTPListParseEngine负责处理通过socket来获取远程服务器的信息。通过ls –l的信息,解析出文件名,文件时间,文件大小,文件权限,文件创建者。。。。。 
01 public FTPFile[] getFiles() throws IOException {
02   List tmpResults = new LinkedList();
03   Iterator iter = this.entries.iterator();
04   while (iter.hasNext()) {
05     String entry = (String) iter.next();
06     // 核心方法
07     // commons-net默认根据机器信息,按照Unix,WinNT返回解析结果,
08     // 解析方法通过正则表达式,区分匹配各个字段,不支持中文日期,
09     FTPFile temp = this.parser.parseFTPEntry(entry);
10     tmpResults.add(temp);
11   }
12   return (FTPFile[]) tmpResults.toArray(new FTPFile[0]);
13 }

01 //listFiles方法先初始化FTPListParseEngine,initiateListParsing方法
02 public FTPFile[] listFiles(String pathname) throws IOException{
03   String key = null;
04   FTPListParseEngine engine = initiateListParsing(key, pathname);
05   return engine.getFiles();
06 }
07  
08 public FTPListParseEngine initiateListParsing(String parserKey, String pathname)
09   throws IOException {
10   if (__entryParser == null) {
11     // 传递parserKey的方法deprecated了,推荐使用FTPClientConfig
12     if (null != parserKey) {
13       __entryParser = __parserFactory.createFileEntryParser(parserKey);
14     }
15     // 设置了FTPClientConfig,按照设置生成ParseEngine
16     else {
17       if (null != __configuration) {
18         __entryParser = __parserFactory.createFileEntryParser(__configuration);
19       }
20       // 默认情况下,根据机器信息,自动生成ParseEngine
21       else {
22         __entryParser = __parserFactory.createFileEntryParser(getSystemName());
23       }
24     }
25   }
26   return initiateListParsing(__entryParser, pathname);
27 }



找到原因后,我们有的放矢,具体解析-rw-rw-rw-  1 username nobody      145  6月22 16时56 xxxxx.csv一行数据 
01 /**
02  * <pre>
03  * 解析IBM财务FTP服务器返回的一行信息
04  * -rw-rw-rw-    1 chnnlftp nobody          145  6月22 16时56 finance_back_info_20100617150652.csv
05  * 取得文件名,文件时间,文件类型,文件大小,文件所属用户。
06  *
07  * 本程序不具有复用性!!
08  * </pre>
09  */
10 public class MyFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
11  
12   private Class clazz = MyFTPEntryParser.class;
13   private Log log = LogFactory.getLog(clazz);
14  
15   /**
16    * 解析FTP传回的文件信息
17    */
18   public FTPFile parseFTPEntry(String entry) {
19     log.debug("开始解析,内容为: " + entry);
20  
21     FTPFile file = new FTPFile();
22     file.setRawListing(entry);
23  
24     String[] temp = entry.split("\\s+");
25     if (temp.length != 8) {
26       return null;
27     }
28     String fileType = temp[0].substring(01);
29     if ("d".equals(fileType)) {
30       file.setType(FTPFile.DIRECTORY_TYPE);
31     else {
32       file.setType(FTPFile.FILE_TYPE);
33       file.setSize(Integer.valueOf(temp[4]));
34     }
35     file.setName(temp[7]);
36     file.setUser(temp[3]);
37  
38     Calendar date = Calendar.getInstance();
39     Date fileDate;
40     // 返回【6月22 2010】形式的日期
41     if(temp[6].matches("\\d{4}")){
42       try {
43         fileDate = new SimpleDateFormat("yyyyMM月dd")
44             .parse(temp[6] + temp[5]);
45       catch (ParseException e) {
46         throw new RuntimeException("日期解析出错", e);
47       }
48     // 返回【6月22 16时56】形式的日期
49     else {
50       int yyyy = date.get(Calendar.YEAR);
51       try {
52         fileDate = new SimpleDateFormat("yyyyMM月ddHH时mm")
53             .parse(yyyy + temp[5] + temp[6]);
54       catch (ParseException e) {
55         throw new RuntimeException("日期解析出错", e);
56       }
57     }
58     date.setTime(fileDate);
59     file.setTimestamp(date);
60  
61     return file;
62   }
63  
64   // =====================================================================
65   // 本类只是特定解析一种FTP,没有考虑到使用正则表达式,匹配解析一类FTP
66   // 核心方法为parseFTPEntry,以下方法没有实现。
67   // =====================================================================
68   public MyFTPEntryParser() {
69     this("");
70   }
71  
72   public MyFTPEntryParser(String regex) {
73     super("");
74   }
75  
76   protected FTPClientConfig getDefaultConfiguration() {
77     return new FTPClientConfig(clazz.getPackage().getName()
78       + clazz.getSimpleName(), """""""""");
79   }
80 }


1 // 在调用 ftpClient.listNames()方法前,先调用
2 ftpClient.configure(new FTPClientConfig(package.MyFTPEntryParser));
3 // package.MyFTPEntryParser:我们的类的全路径



参考: 
http://www.blogjava.net/wodong/archive/2008/08/21/wodong.html

中文FTP环境下,使用commons-net,FTPClient.listFiles()方法返回null的问题及解决办法


分享到:
评论(0) |2014-09-21 |发布  pfan

项目中需要从FTP上下载数据,采用了开源的commons-net包。在实际应用中发现了一个问题,有些服务器上调用ftpClient.listFiles()方法可以返回包含文件名的数组,有些服务器上此方法返回NULL。但是ftpClient.listNames()方法能返回路径中的文件名,ftpClient.delete()方法也能删除文件。 
命令行连接FTP,执行ls -l 发现返回数据日期的地方比较奇怪。 
引用
-rw-rw-rw-  1 username nobody      145  6月22 16时56 xxxxx.csv 
drw-rw-rw-  1 username nobody      145  6月22 2010 bak_dir


失败原因就是这里,commons-net包的FTPListParseEngine负责处理通过socket来获取远程服务器的信息。通过ls –l的信息,解析出文件名,文件时间,文件大小,文件权限,文件创建者。。。。。 
01 public FTPFile[] getFiles() throws IOException {
02   List tmpResults = new LinkedList();
03   Iterator iter = this.entries.iterator();
04   while (iter.hasNext()) {
05     String entry = (String) iter.next();
06     // 核心方法
07     // commons-net默认根据机器信息,按照Unix,WinNT返回解析结果,
08     // 解析方法通过正则表达式,区分匹配各个字段,不支持中文日期,
09     FTPFile temp = this.parser.parseFTPEntry(entry);
10     tmpResults.add(temp);
11   }
12   return (FTPFile[]) tmpResults.toArray(new FTPFile[0]);
13 }

01 //listFiles方法先初始化FTPListParseEngine,initiateListParsing方法
02 public FTPFile[] listFiles(String pathname) throws IOException{
03   String key = null;
04   FTPListParseEngine engine = initiateListParsing(key, pathname);
05   return engine.getFiles();
06 }
07  
08 public FTPListParseEngine initiateListParsing(String parserKey, String pathname)
09   throws IOException {
10   if (__entryParser == null) {
11     // 传递parserKey的方法deprecated了,推荐使用FTPClientConfig
12     if (null != parserKey) {
13       __entryParser = __parserFactory.createFileEntryParser(parserKey);
14     }
15     // 设置了FTPClientConfig,按照设置生成ParseEngine
16     else {
17       if (null != __configuration) {
18         __entryParser = __parserFactory.createFileEntryParser(__configuration);
19       }
20       // 默认情况下,根据机器信息,自动生成ParseEngine
21       else {
22         __entryParser = __parserFactory.createFileEntryParser(getSystemName());
23       }
24     }
25   }
26   return initiateListParsing(__entryParser, pathname);
27 }



找到原因后,我们有的放矢,具体解析-rw-rw-rw-  1 username nobody      145  6月22 16时56 xxxxx.csv一行数据 
01 /**
02  * <pre>
03  * 解析IBM财务FTP服务器返回的一行信息
04  * -rw-rw-rw-    1 chnnlftp nobody          145  6月22 16时56 finance_back_info_20100617150652.csv
05  * 取得文件名,文件时间,文件类型,文件大小,文件所属用户。
06  *
07  * 本程序不具有复用性!!
08  * </pre>
09  */
10 public class MyFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
11  
12   private Class clazz = MyFTPEntryParser.class;
13   private Log log = LogFactory.getLog(clazz);
14  
15   /**
16    * 解析FTP传回的文件信息
17    */
18   public FTPFile parseFTPEntry(String entry) {
19     log.debug("开始解析,内容为: " + entry);
20  
21     FTPFile file = new FTPFile();
22     file.setRawListing(entry);
23  
24     String[] temp = entry.split("\\s+");
25     if (temp.length != 8) {
26       return null;
27     }
28     String fileType = temp[0].substring(01);
29     if ("d".equals(fileType)) {
30       file.setType(FTPFile.DIRECTORY_TYPE);
31     else {
32       file.setType(FTPFile.FILE_TYPE);
33       file.setSize(Integer.valueOf(temp[4]));
34     }
35     file.setName(temp[7]);
36     file.setUser(temp[3]);
37  
38     Calendar date = Calendar.getInstance();
39     Date fileDate;
40     // 返回【6月22 2010】形式的日期
41     if(temp[6].matches("\\d{4}")){
42       try {
43         fileDate = new SimpleDateFormat("yyyyMM月dd")
44             .parse(temp[6] + temp[5]);
45       catch (ParseException e) {
46         throw new RuntimeException("日期解析出错", e);
47       }
48     // 返回【6月22 16时56】形式的日期
49     else {
50       int yyyy = date.get(Calendar.YEAR);
51       try {
52         fileDate = new SimpleDateFormat("yyyyMM月ddHH时mm")
53             .parse(yyyy + temp[5] + temp[6]);
54       catch (ParseException e) {
55         throw new RuntimeException("日期解析出错", e);
56       }
57     }
58     date.setTime(fileDate);
59     file.setTimestamp(date);
60  
61     return file;
62   }
63  
64   // =====================================================================
65   // 本类只是特定解析一种FTP,没有考虑到使用正则表达式,匹配解析一类FTP
66   // 核心方法为parseFTPEntry,以下方法没有实现。
67   // =====================================================================
68   public MyFTPEntryParser() {
69     this("");
70   }
71  
72   public MyFTPEntryParser(String regex) {
73     super("");
74   }
75  
76   protected FTPClientConfig getDefaultConfiguration() {
77     return new FTPClientConfig(clazz.getPackage().getName()
78       + clazz.getSimpleName(), """""""""");
79   }
80 }


1 // 在调用 ftpClient.listNames()方法前,先调用
2 ftpClient.configure(new FTPClientConfig(package.MyFTPEntryParser));
3 // package.MyFTPEntryParser:我们的类的全路径



参考: 
http://www.blogjava.net/wodong/archive/2008/08/21/wodong.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值