Java Spring 返回以 UTF-8 和 BOM 编码的 CSV 文件

2023-12-30

显然,为了让 Excel 能够很好地打开 CSV 文件,它应该在开头有字节顺序标记。 CSV的下载是通过写入来实现的HttpServletResponse控制器中的输出流,因为数据是在请求期间生成的。当我尝试写入 BOM 字节时出现异常 -java.io.CharConversionException: Not an ISO 8859-1 character: [](即使我指定的编码是UTF-8).


有问题的控制器的方法

@RequestMapping("/monthly/list")
public List<MonthlyDetailsItem> queryDetailsItems(
        MonthlyDetailsItemQuery query,
        @RequestParam(value = "format", required = false) String format,
        @RequestParam(value = "attachment", required = false, defaultValue="false") Boolean attachment,
        HttpServletResponse response) throws Exception 
{   
    // load item list
    List<MonthlyDetailsItem> list = detailsSvc.queryMonthlyDetailsForList(query);
    // adjust format
    format = format != null ? format.toLowerCase() : "json";
    if (!Arrays.asList("json", "csv").contains(format)) format = "json";

    // modify common response headers
    response.setCharacterEncoding("UTF-8");
    if (attachment)
        response.setHeader("Content-Disposition", "attachment;filename=duomenys." + format);

    // build csv
    if ("csv".equals(format)) {
        response.setContentType("text/csv; charset=UTF-8");
        response.getOutputStream().print("\ufeff");
        response.getOutputStream().write(buildMonthlyDetailsItemCsv(list).getBytes("UTF-8"));
        return null;
    }

    return list;
}

我刚刚遇到,同样的问题。对我有用的解决方案是从响应对象获取输出流并写入它,如下所示

    // first create an array for the Byte Order Mark
    final byte[] bom = new byte[] { (byte) 239, (byte) 187, (byte) 191 }; 
    try (OutputStream os = response.getOutputStream()) {
        os.write(bom);

        final PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
        w.print(data);
        w.flush();
        w.close();
    } catch (IOException e) {
        // logit
    }

所以在OutputStreamWriter上指定UTF-8。


作为对此的补充,我应该补充一点,相同的应用程序需要允许用户上传文件,这些文件可能有也可能没有 BOM。这可以通过使用类来处理org.apache.commons.io.input.BOMInputStream,然后用它来构造一个org.apache.commons.csv.CSVParser。 BOMInputStream 包含一个方法hasBOM()检测文件是否有 BOM。 我首先遇到的一个问题是hasBOM()方法从底层流中读取(显然!),因此处理此问题的方法是首先标记流,然后在测试后如果没有 BOM,则重置流。我为此使用的代码如下所示:

try (InputStream is = uploadFile.getInputStream();
        BufferedInputStream buffIs = new BufferedInputStream(is);
        BOMInputStream bomIn = new BOMInputStream(buffIs);) {
      buffIs.mark(LOOKAHEAD_LENGTH);
      // this should allow us to deal with csv's with or without BOMs
      final boolean hasBOM = bomIn.hasBOM();
      final BufferedReader buffReadr = new BufferedReader(
          new InputStreamReader(hasBOM ? bomIn : buffIs, StandardCharsets.UTF_8));

      // if this stream does not have a BOM, then we must reset the stream as the test
      // for a BOM will have consumed some bytes
      if (!hasBOM) {
        buffIs.reset();
      }

      // collect the validated entity details
      final CSVParser parser = CSVParser.parse(buffReadr,
          CSVFormat.DEFAULT.withFirstRecordAsHeader());
      // Do stuff with the parser
      ...
  // Catch and clean up

希望这对某人有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java Spring 返回以 UTF-8 和 BOM 编码的 CSV 文件 的相关文章

随机推荐

  • 将值存储在 MIPS 的 HI 和 LO 寄存器中

    我正在 MIPS 中编写某些代码 并且要求将结果暂时存储在HI and LO特殊寄存器 均为 4 字节宽 这些说明可供我使用 divu s t lo lt s div t hi lt s mod t multu s t hi lo lt s
  • 朱莉娅似乎很慢

    我正在运行此中所示的代码question https stackoverflow com questions 73599180 plot not showing in julia 73599239 我预计它第二次和第三次运行得更快 第一次运
  • 如何将列表列转换为 R 中 tibble 中的向量

    我试图折叠下面的小标题 称为数据 中的 周 列 以便结果是具有两列的小标题 1 表示周 另一列表示相关值 由于周列是一个列表 我不知道该怎么做 能否请你帮忙 gt head data A tibble 6 x 1 Weeks Value
  • Oracle SQL Developer 和 PostgreSQL

    我正在尝试使用 Oracle SQL Developer 3 0 04 连接到 PostgreSQL 9 1 数据库 但到目前为止我还没有取得任何成功 首先 如果我在首选项中添加第三方驱动程序 则在添加新连接时 没有 PostgreSQL
  • 测量要在 Canvas 上绘制的文本宽度(Android)

    是否有一种方法可以根据用于绘制文本的 Paint 使用 drawText 方法返回要在 Android 画布上绘制的文本的宽度 以像素为单位 你看过吗android graphics Paint measureText String txt
  • 如何在 Greasemonkey 脚本中播放声音?

    如何在 Greasemonkey 脚本中播放声音 我目前想做的是在达到条件时播放声音 例如 UserScript name Sound Alert namespace example com include example com requ
  • 检查 Postgresql 是否正在监听

    给定 IP 地址和端口号 是否可以检查具有该 IP 地址的计算机是否在指定端口上侦听 Postgresql 如果是这样 怎么办 我只想获取Postgresql是否正在监听指定机器的指定端口的布尔值 例如 您可以使用nmap http nma
  • 这个八位字节流如何被解释为希伯来语 UTF-8 编码?

    下面的字节流被标识为UTF 8 它包含希伯来语句子 我正在尝试理解编码 ubuntu ip 10 126 21 104 od t x1 homeless title fromwireshark followed by hexdump txt
  • 如何正确制作阴影贴图的深度立方体贴图?

    我已经编写了代码将场景对象渲染为以下格式的立方体贴图纹理GL DEPTH COMPONENT然后在着色器中使用此纹理来确定片段是否被直接照亮 以用于阴影目的 然而 我的立方体贴图看起来是黑色的 我想我没有充分设置我的 FBO 或渲染上下文
  • CSRF 保护:我们是否必须为每个表单生成一个令牌?

    我们是否必须为网站中的每个表单生成一个令牌 我的意思是 每次为每个请求的表单生成不同的令牌 如果没有 为什么 一般来说 只要有每个会话一个令牌 https www owasp org index php Cross Site Request
  • 将“默认”数组与“输入”数组合并? PHP 哪个函数?

    假设您让用户提供信息 Array 1 但并非全部都是必需的 所以你有默认值 Array 2 PHP 是否有一个函数可以覆盖所有数组值Array 2基于它们是否提供Array 1 而不是空的 我想你正在寻找的是array replace re
  • WinRm - 由于 SSL 证书不正确,无法在 HTTPS 上创建 WinRM 侦听器

    我想将 WinRM 与 https 传输结合使用 我购买了 Comodo 证书 错误表明我无法使用自签名证书 其主题与我的 Windows 10 计算机 未加入域 的 FQDN 系统中的完整计算机名称 相匹配 CN my domain ne
  • 我们可以在不更改APP版本的情况下更新Google Play商店上的APK吗

    谁能告诉我 我可以替换上传到 Google Play 商店的 APK 而不更改应用程序版本吗 基本上我昨天已经上传了 1 0 版本的应用程序 今天我想重新上传 APK 并进行一些重要的修复 并且不想更改版本 You cannot更新现有应用
  • Linux:如何检查进程可用的最大连续地址范围

    我想在命令行输入pid 取回未被保留的最大连续地址空间 有任何想法吗 我们的 32 位应用程序在 64 位 RHEL 5 4 上运行 运行一段时间后 比如 24 小时 就会崩溃 当时仅使用了 2 5 GB 的内存 但我们遇到了内存不足的错误
  • 使用 Linux PulseAudio 时无法关闭 Java 音频 Clip

    我正在尝试在 Java 应用程序中播放声音 但该应用程序实际上从未终止 因为即使在尝试执行以下操作后 PulseAudio Eventloop 线程仍保持运行状态close https docs oracle com javase 8 do
  • 由“ggpair”和“ggplot”并排生成的图

    给定两个 ggplots 我们可以将它们并排排列 library ggplot2 library gridExtra Data data iris df lt data frame y rnorm 100 Plotting p1 lt qp
  • 在继承中:我可以覆盖基类数据成员吗?

    假设我有两个类 如下所示 Class A public private int length Class B public Class A public private float length 我想知道的是 Is 重写基类数据成员允许吗
  • ggplot 中 ylab 中的上标“^oC” -

    尝试绘制 oC 但不断收到错误 错误 ggplot 中出现意外的 但是 如果我放置 R o C 就可以了 请参阅下面的代码片段 第一个代码不起作用 第二个代码起作用 但对 ylab 中的 R 没有用 ggplot MD15 aes Date
  • Three.js - 如何等待图像加载?

    我加载图像来显示精灵 但代码似乎在图像完全加载之前继续进行 dart web gl 渲染警告 绑定到纹理单元 0 的纹理不可渲染 https stackoverflow com questions 21954036 dartweb gl r
  • Java Spring 返回以 UTF-8 和 BOM 编码的 CSV 文件

    显然 为了让 Excel 能够很好地打开 CSV 文件 它应该在开头有字节顺序标记 CSV的下载是通过写入来实现的HttpServletResponse控制器中的输出流 因为数据是在请求期间生成的 当我尝试写入 BOM 字节时出现异常 ja