Перейти к содержимому

Как узнать кодировку файла c

  • автор:

Как узнать кодировку файла c

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

Спросил Sergey
655 дн., 17 час., 31 мин. назад

Новые ответы

Если речь идёт о кодировке UTF-8, то можно использовать проект Utf8Checker. Проект состоит из одного класса (и интерфейса к нему), который и делает всю работу.

Ответил admax
618 дн., 1 час., 9 мин. назад

И все же мне удалось решить проблему

BinaryReader instr = new BinaryReader(File.OpenRead(path)); byte[] data = instr.ReadBytes((int)instr.BaseStream.Length); instr.Close(); // определяем BOM (EF BB BF) if (data.Length > 2 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf) < if (data.Length != 3) return Encoding.UTF8.GetString(data, 3, data.Length - 3); else return ""; >int i = 0; while (i < data.Length - 1) < if (data[i] >0x7f) < // не ANSI-символ if ((data[i] >> 5) == 6) < if ((i >data.Length - 2) || ((data[i + 1] >> 6) != 2)) return Encoding.GetEncoding(1251).GetString(data); i++; > else if ((data[i] >> 4) == 14) < if ((i >data.Length - 3) || ((data[i + 1] >> 6) != 2) || ((data[i + 2] >> 6) != 2)) return Encoding.GetEncoding(1251).GetString(data); i += 2; > else if ((data[i] >> 3) == 30) < if ((i >data.Length - 4) || ((data[i + 1] >> 6) != 2) || ((data[i + 2] >> 6) != 2) || ((data[i + 3] >> 6) != 2)) return Encoding.GetEncoding(1251).GetString(data); i += 3; > else < return Encoding.GetEncoding(1251).GetString(data); >> i++; > return Encoding.UTF8.GetString(data); 

Теперь немного поясню: Сиволы в UTF-8 кодируются последовательностями длиной от 1 до 4 байт (октетов).

Вот в таком формате:

U+000000-U+00007F: 0xxxxxxx (ANSI) U+000080-U+0007FF: 110xxxxx 10xxxxxx (сюда входит кириллица) U+000800-U+00FFFF: 1110xxxx 10xxxxxx 10xxxxxx U+010000-U+10FFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 

По маске первого октета определяется общее число октет в последовательности, а затем они проверяются на соответствие маске 10xxxxxx. Если какой-то байт не соответсвует маске, значит кодировка отличная от UTF-8 (в моем случае win1251).

Код, конечно, громоздкий, но для демонтрации самого алгоритма вполне достаточный

Определение кодировки

Поле DllImportAttribute.CharSet управляет маршалированием строк и определяет, как вызов платформы находит имена функций в библиотеке DLL. В этом разделе описываются оба механизма.

Некоторые API экспортируют две версии функций, которые принимают строковые аргументы: обычные (ANSI) и двухбайтовые (Юникод). Например, API Windows включает следующие имена точек входа для функции MessageBox:

  • MessageBoxA Обеспечивает форматирование однобайтовых символов ANSI и имеет суффикс «A» в имени точки входа. При вызове MessageBoxA строки всегда маршалируются в формате ANSI.
  • MessageBoxW Обеспечивает форматирование двухбайтовых символов Юникода и имеет суффикс «W» в имени точки входа. При вызове MessageBoxW строки всегда маршалируются в формате Юникод.

Маршалирование строк и сопоставление имен

Поле CharSet принимает следующие значения:

Ansi (значение по умолчанию)

  • Маршалирование строк При вызове неуправляемого кода выполняется маршалинг строк из соответствующего управляемого формата (Юникод) в формат ANSI.
  • Сопоставление имен Если поле DllImportAttribute.ExactSpelling имеет значение true (значение по умолчанию в Visual Basic), при вызове неуправляемого кода осуществляется поиск только указанного имени. Например, если указать MessageBox, при вызове неуправляемого кода будет выполнен поиск MessageBox, который может завершиться сбоем из-за невозможности найти точное совпадение. Если поле ExactSpelling имеет значение false (по умолчанию для C++ и C#), при вызове неуправляемого кода выполняется поиск сначала неуправляемого псевдонима (MessageBox), а затем, если неуправляемый псевдоним не найден, управляемого имени (MessageBoxA). Обратите внимание, что принципы сопоставления имен ANSI и Юникода различаются.
  • Маршалирование строк При вызове неуправляемого кода строки копируются из соответствующего управляемого формата (Юникод) в формат Юникода.
  • Сопоставление имен Если поле ExactSpelling имеет значение true (значение по умолчанию в Visual Basic), при вызове неуправляемого кода осуществляется поиск только указанного имени. Например, если указать MessageBox, при вызове неуправляемого кода будет выполнен поиск MessageBox, который может завершиться сбоем из-за невозможности найти точное совпадение. Если поле ExactSpelling имеет значение false (по умолчанию для C++ и C#), при вызове неуправляемого кода выполняется поиск сначала управляемого имени (MessageBoxW), а затем, если управляемое имя не найдено, неуправляемого псевдонима (MessageBox). Обратите внимание, что принципы сопоставления имен Юникода и ANSI различаются.
  • При вызове неуправляемого кода во время выполнения осуществляется выбор между форматами ANSI и Юникода в соответствии с целевой платформой.

Определение кодировки в Visual Basic

В Visual Basic можно указать поведение кодировки, добавив ключевое слово Ansi , Unicode или Auto в операторе объявления. Если опустить ключевое слово кодировки, в поле DllImportAttribute.CharSet по умолчанию будет задана кодировка ANSI.

В следующем примере функция MessageBox объявляется три раза с разными кодировками. В первом операторе ключевое слово кодировки опущено, в связи с чем по умолчанию устанавливается кодировка ANSI. Во втором и третьем операторе кодировка задается явно с использованием ключевого слова.

Friend Class NativeMethods Friend Declare Function MessageBoxA Lib "user32.dll" ( ByVal hWnd As IntPtr, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As UInteger) As Integer Friend Declare Unicode Function MessageBoxW Lib "user32.dll" ( ByVal hWnd As IntPtr, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As UInteger) As Integer Friend Declare Auto Function MessageBox Lib "user32.dll" ( ByVal hWnd As IntPtr, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As UInteger) As Integer End Class 

Определение кодировки в C# и C++

Поле DllImportAttribute.CharSet определяет базовую кодировку как ANSI или Юникод. Набор символов определяет способ маршалирования строковых аргументов метода. Чтобы указать кодировку, используйте одну из следующих форм:

[DllImport("DllName", CharSet = CharSet.Ansi)] [DllImport("DllName", CharSet = CharSet.Unicode)] [DllImport("DllName", CharSet = CharSet.Auto)] 
[DllImport("DllName", CharSet = CharSet::Ansi)] [DllImport("DllName", CharSet = CharSet::Unicode)] [DllImport("DllName", CharSet = CharSet::Auto)] 

В следующем примере показаны три управляемых определения функции MessageBox с атрибутами, задающими кодировку. В первом определении соответствующее ключевое слово опущено, в результате чего в поле CharSet по умолчанию устанавливается кодировка ANSI.

using System; using System.Runtime.InteropServices; internal static class NativeMethods
typedef void* HWND; // Can use MessageBox or MessageBoxA. [DllImport("user32")] extern "C" int MessageBox( HWND hWnd, String* lpText, String* lpCaption, unsigned int uType); // Can use MessageBox or MessageBoxW. [DllImport("user32", CharSet = CharSet::Unicode)] extern "C" int MessageBoxW( HWND hWnd, String* lpText, String* lpCaption, unsigned int uType); // Must use MessageBox. [DllImport("user32", CharSet = CharSet::Auto)] extern "C" int MessageBox( HWND hWnd, String* lpText, String* lpCaption, unsigned int uType); 

См. также

  • DllImportAttribute
  • Создание прототипов в управляемом коде
  • Примеры вызовов неуправляемого кода
  • Маршалирование данных с помощью вызова платформы

Совместная работа с нами на GitHub

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

FAQ: Как проверить кодировку в текстовом файле?

Программный комплекс SocialKit корректно работает с кириллицей в текстовых файлах, кодировка которых соответствует стандарту Windows-1251 (кратко может быть записано как CP1251 или ANSI). В этой связи в задачах, поддерживающих указание внешнего файла с перечнем комментариев, сообщений, описаний и прочей информации, которая может содержать кириллицу, нужно указывать текстовые файлы, где русский текст задан в кодировке по стандарту Windows-1251 или же просто ANSI, или CP1251 — всё это, по сути, одно и то же.

Учитывая, что многие инструменты по работе с текстом не отображают, в какой именно кодировке задан текст в текстовом файле и/или не поддерживают преобразование кодировок, то у новичков часто возникает вопрос о том, как именно привести кодировку текстового файла с русским текстом к понятному для SocialKit формату CP1251.

Следует сразу отметить, что большинство текстовых редакторов для ОС Windows (например, встроенный Блокнот и Wordpad) по умолчанию создают текстовые файлы именно с кодировкой по стандарту Windows-1251. Однако, эта кодировка по умолчанию может быть изменена в следствие тех или иных действий.

Если вы не уверены в том, в какой именно кодировке задан текст, то проще всего этот текст пересохранить через стандартный Блокнот Windows. При пересохранении Блокнот также покажет, в каком формате текст сейчас.

Опишем эту простую процедуру по шагам.

1. Открыть искомый текстовый файл в Блокноте Windows и выбрать пункт меню «Файл» -> «Сохранить как. «.

Пример текстового файла, в котором русский текст задан в формате UTF, но это не очевидно при открытии.

2. В открывшемся диалоговом окне вы сразу видите, в какой кодировке был сохранён текст в текстовом файле.

Диалоговое окно пересохранения текстового файла, в котором можно сразу изменить кодировку.

Как видно, в примере текст в текстовом файле был ранее сохранён в кодировке UTF-8. Для изменения кодировке достаточно выбрать в выпадающем списке кодировку ANSI и нажать кнопку «Сохранить«.

При этом зрительно для вас ничего не изменится, но многое изменится для программы и алгоритмов, занимающихся обработкой текста в процессе отправки. Корректно Instagram’у будет отправлен только ANSI-текст.

C#: распознать кодировку

Собственно проблема заключается в том, что есть 2 типа файлов, в одних текст сохранён в кодировке UTF8 в других — Windows-1251 и необходимо переконвертировать файлы Windows-1251 в UTF8, с UTF8 ничего не делать. Как определить кодировку файла? Я Не знаю заведомо в какой кодировке сохранён файл.

StreamReader sr = new StreamReader(s, true); //true — определить кодировку, но sr.CurrentEncoding показывает что кодировка Encoding.UTF8

12 ответов

19 мая 2009 года
3.0K / / 25.03.2003
А префикса в UTF8 файле нету?
19 мая 2009 года
3 / / 19.05.2009

Префикс? типа имя файла вида utf8_144545.txt, win-1251_3243222.txt?? нет все файлы имеют имя \d<1,5>.txt

Есть только фолдер с файлами различной кодировки, необходимо чтобы все файлы стали в UTF8.

19 мая 2009 года
3.0K / / 25.03.2003

Префикс? типа имя файла вида utf8_144545.txt, win-1251_3243222.txt?? нет все файлы имеют имя \d<1,5>.txt

Есть только фолдер с файлами различной кодировки, необходимо чтобы все файлы стали в UTF8.

Я про первые 3 байта в файле.

[FONT=»Courier New»][SIZE=»2″]UTF-8 (EF BB BF)
UTF-16 big-endian (FE FF)
UTF-16 little-endian (FF FE)
UTF-32 big-endian (00 00 FE FF)
UTF-32 little-endian (FF FE 00 00)[/SIZE][/FONT]

Читаешь первые три байта файла. И если они равны 0xEF 0xBB 0xBF, то файл должен быть в UTF-8. Правда, это условие не всегда выполняется.

19 мая 2009 года
3 / / 19.05.2009
К сожалению юникод файлы сохранены без сигнатуры
19 мая 2009 года
3.0K / / 25.03.2003

Ну тогда, поскольку символы в UTF-8 определяются последовательностями от 1 до 4 байт, можно попробовать анализ по маске первого байта в коде.

19 мая 2009 года
3.3K / / 19.06.2008

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

20 мая 2009 года
3.0K / / 13.12.2005

Я про первые 3 байта в файле.

Читаешь первые три байта файла. И если они равны 0xEF 0xBB 0xBF, то файл должен быть в UTF-8. Правда, это условие не всегда выполняется.

Что-то мне говорить, что это BOM 😉

20 мая 2009 года
3.0K / / 13.12.2005

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

На сколько я помню как раз утф-8 проще всего и распознать. На практике в утф-8 используется от 1 до 4 байт. Два первых старших бита в первом байте всегда установлены в единицу. С учетом BOM-а нужно прочитать первых 7 байт. Для полной гарантии и определения размерности байт на символ конечно лучше прочесть все же первые 11. Собственно по ним и будет видно.

20 мая 2009 года
3.3K / / 19.06.2008

М-м-м.. Все же скажу хоть первый раз не собрался :). Насколько помню я, по стандарту, UTF8 может отводить на 1 символ до 6 байт. Вот даж прям счаз лезть проверять лень :). Ну просто не факт что последовательности из5-6 байт за чем-то закреплены. А английский текст на UTF8 выглядит аналогично ANSI, поэтому я и говорю что задача непростая (имеется ввиду нет у нее четкого алгоритмического решения). А вот если символ из некоей национальной кодировки (занимает несколько байт) то да, вплоть до последнего байта некоторые биты в начальных байтах играют роль флагов. Но эти же байты не запрещены в ANSI что делает отнесение потока к ANSI/UTF не совсем тривиальной задачей

20 мая 2009 года
2.7K / / 02.02.2008

Теоретически, текст может отличаться только тем, что в UTF-8 невозможны некоторые комбинации байтов, которые используются в ANSI.

Таким образом, можно попытаться переводить текст (с неизвестной кодировкой) из UTF-8 в ANSI и ловить исключение. Если текст был в кодировке ANSI, то может быть сгенерировано исключение.

Это ленивый метод, который в теории может сработать.

20 мая 2009 года
3.3K / / 19.06.2008

Таким образом, можно попытаться переводить текст (с неизвестной кодировкой) из UTF-8 в ANSI и ловить исключение. Если текст был в кодировке ANSI, то может быть сгенерировано исключение.

Ну вообщем я пропагандировал этот же подход. Дополнительно, если возможно основываться на некоем формате/содержимом обрабатываемых файлов можно искать какие-либо шаблоны. Например распространенные слова языка.

20 мая 2009 года
3.0K / / 13.12.2005

М-м-м.. Все же скажу хоть первый раз не собрался :). Насколько помню я, по стандарту, UTF8 может отводить на 1 символ до 6 байт.

Правильно помнишь. Но я подчеркивал:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *