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

1. Denis211990 20 10.03.22 10:28 Сейчас в теме
Требуется определить, какая кодировка используется в файле.
Чтобы предупредить пользователя
По теме из базы знаний
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
3. Denis211990 20 10.03.22 11:48 Сейчас в теме
(2) нужен другой вариант, без необходимости ввода подстроки поиска
4. starik-2005 3033 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 312 30.11.22 12:48 Сейчас в теме
(1) Определял для XML. Может подойдет.
Denis211990; +1 Ответить
10. triviumfan 92 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 92 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 92 28.03.23 14:57 Сейчас в теме
(19) Ничего не понял, причём тут WMI.
Понял, что вы пытались использовать типовую функцию, неверно передав в неё параметр "расширение", хотя оно нужно лишь для частного случая определения кодировки из xml файла по заголовку:)
Вообще я сомневаюсь, что это "определение по алфавиту" работает, я просто нашёл её в одном из решении, проверил работу и всё)
21. ybatiaev 58 28.03.23 15:03 Сейчас в теме
(20)
(20)
Ничего не понял, причём тут WMI

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

Руководитель направления 1С
Москва
зарплата от 350 000 руб.
Полный день

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)