jsch 乱码有什么好的解决方案么?

如题,或者说 FTP 服务端编码不确定的情况下如何保证不会乱码

吾辈在项目中使用 jsch 连接 SFTP,然而使用 ls 获取文件列表中的中文文件名都乱码了,而且参数为中文文件名的时候会直接抛出异常 no such file

代码如下

package com.zx.idc.common.ftp.sftp;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;
import java.util.Vector;
import java.util.stream.Collectors;

/**
 * @author rxliuli
 */
public class SftpTest {
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Test
    public void ls() {
        final JSch jSch = new JSch();
        ChannelSftp sftp = null;
        Session session = null;
        try {
            session = jSch.getSession("rxliuli", "localhost", 22);
            session.setPassword("123456");
            final Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            session.setConfig(properties);
            session.connect();
            log.info("JSch open ssh session successful: {}", session);

            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect();
            /*
            如果使用 GBK 抛出异常
            com.jcraft.jsch.SftpException: The encoding can not be changed for this sftp server.
             */
            sftp.setFilenameEncoding("UTF-8");

            log.info("Sftp connection successful: {}", sftp);

            /*
            结果是:
            TestSftpDir
            ����.xsd
            ��������Ŀ¼
             */
            final Vector<ChannelSftp.LsEntry> list = sftp.ls("/");
            log.info("list: \n{}", list.stream().map(ChannelSftp.LsEntry::getFilename).collect(Collectors.joining("\n")));
            /*
            抛出异常:
            com.jcraft.jsch.SftpException: No such file
             */
            try {
                sftp.ls("/测试中文目录");
            } catch (SftpException sftpException) {
                sftpException.printStackTrace();
            }
            /*
            也会抛出异常:
            com.jcraft.jsch.SftpException: No such file
             */
            try {
                sftp.ls(new String("/测试中文目录".getBytes("GBK"), "ISO-8859-1"));
            } catch (SftpException sftpException) {
                sftpException.printStackTrace();
            }
        } catch (Throwable e) {
            log.error("sftp operation failed: {}", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null && sftp.isConnected()) {
                sftp.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }
}

已经尝试的解决方案有:

  • 使用 sftp.setFilenameEncoding("UTF-8"); 设置文件名编码为 UTF-8:实测无效
  • 使用 sftp.setFilenameEncoding("GBK");:抛出异常 com.jcraft.jsch.SftpException: The encoding can not be changed for this sftp server.
  • 使用 sftp.ls(new String("/测试中文目录".getBytes("GBK"), "ISO-8859-1")) 编码文件名,抛出异常 com.jcraft.jsch.SftpException: No such file

有人遇到过这种问题么?

阅读 6.7k
1 个回答
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题