Java JSch 在复制时更改文件编码

Java JSch change file encoding while copying

我将一些文件从 SFTP 服务器传输到另一台机器。 SFTP 上的文件是 UTF-8 字符集,我需要它们 'cp1251',是否可以在复制过程中更改文件编码?

我这样做如下:

ChannelSftp sftp_channel = (ChannelSftp) channel;
// some code
sftp_channel.get(src, dst);

不,你不能那样做。您只能传输字节。

您需要做的是将文件下载到临时文件中,然后进行转换:

final Path transferFile = Files.createTempFile("transfer", "xxx");

// transfer file to transferFile

// Sure it's not 1252?
final Charset srcCharset = Charset.forName("windows-1251");

final Path dstFile = Paths.get("destinationFile");
final Charset dstCharset = StandardCharsets.UTF_8;

final char[] buf = new char[16384]; // or another size
int charsRead;

try (
    final BufferedReader reader = Files.newBufferedReader(transferFile, srcCharset);
    final BufferedWriter writer = Files.newBufferedWriter(dstFile, dstCharset);
) {
    while ((charsRead = reader.read(buf)) != -1)
        writer.write(buf, 0, charsRead);
    writer.flush();
}

Files.delete(transferFile);

现在,如果您可以从要传输的文件中获取 InputStream,代码将如下所示(注意:关闭此处未处理的原始 InputStream;但请注意Closeable.close() 是幂等的,所以即使 reader 关闭了流,你还是想关闭它):

// "in" is the InputStream from the remote file
final Charset srcCharset = Charset.forName("windows-1251");

final Path dstFile = Paths.get("destinationFile");
final Charset dstCharset = StandardCharsets.UTF_8;

try (
    final FileSystem sshfs = xxx;
    final Reader reader = new InputStreamReader(in, srcCharset);
    final BufferedWriter writer  = Files.newBufferedWriter(dstFile, dstCharset);
) {
    while ((charsRead = reader.read(buf)) != -1)
        writer.write(buf, 0, charsRead);
    writer.flush();
}

理想情况下:存在一个基于 SFTP 的 JSR 203 实现,但我还没有找到它;如果你找到它,你甚至可以使用 Files.copy():

final Charset srcCharset = Charset.forName("windows-1251");

final Path dstFile = Paths.get("destinationFile");
final Charset dstCharset = StandardCharsets.UTF_8;

try (
    final FileSystem sshfs = xxx;
    final BufferedReader reader 
        = Files.newBufferedReader(sshfs.getPath("sourcepath"), srcCharset);
    final BufferedWriter writer  = Files.newBufferedWriter(dstFile, dstCharset);
) {
    while ((charsRead = reader.read(buf)) != -1)
        writer.write(buf, 0, charsRead);
    writer.flush();
}

JSch 无法为您转换下载的文件编码。正如@fge 的回答所示,您必须自己完成。

为避免保存下载文件的临时副本(以原始编码),使用 get 方法的签名 returns 一个流:

public InputStream get(String src)

然后直接从该流中读取,并在实际将下载的数据保存到目标文件之前即时转换它们。

对于即时转换,当从流中读取时,请参见示例:

  • Java file encoding conversion from ANSI to UTF8
  • java: how to convert a file to utf8