Писать текстовые файлы без метки порядка байтов (BOM)?

116

Я пытаюсь создать текстовый файл с помощью VB.Net с кодировкой UTF8 без спецификации. Кто-нибудь может мне помочь, как это сделать?
Я могу записать файл в кодировке UTF8, но как удалить из него отметку порядка байтов?

edit1: я пробовал такой код;

    Dim utf8 As New UTF8Encoding()
    Dim utf8EmitBOM As New UTF8Encoding(True)
    Dim strW As New StreamWriter("c:\temp\bom\1.html", True, utf8EmitBOM)
    strW.Write(utf8EmitBOM.GetPreamble())
    strW.WriteLine("hi there")
    strW.Close()

        Dim strw2 As New StreamWriter("c:\temp\bom\2.html", True, utf8)
        strw2.Write(utf8.GetPreamble())
        strw2.WriteLine("hi there")
        strw2.Close()

1.html создается только с кодировкой UTF8, а 2.html создается с форматом кодировки ANSI.

Упрощенный подход - http://whatilearnttuday.blogspot.com/2011/10/write-text-files-without-byte-order.html

Виджей Балкаваде
источник
8
Если вам не нужна спецификация, зачем вы пишете GetPreamble ()?
Ханс Пассан,

Ответы:

200

Чтобы опустить отметку порядка байтов (BOM), ваш поток должен использовать экземпляр, UTF8Encodingотличный от System.Text.Encoding.UTF8(который настроен для создания BOM). Это можно сделать двумя простыми способами:

1. Явное указание подходящей кодировки:

  1. Вызвать UTF8Encodingконструктор с Falseдля encoderShouldEmitUTF8Identifierпараметра.

  2. Передайте UTF8Encodingэкземпляр конструктору потока.

' VB.NET:
Dim utf8WithoutBom As New System.Text.UTF8Encoding(False)
Using sink As New StreamWriter("Foobar.txt", False, utf8WithoutBom)
    sink.WriteLine("...")
End Using
// C#:
var utf8WithoutBom = new System.Text.UTF8Encoding(false);
using (var sink = new StreamWriter("Foobar.txt", false, utf8WithoutBom))
{
    sink.WriteLine("...");
}

2. Использование кодировки по умолчанию:

Если вы вообще не предоставили конструктор Encodingto StreamWriter, StreamWriterпо умолчанию будет использоваться кодировка UTF8 без спецификации, поэтому следующее должно работать точно так же:

' VB.NET:
Using sink As New StreamWriter("Foobar.txt")
    sink.WriteLine("...")
End Using
// C#:
using (var sink = new StreamWriter("Foobar.txt"))
{
    sink.WriteLine("...");
}

Наконец, обратите внимание, что исключение спецификации допустимо только для UTF-8, но не для UTF-16.

stakx - больше не участвует
источник
Не всегда разумно: например, My.Computer.FileSystem.WriteAllTextпишет спецификацию, если кодировка не указана.
beppe9000 04
My.Computer.FileSystem.WriteAllTextявляется исключением в этом отношении, возможно, предполагая обратную совместимость с VB? File.WriteAllTextпо умолчанию UFT8NoBOM.
jnm2 06
28

Попробуй это:

Encoding outputEnc = new UTF8Encoding(false); // create encoding with no BOM
TextWriter file = new StreamWriter(filePath, false, outputEnc); // open file with encoding
// write data here
file.Close(); // save and close it
Роман Никитин
источник
6

Просто используйте метод WriteAllTextиз System.IO.File.

Пожалуйста, проверьте образец из File.WriteAllText .

В этом методе используется кодировка UTF-8 без метки порядка байтов (BOM), поэтому использование метода GetPreamble вернет пустой массив байтов. Если необходимо включить идентификатор UTF-8, например метку порядка байтов, в начало файла, используйте перегрузку метода WriteAllText (String, String, Encoding) с кодировкой UTF8.

Joe.wang
источник
Тот из пространства имен My действительно использует BOM
beppe9000
4

Интересное замечание по этому поводу: как ни странно, статический метод CreateText () класса System.IO.File создает файлы UTF-8 без спецификации.

В общем, это источник ошибок, но в вашем случае это могло быть простейшее решение :)

Tao
источник
4

Если вы не укажете Encodingпри создании нового объекта, StreamWriterпо умолчанию будет Encodingиспользоваться объект, UTF-8 No BOMсозданный с помощью new UTF8Encoding(false, true).

Итак, чтобы создать текстовый файл без спецификации, используйте конструкторы, которые не требуют от вас предоставления кодировки:

new StreamWriter(Stream)
new StreamWriter(String)
new StreamWriter(String, Boolean)
JG в SD
источник
Что делать, если мне нужно указать leaveOpen?
binki
@binki в этом случае вы не можете использовать кодировку по умолчанию, которая StreamWriterиспользует. Вам нужно будет указать, new UTF8Encoding(false, true)чтобы ваша кодировка могла указывать leaveOpenи не иметь спецификации.
JG в SD
3

Я считаю, что Роман Никитин прав. Значение аргумента конструктора переворачивается. Ложь означает отсутствие спецификации, а истина означает, что спецификация есть.

Вы получаете кодировку ANSI, потому что файл без спецификации, не содержащий символов, отличных от ANSI, в точности совпадает с файлом ANSI. Попробуйте ввести в строку «привет» несколько специальных символов, и вы увидите, что кодировка ANSI изменилась на без спецификации.

Jos
источник
1

Кодирование XML UTF-8 без спецификации
Нам нужно отправить данные XML в EPA, и их приложение, которое принимает наши входные данные, требует UTF-8 без спецификации. О да, простой UTF-8 должен быть приемлем для всех, но не для EPA. Ответ на этот вопрос находится в комментариях выше. Спасибо Роман Никитин .

Вот фрагмент кода C # для кодировки XML:

    Encoding utf8noBOM = new UTF8Encoding(false);  
    XmlWriterSettings settings = new XmlWriterSettings();  
    settings.Encoding = utf8noBOM;  
          
    using (XmlWriter xw = XmlWriter.Create(filePath, settings))  
    {  
        xDoc.WriteTo(xw);  
        xw.Flush();  
    }    

Можно ввести в заблуждение, чтобы увидеть, действительно ли это удаляет три ведущих символа из выходного файла. Например, если вы используете Notepad ++ (www.notepad-plus-plus.org), он сообщит «Кодировать в ANSI». Я предполагаю, что большинство текстовых редакторов рассчитывают на символы спецификации, чтобы определить, является ли это UTF-8. Это можно четко увидеть с помощью бинарного инструмента, такого как WinHex (www.winhex.com). Поскольку я искал разницу до и после, я использовал приложение Microsoft WinDiff .

Джерри Банасик
источник
-1

Возможно, ваш вводимый текст содержит отметку порядка байтов. В этом случае вы должны удалить его перед написанием.


источник
1
Пожалуйста, помогите мне. Как убрать перед написанием.
Виджей Балкаваде,
@ user180326 разве читатель по умолчанию уже не отфильтровывает это для вас?
binki
-1
Dim sWriter As IO.StreamWriter = New IO.StreamWriter(shareworklist & "\" & getfilename() & ".txt", False, Encoding.Default)

Дает те результаты, которые вы хотите (я думаю).

Mwenyeji
источник
1
На моем ПК он создает файлы ANSI
Muflix