2010-12-10 118 views
37

我在C#中的asp.net mvc 2应用程序中遇到了UTF8编码问题。我试图让用户从字符串中下载一个简单的文本文件。我想获得的字节数组,下面一行:如何在C#中使用带有BOM的UTF8编码获取BIT()?

var x = Encoding.UTF8.GetBytes(csvString);

但是当我回到它下载使用:

return File(x, ..., ...);

我得到一个文件,该文件是没有BOM,所以我不要没有正确显示克罗地亚人的字符。这是因为我的字节数组在编码后不包含BOM。我手动插入这些字节,然后它显示正确,但这不是最好的方式来做到这一点。

我也尝试创建UTF8Encoding类实例并将布尔值(true)传递给其构造函数以包含BOM,但它也不起作用。

任何人都有解决方案吗?谢谢!

回答

91

尝试这样的:

public ActionResult Download() 
{ 
    var data = Encoding.UTF8.GetBytes("some data"); 
    var result = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); 
    return File(result, "application/csv", "foo.csv"); 
} 

的原因是,UTF8Encoding构造函数的布尔参数不会做你所期望的:

byte[] bytes = new UTF8Encoding(true).GetBytes("a"); 

结果数组将包含单字节值为97.没有BOM,因为UTF8不需要BOM。

+1

工程就像一个魅力,谢谢! :) – 2010-12-10 23:20:46

+2

谢谢!我疯了,我的特殊字符不能在Excel CSV中工作:) – 2013-06-11 14:23:38

+1

为了清晰起见,'Encoding.UTF8'等同于'new UTF8Encoding(true)'。该参数控制“GetPreamble()”是否会发出物料清单。 – Stijn 2014-09-16 08:45:45

2

UTF-8不需要BOM,因为它是一个1字节字的序列。 UTF-8 = UTF-8BE = UTF-8LE。

相比之下,由于UTF-16是一个2字节的字序列,因此UTF-16需要在流的开头部署BOM来标识流的其余部分是UTF-16BE还是UTF-16LE。 BOM标识字中的字节是BE还是LE。

问题不在于Encoding.UTF8类。问题出在您用来查看文件的任何程序。

+1

UTF-8是一种可变宽度编码。它只需要1个字节来编码ASCII字符,但其他代码点将使用多个字节。 – 2011-07-12 15:47:45

+2

用多个字节编码的码点具有预定义的顺序(基于'U +'大端表示)。然而,由于UTF8被表示为一个字节流(而不是字或词的流,它们本身被表示为一个字节序列),因此,排序的概念不适用。字节顺序适用于将16,32,64,128位整数表示为字节,而不是将字符表示为代码点。 – yfeldblum 2011-07-12 16:59:32

+0

对不起,我以为你指的是用“1字节字的序列”这个短语来存储代码点。感谢您的澄清。 +1为您的答案和评论。 – 2011-07-12 19:16:13

-1

请记住,.NET字符串都是unicode,但仍然保留在内存中,所以如果您可以使用调试器正确地看到您的csvString,问题就是写入文件。

在我看来,你应该返回一个FileResult与文件相同的编码。尝试将返回文件编码,

4

我创建了一个简单的扩展到任何字符串转换在任何编码的字节数组的表示时,它被写入文件或流:

public static class StreamExtensions 
{ 
    public static byte[] ToBytes(this string value, Encoding encoding) 
    { 
     using (var stream = new MemoryStream()) 
     using (var sw = new StreamWriter(stream, encoding)) 
     { 
      sw.Write(value); 
      sw.Flush(); 
      return stream.ToArray(); 
     } 
    } 
} 

用法:

stringValue.ToBytes(Encoding.UTF8) 

这也适用于其他编码,如需要BOM的UTF-16。

+0

这实际上是一个非常有用的解决方法。使用带编码的'StreamWriter',解决了我的直接问题,并允许使用Excel 2013打开我的文件。 – 2015-06-29 10:00:13