创建一个UTF8文本文件而不是ANSI

3

我有这样一段代码可以异步写入文件:

    private static async Task WriteTextAsync(string filePath, string text)
    { //Writes to our output files
        byte[] encodedText = Encoding.UTF8.GetBytes(text);
        using (FileStream sourceStream = new FileStream(filePath,
            FileMode.Create, FileAccess.Write, FileShare.None,
            bufferSize: 4096, useAsync: true))
        {
            await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
        };
    }

尽管设置了Encoding.UTF8,但创建的文本文件仍然是ANSI格式。 FileStream类有15个重载构造函数,如果不是在编码后的文本上设置,我完全不清楚在哪里应该设置它。

我可以判断该文件是ANSI格式,因为当我在TextPad中打开它并查看文件统计信息时,它将ANSI列为代码集:

enter image description here

遇到了问题,因为MySQL的LOAD INFILE无法正确读取该文件,在阅读答案后,我认为这与BOM有关,但不确定。

我尝试了以下内容(用于BOM):

        byte[] encodedText = new byte[] { 0xEF, 0xBB, 0xBF }.Concat(Encoding.UTF8.GetBytes(text)).ToArray();
        using (FileStream sourceStream = new FileStream(filePath,
            FileMode.Create, FileAccess.Write, FileShare.None,
            bufferSize: 4096, useAsync: true))
        {
            await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
        };

在Textpad中打开后,发现文件是UTF8编码,但使用MySQL的LOAD INFILE仍然失败。将文件重新保存在Textpad中后,MySQL便能够正常读取。

代码已更改为:

        using (TextWriter writer = File.CreateText(filePath))
        {
            await writer.WriteAsync(text);
        }

这似乎在两个方面都有效。关于MySQL的LOAD INFILE问题,我不确定是什么原因。


1
关于您的编辑:除非有BOM或字符超过127,否则textpad无法确定它是UTF-8。如果所有字符都在0-127范围内(假设没有BOM),ASCII、ANSI和UTF-8是完全相同的。 - Marc Gravell
2个回答

4
不,它绝对是UTF-8编码:
byte[] encodedText = Encoding.UTF8.GetBytes(text);

这只能给你UTF-8编码;然后你把encodedText写入流中。

然而!对于任何在0-127范围内的字符,UTF-8看起来与ASCII/ANSI完全相同。只有在超出该范围时才会有所不同。误报?


当我在Textpad中打开它时,它将其列为ANSI格式,而MySQL的“load infile”会出现问题。如果我在Textpad中将其重新保存为UTF8格式,则可以解决MySQL的问题。因此,某种方式这个C#程序没有创建一个真正的UTF8文件。 - user17753
@user17753,请查看我在问题上的评论。如果真正的问题是MySQL要求BOM,那么这是一个单独的问题:然而,BOM不是必需品,没有BOM仍然是一个有效的UTF-8文件。 - Marc Gravell

2

我相信您忘记了在文件开头写入BOM标头。由于您使用的是FileStream(而不是某种TextWriter),您必须手动编写它。
对于UTF-8,应该是“EF BB BF”。


1
BOM不会改变文件的编码,只会影响一些文本编辑器打开它的方式。 - jv42
1
BOM并不是必须的,或许有点用处 - 但它也会导致糟糕的客户误解前几个字节,即使其余数据是纯ASCII。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接