如何向 StringBuilder 添加字节顺序标记? (我必须将字符串传递给另一个方法,该方法会将其保存为文件,但我无法修改该方法)。
我试过这个:
var sb = new StringBuilder();
sb.Append('\xEF');
sb.Append('\xBB');
sb.Append('\xBF');
但是当我用十六进制编辑器查看它时,它添加了以下序列:
C3 AF C2 BB C2 BF
字符串很大,所以最好不要来回转换为字节数组。
编辑: 评论中的问题后进行澄清。我必须将字符串传递给另一个方法,该方法接受一个字符串并在 Azure Blob 存储上创建它的文件。我无法修改其他方法。
两种选择:
将其作为角色包含在您的
StringBuilder
中:
sb.Append('\uFEFF'); // U+FEFF is the byte-order mark character
就我个人而言,我通常会选择第一种方法,但“我无法修改该方法”表明它可能不是您的情况的选择。
字节顺序标记是为了告知文件的读取者该文件具有特定的编码。因此,您应该只需要实际文件中的字节顺序标记 (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());
IIRC(我不确定),当您使用相关的 Unicode 编码器之一转换为字节时,BOM 会被添加。我相信 一些 UnicodeEncoding 的构造函数 采用 bool 来控制是否添加 BOM。
我在 ASP.NET core 中使用了这段代码,效果很好!它有效
[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;
}
}
}