Как определить кодировку в текстовом файле (имея в наличии только файл)?

1. Denis211990 20 10.03.22 10:28 Сейчас в теме
Требуется определить, какая кодировка используется в файле.
Чтобы предупредить пользователя
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. Denis211990 20 10.03.22 11:48 Сейчас в теме
(2) нужен другой вариант, без необходимости ввода подстроки поиска
4. starik-2005 3052 10.03.22 12:39 Сейчас в теме
(3)
без необходимости ввода подстроки поиска
Все зависит от характера файла. Кодировка - это интерпретация только русских букв (и прочих знаков национальных алфавитов, отличных от латиницы, цифр и знаков препинания, ...). В итоге единственная мера - открыть файл в разных кодировках и найти русские буквы там, где они должны быть исходя из характера данных.
Denis211990; +1 Ответить
5. ishelper 10.03.22 13:03 Сейчас в теме
(3)
без необходимости ввода подстроки поиска
Без строки поиска требуется понимание содержания текста. Вряд ли можно рассчитывать в этом на 1С. ;-)

Просто строку поиска нужно задавать программно, подбирая ее по частоте использования в языке, возможно - не одну, например, искать: " и ", " не ", "но " и так далее
Denis211990; +1 Ответить
11. dehro 5 29.01.23 09:21 Сейчас в теме
(1)Однозначно: никак. Текстовый файл: набор байтов, разделённых байтом EOL и заканчивающихся байтом EOF. Никакого заголовка, как например у файла архива или exe-шника, у него нет.

Для двухбайтных кодировок вряд ли что изменилось. Просто теперь это последовательность машинных слов (word), а не одиночных байтов.

Все утилиты путём анализа символов (последовательностей, количества, etc) пытаются угадать кодировку.
13. Said-We 27.03.23 19:38 Сейчас в теме
(1)
Требуется определить, какая кодировка используется в файле.
Чтобы предупредить пользователя


В идеале никак.
Браузеры свои алгоритмы сложные имеют и то иногда кракозябры открывают.

Но чаще всего это UTF-8. Т.е. каждый символ может занимать от одного байта до 4-х. И всё это в одном и том же тексте. Одновременно.
Английский язык один байт, русский два, грузинский три, азиатские иероглифы 4-ре.

ASCII, КОИ-8, UTF-8 первые символы и английские символы максимально совпадают.
КОИ-7 давно не видел.
6. cargobird 306 30.11.22 12:36 Сейчас в теме
Такую функцию сделал исходя из предположения, что коды символов всех знаков находятся до 100, а коды символов заглавных букв от А до Я находится в диапазоне 1040-1071. Исключение - Ё с кодом 1025.
Так вот, если при чтении файла с заданной кодировкой встречается символ вне указанных диапазонов - то это битый символ, значит кодировка не та надо прочитать файл с другой кодировкой (и так до победного).
Для небольших файлов пригодилось.

Функция ОпределитьКодировкуФайла(ПутьКФайлу) Экспорт 
	мКодировок=Новый Массив;
	мКодировок.Добавить(КодировкаТекста.ANSI);
	мКодировок.Добавить(КодировкаТекста.OEM);
	мКодировок.Добавить(КодировкаТекста.UTF16);
	мКодировок.Добавить(КодировкаТекста.UTF8);	
	мНайденных=Новый Массив;
	Для каждого рКодировка Из мКодировок Цикл
		т=Новый ТекстовыйДокумент;
		т.Прочитать(ПутьКФайлу,рКодировка);
		стро=ВРег(т.ПолучитьТекст()); // ВРег это важно
		Если НЕ НайтиСимволыВнеДиапазона(стро) Тогда
			// если не найдено ни одного "битого" символа - искомая кодировка
			Возврат рКодировка;
		КонецЕсли;		
	КонецЦикла;
	Возврат КодировкаТекста.ANSI; // по умолчанию	
КонецФункции

Функция НайтиСимволыВнеДиапазона(ТекСтрока) 
	Для Поз = 1 По СтрДлина(ТекСтрока) Цикл
		ТекКод = КодСимвола(Сред(ТекСтрока, Поз, 1));
		Если (ТекКод  > 100 // до 100 разные знаки типа % - " и т.д.
			И ТекКод < 1040 // 1040  код символа А
			И НЕ ТекКод = 1025)  // 1025 код символа Ё (вне диапазона заглавных букв А-Я 1040-1071)
			ИЛИ ТекКод > 1071// 1071 код символа Я
			Тогда
			Возврат Истина;
		КонецЕсли; 
	КонецЦикла;
	Возврат Ложь;	
КонецФункции
Показать
Denis211990; +1 Ответить
7. user1863362 30.11.22 12:46 Сейчас в теме
(6)
коды символов всех знаков находятся до 100

Вот скажи честно, ты таблицу ASCII вообще видел? Скобки там разные квадратные, фигурные, не? Битые символы, да?
cargobird; +1 Ответить
9. cargobird 306 30.11.22 13:02 Сейчас в теме
(7) до 126 нижний диапазон расширить надо.
Спасибо за подсказку!
8. ImHunter 318 30.11.22 12:48 Сейчас в теме
(1) Определял для XML. Может подойдет.
Denis211990; +1 Ответить
10. triviumfan 95 28.01.23 23:40 Сейчас в теме
В ERP есть такое:
// Возвращает наиболее подходящую кодировку текста, полученную путем сравнения с алфавитом.
//
// Параметры:
//  ДанныеТекста - ДвоичныеДанные - двоичные данные файла.
//
// Возвращаемое значение:
//  Строка - кодировка файла.
//
Функция КодировкаИзСоответствияАлфавиту(ДанныеТекста)
	
	Кодировки = РаботаСФайламиСлужебный.Кодировки();
	Кодировки.Удалить(Кодировки.НайтиПоЗначению("utf-8_WithoutBOM"));
	
	КодировкаKOI8R = Кодировки.НайтиПоЗначению("koi8-r");
	Кодировки.Сдвинуть(КодировкаKOI8R, -Кодировки.Индекс(КодировкаKOI8R));
	
	КодировкаWin1251 = Кодировки.НайтиПоЗначению("windows-1251");
	Кодировки.Сдвинуть(КодировкаWin1251, -Кодировки.Индекс(КодировкаWin1251));
	
	КодировкаUTF8 = Кодировки.НайтиПоЗначению("utf-8");
	Кодировки.Сдвинуть(КодировкаUTF8, -Кодировки.Индекс(КодировкаUTF8));
	
	СоответствующаяКодировка = "";
	МаксимальноеСоответствиеКодировки = 0;
	Для Каждого Кодировка Из Кодировки Цикл
		
		СоответствиеКодировки = ПроцентСоответствияАлфавиту(ДанныеТекста, Кодировка.Значение);
		Если СоответствиеКодировки > 0.95 Тогда
			Возврат Кодировка.Значение;
		КонецЕсли;
		
		Если СоответствиеКодировки > МаксимальноеСоответствиеКодировки Тогда
			СоответствующаяКодировка = Кодировка.Значение;
			МаксимальноеСоответствиеКодировки = СоответствиеКодировки;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат СоответствующаяКодировка;
	
КонецФункции

Функция ПроцентСоответствияАлфавиту(ДвоичныеДанные, ПроверяемаяКодировка)
	
	// АПК:1036-выкл, АПК:163-выкл - алфавит не требует проверки орфографии.
	Алфавит = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬ­ьЭэЮюЯя"
		+ "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
		+ "1234567890 ";
	// АПК:1036-вкл, АПК:163-вкл
	
	ПотокАлфавита = Новый ПотокВПамяти();
	ЗаписьАлфавита = Новый ЗаписьДанных(ПотокАлфавита);
	ЗаписьАлфавита.ЗаписатьСтроку(Алфавит, ПроверяемаяКодировка);
	ЗаписьАлфавита.Закрыть();
	
	ДанныеАлфавита = ПотокАлфавита.ЗакрытьИПолучитьДвоичныеДанные();
	ЧтениеДанныхАлфавита = Новый ЧтениеДанных(ДанныеАлфавита);
	БуферАлфавитаВКодировке = ЧтениеДанныхАлфавита.ПрочитатьВБуферДвоичныхДанных();
	
	Индекс = 0;
	СимволыАлфавита = Новый Массив;
	Пока Индекс <= БуферАлфавитаВКодировке.Размер - 1 Цикл
		
		ТекущийСимвол = БуферАлфавитаВКодировке[Индекс];
		
		// Символы кириллицы в кодировке UTF-8 - двухбайтовые.
		Если ПроверяемаяКодировка = "utf-8"
			И (ТекущийСимвол = 208
			Или ТекущийСимвол = 209) Тогда
			
			Индекс = Индекс + 1;
			ТекущийСимвол = Формат(ТекущийСимвол, "ЧН=0; ЧГ=") + Формат(БуферАлфавитаВКодировке[Индекс], "ЧН=0; ЧГ=");
		КонецЕсли;
		
		Индекс = Индекс + 1;
		СимволыАлфавита.Добавить(ТекущийСимвол);
		
	КонецЦикла;
	
	ЧтениеДанныхТекста = Новый ЧтениеДанных(ДвоичныеДанные);
	БуферДанныхТекста = ЧтениеДанныхТекста.ПрочитатьВБуферДвоичныхДанных(?(ПроверяемаяКодировка = "utf-8", 200, 100));
	РазмерБуфераТекста = БуферДанныхТекста.Размер;
	КоличествоСимволов = РазмерБуфераТекста;
	
	Индекс = 0;
	КоличествоВхождений = 0;
	Пока Индекс <= РазмерБуфераТекста - 1 Цикл
		
		ТекущийСимвол = БуферДанныхТекста[Индекс];
		Если ПроверяемаяКодировка = "utf-8"
			И (ТекущийСимвол = 208
			Или ТекущийСимвол = 209) Тогда
			
			// Если последний байт в буфере является первым байтом двухбайтового символа, игнорируем его.
			Если Индекс = РазмерБуфераТекста - 1 Тогда
				Прервать;
			КонецЕсли;
			
			Индекс = Индекс + 1;
			КоличествоСимволов = КоличествоСимволов - 1;
			ТекущийСимвол = Формат(ТекущийСимвол, "ЧН=0; ЧГ=") + Формат(БуферДанныхТекста[Индекс], "ЧН=0; ЧГ=");
			
		КонецЕсли;
		
		Индекс = Индекс + 1;
		Если СимволыАлфавита.Найти(ТекущийСимвол) <> Неопределено Тогда
			КоличествоВхождений = КоличествоВхождений + 1;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат ?(КоличествоСимволов = 0, 100, КоличествоВхождений/КоличествоСимволов);
	
КонецФункции
Показать
Denis211990; +1 Ответить
12. ybatiaev 58 27.03.23 19:13 Сейчас в теме
(10)
КодировкаИзСоответствияАлфавиту

так понял, что данной функции надо скармливать файлы с только определёнными именами. По крайней мере в Бух30 так сейчас (
14. triviumfan 95 27.03.23 21:49 Сейчас в теме
(12) Параметр "ДанныеТекста" - двоичные данные. Где там хотя бы слово про формат файла?)
Анализируется сам текст.
15. ybatiaev 58 27.03.23 22:10 Сейчас в теме
(14)
(14) Это я воспользовался стандартной РегистрыСведенийКодирвкиФайлов.ОпределитьКодирвкиФайлов(ПрисоединенныйФайл, Расширение)
Ошибку выдавала 1С не про формат, а про имена файлов. Типа ожидаю вот такие, а мне подсунуто "Тест.txt"
16. user1826630 27.03.23 22:38 Сейчас в теме
(15)
Типа ожидаю вот такие, а мне подсунуто "Тест.txt"
Точно! Кодировка текста определяется расширением файла!
17. ybatiaev 58 27.03.23 22:40 Сейчас в теме
(16) расширение задаётся параметром, что не так? И не надо смеяться. Сделал в итоге по Вашему. Стандартную сразу не использую
(16)
18. user1826630 27.03.23 22:52 Сейчас в теме
(17)
Сделал в итоге по Вашему.
Я разве предлагал свое решение? Покажите мне его.
расширение задаётся параметром, что не так?
А проблема разве в расширении? Проблема в определении кодировки.
19. ybatiaev 58 27.03.23 23:41 Сейчас в теме
(18)
А проблема разве в расширении? Проблема в определении кодировки.

Так и пытаюсь это решить же. Если операционка определяет это чётко, значит как бы можно используя WMI это сделать. Пока не нашёл правильного решения
20. triviumfan 95 28.03.23 14:57 Сейчас в теме
(19) Ничего не понял, причём тут WMI.
Понял, что вы пытались использовать типовую функцию, неверно передав в неё параметр "расширение", хотя оно нужно лишь для частного случая определения кодировки из xml файла по заголовку:)
Вообще я сомневаюсь, что это "определение по алфавиту" работает, я просто нашёл её в одном из решении, проверил работу и всё)
21. ybatiaev 58 28.03.23 15:03 Сейчас в теме
(20)
(20)
Ничего не понял, причём тут WMI

Это я написал, что ВОЗМОЖНО есть механизмы операционки для определения кодировки. Они 100% есть, т.к. открываешь файл в Виндах - кодировка сразу прописана в строке состояния. У нас. на некоторых серверах не прописана. Т.е. задана системная и, скорее всего, других не используется вообще. Спросил только потому, что может кто-то сталкивался...
Предварительно решил как предложил cargobird(6). Пользователи работают...
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот