【问题标题】:Add byte order mark to a string via StringBuilder通过 StringBuilder 将字节顺序标记添加到字符串
【发布时间】:2014-03-10 17:07:08
【问题描述】:

如何向 StringBuilder 添加字节顺序标记? (我必须将一个字符串传递给另一个方法,它将它保存为一个文件,但我不能修改那个方法)。

我试过了:

var sb = new StringBuilder();
sb.Append('\xEF');
sb.Append('\xBB');
sb.Append('\xBF');

但是当我用十六进制编辑器查看它时,它会添加以下序列: C3 AF C2 BB C2 BF

字符串很大,最好不用来回转换为字节数组。

编辑: 在 cmets 提问后进行澄清。我必须将字符串传递给另一个方法,该方法接受一个字符串并在 Azure Blob 存储上创建一个文件。我无法修改其他方法。

【问题讨论】:

  • 为什么?在写入文件之前不需要字节顺序标记...您看到的问题是因为字节顺序标记不是 Unicode
  • 我必须将字符串传递给另一个方法,该方法接受一个字符串并在 Azure Blob 存储上创建一个文件。

标签: c# utf-8 stringbuilder byte-order-mark


【解决方案1】:

两种选择:

  1. 根本不要在您的文本中包含字节顺序标记...而是使用会自动包含它的编码
  2. 将其作为一个字符包含在您的StringBuilder中:

    sb.Append('\uFEFF'); // U+FEFF is the byte-order mark character
    

我个人通常会采用第一种方法,但“我无法修改该方法”表明它可能不适用于您的情况。

【讨论】:

  • 谢谢。是的,你是对的,我通常会选择第一个,但我采用这种方法是因为我必须将字符串传递给另一个方法,该方法接受一个字符串并在 Azure Blob 存储上创建一个文件。跨度>
【解决方案2】:

字节顺序标记用于通知文件的读者该文件具有特定编码。因此,您应该只需要实际文件中的字节顺序标记 (BOM)。如果您想在正在编写的文本文件中包含 BOM,只需使用 StreamWriter 写入文件即可。例如:

using(var writer = new StreamWriter(stream, System.Text.Encoding.UTF8))
{
    writer.Write(sb.ToString);
}

如果您不想使用 UTF-8 的 BOM:

using(var writer = new StreamWriter(stream))
{
    writer.Write(sb.ToString());
}

或者如果您想要不同的 BOM:

using(var writer = new StreamWriter(stream, System.Text.Encoding.UTF16))
{
    writer.Write(sb.ToString);
}

更新:

如果您想从 BOM 的实现细节或特定编码的 BOM 中耦合(即可以在运行时或部署后更改)但仍想传递一个 BOM 标记的字符串,您可以这样做(假设 .NET 4.5):

var stream = new MemoryStream();
var encoding = Encoding.UTF8; // TODO: configurize this, if necessary
using(var writer = new StreamWriter(stream, encoding, 1024, true))
{
    writer.Write(sb.ToString());
}
CantModifyButMustUseThis(encoding.GetString(stream.ToArray());

【讨论】:

  • 我知道 BOM 的用途。但是,正如我在问题中提到的,我必须将它传递给另一个方法(它接受一个字符串并在 Azure Blob 存储上创建一个文件),这就是我采用这种方法的原因。
  • 这是误导。例如,对于 UTF-8 和 StreamWriter,如果您完全省略了 encoding 构造函数参数,或者如果您使用 new UTF8Encoding() 作为参数,则 UTF-8 没有 产生字节顺序标记。另一方面,如果您将参数指定为 Encoding.UTF8new UTF8Encoding(true),您将获得 UTF-8 with BOM。实际上,这有点棘手。所以你的第一个例子是错误的。
  • @JeppeStigNielsen 是的,你是对的。我已经按答案修改了。
  • @user2270404 StreamWriter 使用的stream 不需要是文件流。
  • dotnet core 中没有Encoding.UTF16,请改用Encoding.Unicode
【解决方案3】:

IIRC(不确定我是否这样做),当您使用相关的 Unicode 编码器之一转换为字节时,会添加 BOM。我相信some of those's constructors 使用一个布尔值来控制是否添加 BOM。

【讨论】:

    【解决方案4】:

    我在 ASP.NET 核心中使用了这段代码,很好!!它有效

     [HttpGet("GetCsv")]
        public async Task<IActionResult> GetCsv() {
            
            var cc = new CsvConfiguration(new System.Globalization.CultureInfo("en-US"));
            var entity = await _service.AdminPanelList();
            using (var ms = new MemoryStream()) {
                using (var sw = new StreamWriter(stream: ms, encoding: new UTF8Encoding(true))) {
                    using (var cw = new CsvWriter(sw, cc)) {
    
                        var bom = '\uFEFF'.ToString();
                        byte[] bomArray = Encoding.UTF8.GetBytes(bom);
                        
                        ms.Write(bomArray);
                        cw.WriteRecords(entity);
                    }
    
                    var finalArray = ms.ToArray();
                    
    
    
    
                    var result = File(finalArray, "text/csv", $"PersonExport.csv");
                        
    
                    return result;
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 1970-01-01
      • 2021-09-04
      • 2018-10-18
      • 2014-12-24
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      相关资源
      最近更新 更多