java中ftpClient.listFiles | 结果为空问题解决方案

java中ftpClient.listFiles | 结果为空问题解决方案

最近在JAVA项目中用到ftpClient.listFiles()函数时,总是返回null。现在就我遇到的情况讲讲解决方案。

环境:CentOS release 6.6 (Final), 语言 $LANG=en_US.UTF-8

相关jar:common-net-3.3.jar(common-net-3.4.jar和common-net-1.4.1.jar依旧有这个问题)


之前查了一些资料,别人在处理这个问题时,常常是在执行ftpClient.listFiles()前加上一句:

ftpClient.enterLocalPassiveMode();

也有人说是因为目标机器是中文语言设置的问题,在匹配文件信息时无法匹配中文日期的“月”和“日”而出错。关于这个问题,大家可以参考这位朋友的方法

http://blog.csdn.net/wangchsh2008/article/details/47101423

但是这对我依然不适用!不过却给我提供了解决问题的思路。我明白了原来这个函数会匹配 ls -l的结果。

在我的目标机器上:

$ ls -l
total 4
-rw-rw-r--. 1 tester5 tester5 7 Apr 28 16:44 test.txt

大家注意看,在“-rw-rw-r--” 后面,紧跟着一个不起眼的“.”,而这个小小的点正是函数返回Null的元凶!

这个点不是一定会出现的。在另外一台机器上,同样执行ls -l的结果:

$ ls -l

total 7984

-rwxrwxrwx. 1 root root 135 Sep 23 2015 py_test.pl

-rwxrwxrwx 1 root root 3897 Apr 8 15:35 test.pl

大家就可以看到,第二个文件test.pl的“-rwxrwxrwx”后面并没有那个“."。所以不同的文件执行ls -l的结果形式可能不同(具体原因是什么,我还没有去研究)。

在已有的jar包common-net-3.3.jar,common-net-3.4.jarcommon-net-1.4.1.jar源码中,都没有对这个“点”做正则匹配。

下面的代码是common-net-1.4.1.jar中UnixFTPEntryParser.java中的相关代码:

 /**    * this is the regular expression used by this parser.    *    * Permissions:    *    r   the file is readable    *    w   the file is writable    *    x   the file is executable    *    -   the indicated permission is not granted    *    L   mandatory locking occurs during access (the set-group-ID bit is    *        on and the group execution bit is off)    *    s   the set-user-ID or set-group-ID bit is on, and the corresponding    *        user or group execution bit is also on    *    S   undefined bit-state (the set-user-ID bit is on and the user    *        execution bit is off)    *    t   the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and    *        execution is on    *    T   the 1000 bit is turned on, and execution is off (undefined bit-    *        state)    */    private static final String REGEX =        "([bcdlfmpSs-])"        +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))+?s+"  //这里没有考虑到那个"."的问题!!!      + "(d+)s+"        + "(S+)s+"        + "(?:(S+)s+)?"        + "(d+)s+"                /*         numeric or standard format date       */        + "((?:d+[-/]d+[-/]d+)|(?:S+s+S+))s+" //这句对于中文语言设置的系统会发生匹配问题。解决方法见上文我推荐的那篇博客        /*           year (for non-recent standard format)     or time (for numeric or recent standard format   */  + "(d+(?::d+)?)s+"          + "(S*)(s*.*)"; 

那么,我们只要重写这个方法即可。把对于“."的匹配加上。
    /**     * this is the regular expression used by this parser.     *     * Permissions:     *    r   the file is readable     *    w   the file is writable     *    x   the file is executable     *    -   the indicated permission is not granted     *    L   mandatory locking occurs during access (the set-group-ID bit is     *        on and the group execution bit is off)     *    s   the set-user-ID or set-group-ID bit is on, and the corresponding     *        user or group execution bit is also on     *    S   undefined bit-state (the set-user-ID bit is on and the user     *        execution bit is off)     *    t   the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and     *        execution is on     *    T   the 1000 bit is turned on, and execution is off (undefined bit-     *        state)     */    private static final String REGEX =        "([bcdlfmpSs-])"        //+"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))+?s+"            //To match the "." of "-rw-rw-rw-."   @author Sun Ying        +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))+?.*s+"        + "(d+)s+"        + "(S+)s+"        + "(?:(S+)s+)?"        + "(d+)s+"                /*          numeric or standard format date        */        //中文匹配问题出在此处,这个匹配只匹配2中形式:        //(1)2008-08-03        //(2)(Jan  9)  或   (4月 26)        //而出错的hp机器下的显示为 8月20日(没有空格分开)        //故无法匹配而报错        //将下面字符串改为:        + "((?:S+s+S+)|(?:S+))s+"        //+ "((?:d+[-/]d+[-/]d+)|(?:S+s+S+)|(?:S+))s+"        //上面这句是原来那位博主改的,但是第三部分(?:S+)已经包含了第一部分(?:d+[-/]d+[-/]d+),        //所以我去掉了第一部分.  @author Sun Ying        //+ "((?:d+[-/]d+[-/]d+)|(?:S+s+S+))s+"        /*            year (for non-recent standard format)                  or time (for numeric or recent standard format                   */            + "(d+(?::d+)?)s+"                    + "(S*)(s*.*)";

(如果上述粘贴的代码中有<span style="white-space:pre"> </span> 这种东西,请手动去掉。我不知道为什么粘贴的代码会莫名其妙冒出这种东西。删了好几次,还是会自动出来。)


另一个文件FTPTimestampParserImplExZH.java是前面那位博主朋友改的,上面的文件需要配合这个文件使用,才能解决由中文语言导致的返回值为Null的问题。

这两个文件可以到如下地址下载: http://download.csdn.net/detail/yingprince/9506352


将上面的2个文件加入java项目后,用如下的方法调用:

ftpClient.changeWorkingDirectory(path);ftpClient.enterLocalPassiveMode();ftpClient.configure(new FTPClientConfig("cn.com.wechat.ftp.UnixFTPEntryParser")); //这里记得改成你放的位置FTPFile[] fs = ftpClient.listFiles(); // 得到目录的相应文件列表


上面2个文件用的源码虽然是common-net-1.4.1.jar的源码,但是用在common-net-3.3.jar和common-net-3.4.jar也是可行的。我已经实际验证过了。


如有什么问题,还请大家指正。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部