项目中需要从FTP上下载数据,采用了开源的commons-net包。在实际应用中发现了一个问题,有些服务器上调用ftpClient.listFiles()方法可以返回包含文件名的数组,有些服务器上此方法返回NULL。但是ftpClient.listNames()方法能返回路径中的文件名,ftpClient.delete()方法也能删除文件。
命令行连接FTP,执行ls -l 发现返回数据日期的地方比较奇怪。
失败原因就是这里,commons-net包的FTPListParseEngine负责处理通过socket来获取远程服务器的信息。通过ls –l的信息,解析出文件名,文件时间,文件大小,文件权限,文件创建者。。。。。
找到原因后,我们有的放矢,具体解析-rw-rw-rw- 1 username nobody 145 6月22 16时56 xxxxx.csv一行数据
参考:
http://www.blogjava.net/wodong/archive/2008/08/21/wodong.html
命令行连接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
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( 0 , 1 ); |
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。但是ftpClient.listNames()方法能返回路径中的文件名,ftpClient.delete()方法也能删除文件。
命令行连接FTP,执行ls -l 发现返回数据日期的地方比较奇怪。
失败原因就是这里,commons-net包的FTPListParseEngine负责处理通过socket来获取远程服务器的信息。通过ls –l的信息,解析出文件名,文件时间,文件大小,文件权限,文件创建者。。。。。
找到原因后,我们有的放矢,具体解析-rw-rw-rw- 1 username nobody 145 6月22 16时56 xxxxx.csv一行数据
参考:
http://www.blogjava.net/wodong/archive/2008/08/21/wodong.html
命令行连接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
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( 0 , 1 ); |
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