Как узнать кодировку файла 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
1,5>
Есть только фолдер с файлами различной кодировки, необходимо чтобы все файлы стали в UTF8.
19 мая 2009 года
3.0K / / 25.03.2003
Префикс? типа имя файла вида utf8_144545.txt, win-1251_3243222.txt?? нет все файлы имеют имя \d<1,5>.txt
1,5>
Есть только фолдер с файлами различной кодировки, необходимо чтобы все файлы стали в 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 байт.
Правильно помнишь. Но я подчеркивал: