Запись текста в кодировке UTF-8 без BOM из 1с 8.2

0. 293 26.05.12 02:51 Сейчас в теме
Как-то хочется из 8.2 записать в кодировке "UTF-8 без BOM" любым из менее затратных способов.

Перейти к публикации

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. andrewks 1313 26.05.12 15:35 Сейчас в теме
если в виндах, то можно заюзать ADODB.Stream

например, так:

		Попытка
			Файл=СоздатьОбъект("ADODB.Stream");
			Файл.Mode=3; // r/w
			Файл.Type=1; //1-Binary, 2-Text
			Файл.Open();
			Файл.LoadFromFile(ИмяФайлаДанных);
			Файл.Position=3;
			ТекстБезБОМ=СоздатьОбъект("ADODB.Stream");
			ТекстБезБОМ.Mode=3; // r/w
			ТекстБезБОМ.Type=1; //1-Binary, 2-Text
			ТекстБезБОМ.Open();
			Файл.CopyTo(ТекстБезБОМ);
			Файл.Close();
			ТекстБезБОМ.SaveToFile(ИмяФайлаДанных,2);
			ТекстБезБОМ.Close();
		Исключение
			ТекстОшибки=ОписаниеОшибки();
			Сообщить(ТекстОшибки,"!");
			Возврат;
		КонецПопытки;

Показать


синтаксис в примере 7-шный, но код применим для любой версии - 7.7, 8.х, главное, чтобы доступ к объекту ADODB.Stream был
Dansur; adhocprog; andrewbc; +3 Ответить
3. andrewbc 293 29.05.12 10:41 Сейчас в теме
(1) andrewks, отлично отработало в следующем виде:

Процедура УбитьВОМ(ИсходныйФайл,РезультирующийФайл)
Попытка
файл = Новый ComObject("ADODB.Stream");
файл.Mode = 3; // r/w
файл.Type = 1; //1-Binary, 2-Text
файл.Open();
файл.LoadFromFile(ИсходныйФайл);
файл.Position = 3;
текстБезБОМ = Новый ComObject("ADODB.Stream");
текстБезБОМ.Mode = 3; // r/w
текстБезБОМ.Type = 1; //1-Binary, 2-Text
текстБезБОМ.Open();
файл.CopyTo(текстБезБОМ);
файл.Close();
текстБезБОМ.SaveToFile(РезультирующийФайл,2);
текстБезБОМ.Close();
УдалитьФайлы(ИсходныйФайл);
Исключение
Сообщить(ОписаниеОшибки(),СтатусСообщения.Важное);
КонецПопытки;
КонецПроцедуры
Mixailovna; +1 Ответить
2. Serj1C 480 28.05.12 12:12 Сейчас в теме
Еще можно провернуть такой танец с бубном (без ВК, работа в памяти, без файлов):
1) получить двоичные данные из файла (как у вас)
2) преобразуем двоичные данные в строку с помощью ЗначениеИзСтрокиВнутр
3) анализируем формат, там не сложно, удаляем лишние переносы кареток (символ 10 вроде) // при желании могу описать подробнее
4) упаковываем поток обратно, получая двоичные данные
5) записываем в файл. Профит
4. andrewbc 293 29.05.12 11:09 Сейчас в теме
(2) Serj1C, не получилось сотворить такой вариант обработки:

1. при преобразовании "ЗначениеВСтрокуВнутр" 1с преобразует двоичные данные в формат base64, при этом длина строки становится больше размера иходного файла почти в полтора раза, это значит, что у нас уже текст не в кодировке UTF-8.
2. не совсем понятно: символы перевода строки (10) (возврат каретки - 13) обязательно удалять? а если это UTF-ный символ с кодом 10?
3. каким образом "упаковать поток обратно"? у объекта "ДвоичныеДанные" только 2 метода - "Размер()" и "Записать(ИмяФайла").
4. как записать в файл результат?

пробовал еще такой вариант:

бин = Новый ДвоичныеДанные(ИсходныйФайл);
бинСтрока = Base64Строка(бин);
новаяБинСтрока = Сред(бинСтрока,4);
бин = Base64Значение(новаяБинСтрока);
бин.Записать(РезультирующийФайл);

но там вообще ерунда получается.
может, примерчик рабочий есть?
5. Serj1C 480 29.05.12 12:23 Сейчас в теме
(4) оформлять как обработку не буду, функции просто положу:

Функция Текст2Base64(Текст, HEX=Ложь)  Экспорт
	// Описание: http://ru.wikipedia.org/wiki/Base64
	Множитель1 = 256;
	Множитель2 = 64;
	СловарьСтрока = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456­789+/=";
	Словарь = Новый Соответствие;
	Для Сч=0 по 64 Цикл
		Словарь.Вставить(Сч, Сред(СловарьСтрока, Сч+1, 1));
	КонецЦикла;
	
	Если HEX=Истина Тогда
		К = 6;
	Иначе
		К = 3;
	КонецЕсли;
	
	ДлинаТекста = СтрДлина(Текст);
	КоличествоЧастей = Цел(ДлинаТекста / К) + ?(ДлинаТекста%К=0, 0, 1);
	Результат = "";
	Для НомерЧасти = 1 По КоличествоЧастей Цикл
		Часть = Сред(Текст, К*(НомерЧасти-1)+1, К);
		
		Если HEX Тогда
			Часть1 = ш(Сред(Часть, 1, 1));
			Часть1 = ш(Сред(Часть, 2, 1)) + Часть1*16;
			Часть2 = ш(Сред(Часть, 3, 1));
			Часть2 = ш(Сред(Часть, 4, 1)) + Часть2*16;
			Часть3 = ш(Сред(Часть, 5, 1));
			Часть3 = ш(Сред(Часть, 6, 1)) + Часть3*16;
		Иначе
			Часть1 = КодСимвола(Сред(Часть, 1, 1));
			Часть2 = КодСимвола(Сред(Часть, 2, 1));
			Часть3 = КодСимвола(Сред(Часть, 3, 1));
		КонецЕсли;
		
		БольшоеЧисло = Часть1 * Множитель1 * Множитель1 + ?(Часть2=-1, 0, Часть2) * Множитель1 + ?(Часть3=-1, 0, Часть3);
		
		Часть4_ = БольшоеЧисло % Множитель2;
		БольшоеЧисло = (БольшоеЧисло-Часть4_) / Множитель2;
		Часть3_ = БольшоеЧисло % Множитель2;
		БольшоеЧисло = (БольшоеЧисло-Часть3_) / Множитель2;
		Часть2_ = БольшоеЧисло % Множитель2;
		БольшоеЧисло = (БольшоеЧисло-Часть2_) / Множитель2;
		Часть1_ = БольшоеЧисло;
		
		Если СтрДлина(Часть)=1*?(HEX, 2, 1)  Тогда
			Часть3_ = 64;
			Часть4_ = 64;
		ИначеЕсли СтрДлина(Часть)=2*?(HEX, 2, 1) Тогда
			Часть4_ = 64;
		КонецЕсли;
		
		Результат = Результат + Словарь.Получить(Часть1_) + Словарь.Получить(Часть2_) + Словарь.Получить(Часть3_) + Словарь.Получить(Часть4_);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции

Функция Ш(С) Экспорт
	Возврат ?(С>="0" и С<="9", КодСимвола(С)-КодСимвола("0"),
		?(С>="A" и С<="F", КодСимвола(С)-КодСимвола("A")+10, -1));
КонецФункции

Процедура Text2Base64(Текст64)
	
	з = "{""#"",87126200-3e98-44e0-b931-ccb1d7edc497,
		|{1,
		|{#base64:"+Текст64+"}
		|}
		|}";
	д = ЗначениеИзСтрокиВнутр(з);
	Сообщить(д);
	д.Записать("e:\1.f");
	
КонецПроцедуры

Процедура Base642Text(Текст64)
	ф = "e:\2.txt";
	норм = "{""#"",87126200-3e98-44e0-b931-ccb1d7edc497,
		|{1,
		|{#base64:"+Текст2Base64(Текст64, Истина)+"}
		|}
		|}";
	д = ЗначениеИзСтрокиВнутр(норм);
	д.Записать(ф);
	Сообщить(д);
КонецПроцедуры
Показать
8. andrewbc 293 31.05.12 12:14 Сейчас в теме
(5) Serj1C, наворочено как-то. для записи простого файлика в формате csv слишком много телодвижений.
самый простой и подходящий вариант - (6).
хотя для общего развития полезно. спасибо.
12. Gmix 402 04.07.12 09:28 Сейчас в теме
(4) Собственно так и делаю.
Только у вас ошибка.
Вот рабочий код:
файлЛог=ПолучитьИмяВременногоФайла(".txt");
	Текст.Записать(файлЛог);
	
	// теперь нужно получить файл без BOM
	ОБ_ДД=Новый ДвоичныеДанные(файлЛог);
	Стр_Base64=Base64Строка(ОБ_ДД);
	ОБ_ДД=Base64Значение(Сред(Стр_Base64,5));
	ОБ_ДД.Записать(файлЛог);


Использовал в Визуализация журнала регистрации Gource
В 8.3 не проверял еще, но думаю должно сработать.
Innuil; seveiven; MsDjuice; +3 Ответить
15. andrewbc 293 04.07.12 15:20 Сейчас в теме
(12) Gmix, этот вариант попробовал - работает. Спасибо за пример. Я просто в цифирьке ошибся. Бывает.
6. mc2 14 30.05.12 10:37 Сейчас в теме
Тоже долго мучился пока нашел как это сделать для записи текстовых файлов средствами 1С:

УдалитьФайлы(ИмяФайла); // надо убедиться, что файл не существует, т.к. если он существует, то данные добавятся в конец файла

ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(МояСтрока);
ЗТ.Закрыть();

И никаких извращений...
Crazy_Max; CratosX; Dioneo; 1c_developer; andogskiy; Lapitskiy; adhocprog; davdykin; lutsiy2; leozx; New Look; ErrorEd88; 1st RUS; vlad.frost; andrewbc; +15 Ответить
7. andrewbc 293 31.05.12 12:11 Сейчас в теме
(6) mc2, шикарный вариант, именно то, что нужно. спасибо!
11. mc2 14 04.07.12 03:38 Сейчас в теме
(7) Ну вот, в 8.3.1 без режима совместимости с 8.2.16, этот вариант работать больше не будет! Разработчики вместо того, чтобы делать то,что надо, делают то что не надо! Теперь извращения принимаются.
13. mc2 14 04.07.12 14:50 Сейчас в теме
(7) нашел новый способ, который годится и для 8.3:

ЗТ = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ЗТ.Закрыть();
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(Данные);
ЗТ.Закрыть();
kn8603; and_r; CratosX; bearman; KPAMOP; Gureev; krv2k; davdykin; dour-dead; BigB; ErrorEd88; andrewbc; +12 Ответить
14. andrewbc 293 04.07.12 15:18 Сейчас в теме
(13) mc2, долго смеялся. Действительно, извращения принимаются. Как так удается находить таких блох? За терпение и находчивость - однозначный +.
16. 1st RUS 81 07.11.12 18:25 Сейчас в теме
(6) mc2,

Попробовал твой метод, и выяснил, что за вредные символы отвечает параметр "Дописывать" в конструкторе "ЗаписьТекста"

в общем получилось так:

УдалитьФайлы(имяФайлаОтправки); это да, это обязательно
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.UTF8,,Истина,Символы.ПС);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""goods.xml""");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: text/xml");
ЗаписьТекста.ЗаписатьСтроку("");
и ниже пишем содержимое XML файла

СПАСИБО
ShinyButt; sergsqr; xzorkiix; Жолтокнижниг; +4 Ответить
18. mc2 14 08.11.12 00:17 Сейчас в теме
(16) 1st RUS, Посмотрите пожалуйста (13) пост этой темы, т.к. то, что было написано в (6) не работает в 8.3.
22. xzorkiix 32 04.06.14 11:41 Сейчас в теме
(16) 1st RUS, спасибо за

ЗаписьТекста = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.UTF8,,Истина,Символы.ПС); 


то что надо!
27. andogskiy 10.03.17 16:47 Сейчас в теме
35. fixin 4089 08.04.21 13:21 Сейчас в теме
(6) не работает через Запись Текста, добавляет.
Заюзал вариант в (3), спасибо.
9. Serj1C 480 31.05.12 12:50 Сейчас в теме
(9) тут http://infostart.ru/public/137969/ тоже неплохо описан процесс записи произвольных данных в файл
10. andrewbc 293 31.05.12 13:44 Сейчас в теме
19. Alex1c 19 10.10.13 16:09 Сейчас в теме
Писал обработку для хеширования по ГОСТ с помощью стороннего EXE. Программка работала через командную строку. Необходимо было указать ей путь к файлу с данными на вход. Она генерила выходной файл с хешем.
Поимел проблему. У меня был тестовый файл и файл сгенеренный 1С, с виду абсолютно одинаковые. Разница в размере в 2 байта. Хеш программа выдавала разный. Оказалось что по умолчанию 1С указывается символ перевода строки и при создании файла и при добавлении строки. Указал в обоих местах в качестве символа "" и все пошло. Использовал много идей из этого поста. Возможно кому то будет полезен полный код.

Функция ПолучитьХЭШГОСТ(СтрокаНаВход)


// очистили входящий файл
УдалитьФайлы(КаталогВременныхФайлов()+"in.txt");
ТекстIn = Новый ЗаписьТекста(КаталогВременныхФайлов()+"in.txt", КодировкаТекста.UTF8,"", Ложь,);
ТекстIn.ЗаписатьСтроку(Строка(СокрЛП(ВРЕГ(ВходящиеДанные))));
ТекстIn.Закрыть();

// обрезаем ВОМ
ОБ_ДД=Новый ДвоичныеДанные(КаталогВременныхФайлов()+"in.txt");
Стр_Base64=Base64Строка(ОБ_ДД);
ОБ_ДД=Base64Значение(Сред(Стр_Base64,5));
ОБ_ДД.Записать(КаталогВременныхФайлов()+"in.txt");

// очистили выходной файл
УдалитьФайлы(КаталогВременныхФайлов()+"out.txt");
ТекстOut = Новый ЗаписьТекста(КаталогВременныхФайлов()+"out.txt", КодировкаТекста.UTF8,,Ложь,);
ТекстOut.Закрыть();

//запустили приложение хеширования
ЗапуститьПриложение(Строка(ИмяФайла)+" --gost-cryptopro "+КаталогВременныхФайлов()+"in.txt"+" "+"--output="+КаталогВременныхФайлов()+"out.txt",,Истина,);

//прочитали из выходного файла результат
Текст = Новый ЧтениеТекста(КаталогВременныхФайлов()+"out.txt", КодировкаТекста.UTF8);
Стр = Текст.ПрочитатьСтроку(""); //при создании файла перевод строки убрали,при чтении тоже убрали, то есть читаем весь файл как строку

Стр = СтрЗаменить(Стр,Строка(КаталогВременныхФайлов()+"in.txt"),"");

РезультатХеширования = Врег(Стр);

Возврат РезультатХеширования;

КонецФункции
20. ErrorEd88 52 24.01.14 22:29 Сейчас в теме
Кодировка UTF-8 без BOM называется "CESU-8". Подсказали.
user1373370; rullin; v_den_v; xvchk; lehis_S; Kazey; maxtomsk; kabanoff; Symbiat; Prad2002; tormozit; formica32; nomadon; Dioneo; Gisborn; vasiliy_b; simgo83; Suxar; Gureev; mc2; malikov_pro; Никс; h00k; rysha; stvorl; 1v7; Valet; sergsqr; AndroidK; DitriX; inhuman; Enot; krv2k; dmitryafanasyev91; DrBlack; Широкий; PolAlex2; Aleksey.Bochkov; BigB; adhocprog; deaddy64; Xephone; ilya4; +43 Ответить
21. andrewks 1313 25.01.14 07:25 Сейчас в теме
(20) ErrorEd88, да ну! и где же об этом написано в описании стандарта? http://www.unicode.org/reports/tr26/
23. Xephone 01.10.14 05:01 Сейчас в теме
24. DrBlack 21 27.08.15 12:33 Сейчас в теме
(20) ErrorEd88, Спасибо!
Информация верная!!! :)
25. dmitryafanasyev91 13.10.15 11:48 Сейчас в теме
26. loky12 10.08.16 12:17 Сейчас в теме
(20) ErrorEd88,
Спасибо помог, очень выручило при склейке csv созданных в фоновых в многопоточной обработке.
28. aaa_pol 31.01.18 23:52 Сейчас в теме
Писал выгрузку на сайт через файл .csv столкнулся с данной проблемой. Перепробовал несколько способов из указанных выше. Нашел для себя наиболее оптимальный следующий метод, который меняет кодировку в уже готовом, ранее сформированном файле .csv

////создаем сам файл
СписокЭкспорт = Новый ТекстовыйДокумент;
СписокЭкспорт.ДобавитьСтроку(ПерваяСтрокаФайла);  ////в цикле добавляем все что надо
СписокЭкспорт.Записать(ИмяФайлаЭкспортаCSV,КодировкаТекста.UTF8);  //// Где "ИмяФайлаЭкспортаCSV" полный путь к файлу

////меняем в готовом файле кодировку "с BOM" на "без BOM"
КонвертируемыйФайл = Новый ДвоичныеДанные(ИмяФайлаЭкспортаCSV);
Строка64=Base64Строка(КонвертируемыйФайл);
Строка64=Прав(Строка64,СтрДлина(Строка64)-4);
ДляЗаписиВФайл=Base64Значение(Строка64);
ДляЗаписиВФайл.Записать(ИмяФайлаЭкспортаCSV);
Показать
29. userGJ 07.05.18 12:44 Сейчас в теме
Варианты с сохранением в промежуточный файл изначально кривое решение. В 20 разумное решение с указанием другой кодировки.
30. Stas84 22.06.18 10:17 Сейчас в теме
20 -> то что нужно, пробуйте указать кодировку в наглую. Вместо КодировкаТекста.UTF8 ->"CESU-8"
Например:
Запрос.УстановитьТелоИзСтроки(ТекстPOSTЗапроса, "CESU-8");
pahich; user743891; +2 Ответить
31. sultbec 8 07.08.19 22:36 Сейчас в теме
(30) в типовой нашел такой код:
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
32. user852614 09.08.19 10:28 Сейчас в теме
Так решил проблему:
	
        ФП = Новый ФайловыйПоток(ИмяФайлаИсходного,РежимОткрытияФайла.СоздатьНовый,ДоступКФайлу.ЧтениеИЗапись);
	Текст = Новый ЗаписьТекста(ФП,,, Истина, Ложь);//Последний параметр самый важный
	Текст.Записать(СтрокаДанных);
	Текст.Закрыть();
	ФП.Закрыть();
qSergey; dock; +2 Ответить
33. user852614 12.08.19 11:26 Сейчас в теме
(32)
Текст = Новый ЗаписьТекста(ФП,КодировкаТекста.UTF8,, , Ложь);//Предпоследний параметр не нужен, надо так ;)
34. dock 43 30.05.20 04:33 Сейчас в теме
(33) Да и последний не нужен :)
<ЗаписатьBOM> (необязательный)
Тип: Булево.
Если в начало потока требуется записать метку порядка байтов (BOM) для используемой кодировки текста, то данный параметр должен иметь значение Истина.
Значение по умолчанию: Ложь.
36. burni4 77 29.06.21 14:28 Сейчас в теме
ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.УстановитьТекст(ТекстКомандногоФайла);
	ТекстовыйДокумент.Записать(ПолноеИмяФайла, "cp866");


установил кодировку cp866 и все взлетело без танцев с бубнами
Оставьте свое сообщение
Вопросы с вознаграждением
Вакансии
Программист 1С
Новосибирск
зарплата от 100 000 руб.
Полный день

Программист 1С: ЗУП
Чита
зарплата от 110 000 руб. до 150 000 руб.
Полный день

Разработчик 1C: ERP (Блоки: Снабжение, закупки, склад; Финансы и казначейство)
Чита
зарплата от 110 000 руб. до 150 000 руб.
Полный день

Консультант 1С
Нижний Новгород
зарплата от 55 000 руб. до 100 000 руб.
Полный день

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