Пишіть текстові файли без позначки порядку в байтах (BOM)?


116

Я намагаюся створити текстовий файл за допомогою VB.Net з кодуванням UTF8, без BOM. Хтось може мені допомогти, як це зробити?
Я можу писати файл із кодуванням 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
Якщо ви не хочете BOM, чому ви пишете 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. Використання кодування за замовчуванням:

Якщо ви не надаєте Encodingв StreamWriter«s конструктор взагалі, StreamWriterбуде при використанні замовчуваного UTF8 кодування без BOM, так що наступне повинен працювати точно так же:

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

Нарешті, зауважте, що опускання BOM допустиме лише для UTF-8, а не для UTF-16.


Не завжди розумно: наприклад, My.Computer.FileSystem.WriteAllTextпише BOM, якщо не вказано кодування.
beppe9000

My.Computer.FileSystem.WriteAllTextє винятком у цьому плані, можливо, здогадуючись про зворотну сумісність VB? File.WriteAllTextза замовчуванням UFT8NoBOM.
jnm2

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.


Той, хто в просторі Моїх імен, використовує BOM
beppe9000

4

Цікава примітка щодо цього: як не дивно, статичний метод "CreateText ()" класу System.IO.File створює файли UTF-8 без BOM.

Загалом це джерело помилок, але у вашому випадку це міг бути найпростіший спосіб вирішення :)


4

Якщо ви не вказуєте, Encodingпри створенні нового StreamWriterвикористовується Encodingоб'єкт за замовчуванням , UTF-8 No BOMякий створюється через new UTF8Encoding(false, true).

Отже, щоб створити текстовий файл без використання BOM конструкторів, які не вимагають від вас кодування:

new StreamWriter(Stream)
new StreamWriter(String)
new StreamWriter(String, Boolean)

Що робити, якщо мені потрібно вказати leaveOpen?
бінкі

@binki в цьому випадку ви не можете використовувати кодування за замовчуванням, яке StreamWriterвикористовується. Вам потрібно буде вказати new UTF8Encoding(false, true)для кодування, щоб мати змогу вказати leaveOpenта не мати BOM.
JG в СД

3

Я думаю, що Роман Нікітін має рацію. Значення аргументу конструктора перевернуто. Неправдиво означає відсутність BOM і справжні засоби з BOM.

Ви отримуєте кодування ANSI, оскільки файл без BOM, який не містить символів non-ansi, точно такий же, як файл ANSI. Спробуйте кілька спеціальних символів у рядку "привіт там", і ви побачите зміну кодування ANSI на без-BOM.


1

XML-кодування UTF-8 без BOM
Нам потрібно подати XML-дані в EPA, а їхнє застосування, яке приймає наш вхід, вимагає UTF-8 без BOM. О так, звичайний 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". Я думаю, що більшість текстових редакторів розраховують на символи BOM, щоб сказати, чи це UTF-8. Шляху чітко це зрозуміти - це двійковий інструмент типу WinHex (www.winhex.com). Оскільки я шукав різницю до і після, я використовував додаток Microsoft WinDiff .


-1

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


1
Будь ласка, допоможіть мені. Як її видалити перед написанням.
Vijay Balkawade

@ user180326 чи не читач за замовчуванням вже це фільтрує для вас?
бінкі

-1
Dim sWriter As IO.StreamWriter = New IO.StreamWriter(shareworklist & "\" & getfilename() & ".txt", False, Encoding.Default)

Дає результати як потрібні (я думаю).


1
На моєму ПК він створює файли ANSI
Muflix,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.