Fre*_*erg 2 c# encoding asp.net-core
我有关于丹麦语字符的问题,并在 Excel 中打开保存为 CSV 的文件。请参阅下面的代码:
\n\n [HttpGet]\n [Route("/progress/data.csv")]\n [Produces("text/csv")]\n public IActionResult GetCSV()\n {\n StringBuilder sb = new StringBuilder();\n sb.AppendLine("\xc3\xa6\xc3\xb8;2;3;");\n Encoding encode = Encoding.UTF8;\n return File(encode.GetBytes(sb.ToString()), "text/csv", "data.csv");\n }\nRun Code Online (Sandbox Code Playgroud)\n\n我使用的是 .NET Core 2.1,此导出的结果是前两个字符 \xc3\xa6\xc3\xb8 显示为 \xc3\x83\xc2\xa6\xc3\x83 。
\n\n我知道这是一个已知问题,但到目前为止我还没有找到解决方案。在过去的 4 个小时里,我尝试了至少 15 种不同的方法,包括带/不带 BOM 的 UTF。使用 System.Text.Encoding.UTF8.GetPreamble() 手动添加 BOM,各种 MemoryStream、StreamWriter 解决方案,尝试使用 windows-1252 和 CodePagesEncodingProvider.Instance.GetEncoding(1252) 但没有任何效果。当在 Excel 中打开此文件时,结果总是与预期不同。
\n\n有人对此有解决方案吗?
\n嗯,问题出在Excel处理BOM的方式上。您可能会发现使用StreamWriter:
\n\n\n除非另有指定,否则 StreamWriter 默认使用 UTF8Encoding 的实例。UTF8Encoding 的此实例是在没有字节顺序标记 (BOM) 的情况下构造的,因此其 GetPreamble 方法返回一个空字节数组。此构造函数的默认 UTF-8 编码会在无效字节上引发异常。此行为与 Encoding.UTF8 属性中的编码对象提供的行为不同。要指定 BOM 并确定是否对无效字节引发异常,请使用接受编码对象作为参数的构造函数,例如 StreamWriter(String, Boolean, Encoding) 或 StreamWriter。
\n
所以我只是创建一个自定义实现IActionResult:
public class Utf8ForExcelCsvResult : IActionResult\n{\n public string Content{get;set;}\n public string ContentType{get;set;}\n public string FileName {get;set;}\n public Task ExecuteResultAsync(ActionContext context)\n {\n var Response =context.HttpContext.Response;\n Response.Headers["Content-Type"] = this.ContentType;\n Response.Headers["Content-Disposition"]=$"attachment; filename={this.FileName}; filename*=UTF-8\'\'{this.FileName}";\n using(var sw = new StreamWriter(Response.Body,System.Text.Encoding.UTF8)){\n sw.Write(Content);\n }\n return Task.CompletedTask ;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n当您需要使用 Excel 打开此类 csv 文件时,只需返回Utf8ForExcelCsvResult.
[HttpGet]\n[Route("/progress/data.csv")]\n[Produces("text/csv")]\npublic IActionResult MyFileDownload()\n// public Utf8ForExcelCsvResult MyFileDownload()\n{\n StringBuilder sb = new StringBuilder();\n sb.AppendLine("\xc3\xa6\xc3\xb8;2;3;");\n sb.AppendLine("\xe1\x83\x92\xe1\x83\x90\xe1\x83\x9b\xe1\x83\x90\xe1\x83\xa0\xe1\x83\xaf\xe1\x83\x9d\xe1\x83\x91\xe1\x83\x90");\n sb.AppendLine("\xe1\x80\x9f\xe1\x80\x9a\xe1\x80\xba\xe1\x80\x9c\xe1\x80\xad\xe1\x80\xaf");\n sb.AppendLine("\xe0\xba\xaa\xe0\xba\xb0\xe0\xba\x9a\xe0\xba\xb2\xe0\xba\x8d\xe0\xba\x94\xe0\xba\xb5");\n sb.AppendLine("cze\xc5\x9b\xc4\x87");\n sb.AppendLine("\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf");\n sb.AppendLine("\xe4\xbd\xa0\xe5\xa5\xbd");\n Console.WriteLine(sb.ToString());\n return new Utf8ForExcelCsvResult(){\n Content=sb.ToString(),\n ContentType="text/csv",\n FileName="hello.csv",\n };\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n我们可以使用 Powershell 通过以下方式检查 csv 文件的十六进制表示形式Format-hex -path .\\hello.csv:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n\n00000000 EF BB BF C3 A6 C3 B8 3B 32 3B 33 3B 0D 0A E1 83 \xc3\xaf\xc2\xbb\xc2\xbf\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8;2;3;..\xc3\xa1\n00000010 92 E1 83 90 E1 83 9B E1 83 90 E1 83 A0 E1 83 AF \xc3\xa1\xc3\xa1\xc3\xa1\xc2\xa0\xc3\xa1\xc2\xaf\n00000020 E1 83 9D E1 83 91 E1 83 90 0D 0A E1 80 9F E1 80 \xc3\xa1\xc3\xa1\xc3\xa1..\xc3\xa1\xc3\xa1\n00000030 9A E1 80 BA E1 80 9C E1 80 AD E1 80 AF 0D 0A E0 \xc3\xa1\xc2\xba\xc3\xa1\xc3\xa1\xc2\xad\xc3\xa1\xc2\xaf..\xc3\xa0\n00000040 BA AA E0 BA B0 E0 BA 9A E0 BA B2 E0 BA 8D E0 BA \xc2\xba\xc2\xaa\xc3\xa0\xc2\xba\xc2\xb0\xc3\xa0\xc2\xba\xc3\xa0\xc2\xba\xc2\xb2\xc3\xa0\xc2\xba\xc3\xa0\xc2\xba\n00000050 94 E0 BA B5 0D 0A 63 7A 65 C5 9B C4 87 0D 0A E3 \xc3\xa0\xc2\xba\xc2\xb5..cze\xc3\x85..\xc3\xa3\n00000060 81 93 E3 82 93 E3 81 AB E3 81 A1 E3 81 AF 0D 0A \xc3\xa3\xc3\xa3\xc2\xab\xc3\xa3\xc2\xa1\xc3\xa3\xc2\xaf..\n00000070 E4 BD A0 E5 A5 BD 0D 0A \xc3\xa4\xc2\xbd\xc2\xa0\xc3\xa5\xc2\xa5\xc2\xbd..\nRun Code Online (Sandbox Code Playgroud)\n\n这里前三个字节EF BB BF是字节顺序标记
| 归档时间: |
|
| 查看次数: |
3377 次 |
| 最近记录: |