【问题标题】:Is there a memory efficient way to convert input stream encoding是否有一种内存有效的方法来转换输入流编码
【发布时间】:2020-01-14 05:33:50
【问题描述】:

我正在使用 http 客户端从 Google Cloud Storage 读取一个可能很大的 CSV 文件。获得 CSV 文件后,我需要将其上传到另一个存储桶,并将数据加载到 BigQuery 表中。不幸的是,我正在下载的文件以 UTF-16 编码,BigQuery 仅支持 UTF-8。我需要一种将数据从 UTF-16 转换为 UTF-8 的方法。我知道我可以简单地将 http 响应输入流中的数据读取为 UTF-16,然后将其以 UTF-8 格式写入新的输入流,如下所示:

byte[] data = IOUtils.toByteArray(response.getEntity().getContent());
String csv = new String(data, StandardCharsets.UTF_8);
ByteArrayInputStream inputStream = new ByteArrayInputStream(csv.getBytes(StandardCharsets.UTF_8));

但是,鉴于 CSV 文件没有最大大小并且有可能非常大,我想尽可能避免将其读入内存。我需要这个过程的最终产品是一个 InputStream 以免破坏接口的合同。

我曾考虑使用 BufferedReader 一次读取一行输入流并转换编码,但我不确定一旦将其转换为新的输入流是否更有效。

有没有办法以一种内存高效的方式将输入流中的 UTF-16 内容转换为 UTF-8 内容?

【问题讨论】:

  • 使用IOUtils.copy(InputStream, Writer, Charset)。您可以将数据从输入流重定向到输出流
  • @maklas 感谢您的建议,但正如我所说,我需要将此过程的输出作为输入流,而不是写入器/输出流。
  • @Ben_Green。好的,明白了。您需要将字节解码为 utf16 字符,然后将它们编码为 utf8。那么这可能会奏效。双重包装输入流。 java InputStreamReader utf16Reader = new InputStreamReader(is, StandardCharsets.UTF_16); ReaderInputStream utf8IS = new ReaderInputStream(utf16Reader, StandardCharsets.UTF_8);
  • @maklas 看起来不错。我假设 InputStreamReader 不会将输入流读入内存?如果您提出答案,我会投票赞成:)
  • @Ben_Green。当然可以。否则它将如何解码和编码。但它不会读取整个流并将其放入字符串中。它可能只是读取 8 kb 的小块,在一个 while 循环中处理每个块。因此它不会将所有数据加载到您的内存中。你的内存和垃圾收集器会很高兴。

标签: java character-encoding inputstream


【解决方案1】:

因为您已经使用了commons.io 库。这可能正是您想要的:

InputStreamReader utf16Reader = new InputStreamReader(is, StandardCharsets.UTF_16);
ReaderInputStream utf8IS = new ReaderInputStream(utf16Reader, StandardCharsets.UTF_8);

哪个双重包装 isutf16-decoding 阅读器,然后到 utf8 编码字节流

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 2020-04-26
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多