Запись текста в кодировке UTF-8 без BOM из 1с 8.2
Комментарии
В избранное
Подписаться на ответы
Сортировка:
Древо развёрнутое
Свернуть все
если в виндах, то можно заюзать ADODB.Stream
например, так:
синтаксис в примере 7-шный, но код применим для любой версии - 7.7, 8.х, главное, чтобы доступ к объекту 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 был
(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();
УдалитьФайлы(ИсходныйФайл);
Исключение
Сообщить(ОписаниеОшибки(),СтатусСообщения.Важное);
КонецПопытки;
КонецПроцедуры
Процедура УбитьВОМ(ИсходныйФайл,РезультирующийФайл)
Попытка
файл = Новый 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();
УдалитьФайлы(ИсходныйФайл);
Исключение
Сообщить(ОписаниеОшибки(),СтатусСообщения.Важное);
КонецПопытки;
КонецПроцедуры
Еще можно провернуть такой танец с бубном (без ВК, работа в памяти, без файлов):
1) получить двоичные данные из файла (как у вас)
2) преобразуем двоичные данные в строку с помощью ЗначениеИзСтрокиВнутр
3) анализируем формат, там не сложно, удаляем лишние переносы кареток (символ 10 вроде) // при желании могу описать подробнее
4) упаковываем поток обратно, получая двоичные данные
5) записываем в файл. Профит
1) получить двоичные данные из файла (как у вас)
2) преобразуем двоичные данные в строку с помощью ЗначениеИзСтрокиВнутр
3) анализируем формат, там не сложно, удаляем лишние переносы кареток (символ 10 вроде) // при желании могу описать подробнее
4) упаковываем поток обратно, получая двоичные данные
5) записываем в файл. Профит
(2) Serj1C, не получилось сотворить такой вариант обработки:
1. при преобразовании "ЗначениеВСтрокуВнутр" 1с преобразует двоичные данные в формат base64, при этом длина строки становится больше размера иходного файла почти в полтора раза, это значит, что у нас уже текст не в кодировке UTF-8.
2. не совсем понятно: символы перевода строки (10) (возврат каретки - 13) обязательно удалять? а если это UTF-ный символ с кодом 10?
3. каким образом "упаковать поток обратно"? у объекта "ДвоичныеДанные" только 2 метода - "Размер()" и "Записать(ИмяФайла").
4. как записать в файл результат?
пробовал еще такой вариант:
бин = Новый ДвоичныеДанные(ИсходныйФайл);
бинСтрока = Base64Строка(бин);
новаяБинСтрока = Сред(бинСтрока,4);
бин = Base64Значение(новаяБинСтрока);
бин.Записать(РезультирующийФайл);
но там вообще ерунда получается.
может, примерчик рабочий есть?
1. при преобразовании "ЗначениеВСтрокуВнутр" 1с преобразует двоичные данные в формат base64, при этом длина строки становится больше размера иходного файла почти в полтора раза, это значит, что у нас уже текст не в кодировке UTF-8.
2. не совсем понятно: символы перевода строки (10) (возврат каретки - 13) обязательно удалять? а если это UTF-ный символ с кодом 10?
3. каким образом "упаковать поток обратно"? у объекта "ДвоичныеДанные" только 2 метода - "Размер()" и "Записать(ИмяФайла").
4. как записать в файл результат?
пробовал еще такой вариант:
бин = Новый ДвоичныеДанные(ИсходныйФайл);
бинСтрока = Base64Строка(бин);
новаяБинСтрока = Сред(бинСтрока,4);
бин = Base64Значение(новаяБинСтрока);
бин.Записать(РезультирующийФайл);
но там вообще ерунда получается.
может, примерчик рабочий есть?
(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, Истина)+"}
|}
|}";
д = ЗначениеИзСтрокиВнутр(норм);
д.Записать(ф);
Сообщить(д);
КонецПроцедуры
Показать
(4) Собственно так и делаю.
Только у вас ошибка.
Вот рабочий код:
Использовал вВизуализация журнала регистрации Gource
В 8.3 не проверял еще, но думаю должно сработать.
Только у вас ошибка.
Вот рабочий код:
файлЛог=ПолучитьИмяВременногоФайла(".txt");
Текст.Записать(файлЛог);
// теперь нужно получить файл без BOM
ОБ_ДД=Новый ДвоичныеДанные(файлЛог);
Стр_Base64=Base64Строка(ОБ_ДД);
ОБ_ДД=Base64Значение(Сред(Стр_Base64,5));
ОБ_ДД.Записать(файлЛог);
Использовал в
В 8.3 не проверял еще, но думаю должно сработать.
Тоже долго мучился пока нашел как это сделать для записи текстовых файлов средствами 1С:
УдалитьФайлы(ИмяФайла); // надо убедиться, что файл не существует, т.к. если он существует, то данные добавятся в конец файла
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(МояСтрока);
ЗТ.Закрыть();
И никаких извращений...
УдалитьФайлы(ИмяФайла); // надо убедиться, что файл не существует, т.к. если он существует, то данные добавятся в конец файла
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(МояСтрока);
ЗТ.Закрыть();
И никаких извращений...
(7) нашел новый способ, который годится и для 8.3:
ЗТ = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ЗТ.Закрыть();
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(Данные);
ЗТ.Закрыть();
ЗТ = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
ЗТ.Закрыть();
ЗТ = Новый ЗаписьТекста(ИмяФайла,,, Истина, Символы.ПС);
ЗТ.Записать(Данные);
ЗТ.Закрыть();
(6) mc2,
Попробовал твой метод, и выяснил, что за вредные символы отвечает параметр "Дописывать" в конструкторе "ЗаписьТекста"
в общем получилось так:
УдалитьФайлы(имяФайлаОтправки); это да, это обязательно
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.UTF8,,Истина,Символы.ПС);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""goods.xml""");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: text/xml");
ЗаписьТекста.ЗаписатьСтроку("");
и ниже пишем содержимое XML файла
СПАСИБО
Попробовал твой метод, и выяснил, что за вредные символы отвечает параметр "Дописывать" в конструкторе "ЗаписьТекста"
в общем получилось так:
УдалитьФайлы(имяФайлаОтправки); это да, это обязательно
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.UTF8,,Истина,Символы.ПС);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""goods.xml""");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: text/xml");
ЗаписьТекста.ЗаписатьСтроку("");
и ниже пишем содержимое XML файла
СПАСИБО
(9) тут http://infostart.ru/public/137969/ тоже неплохо описан процесс записи произвольных данных в файл
Писал обработку для хеширования по ГОСТ с помощью стороннего 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"),"");
РезультатХеширования = Врег(Стр);
Возврат РезультатХеширования;
КонецФункции
Поимел проблему. У меня был тестовый файл и файл сгенеренный 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"),"");
РезультатХеширования = Врег(Стр);
Возврат РезультатХеширования;
КонецФункции
Кодировка UTF-8 без BOM называется "CESU-8". Подсказали.
user1338849; ddd_77; Zixxx; MaZaHacKa_13; user906806; 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;
+48
–
Ответить
(20) ErrorEd88, да ну! и где же об этом написано в описании стандарта? http://www.unicode.org/reports/tr26/
Писал выгрузку на сайт через файл .csv столкнулся с данной проблемой. Перепробовал несколько способов из указанных выше. Нашел для себя наиболее оптимальный следующий метод, который меняет кодировку в уже готовом, ранее сформированном файле .csv
////создаем сам файл
СписокЭкспорт = Новый ТекстовыйДокумент;
СписокЭкспорт.ДобавитьСтроку(ПерваяСтрокаФайла); ////в цикле добавляем все что надо
СписокЭкспорт.Записать(ИмяФайлаЭкспортаCSV,КодировкаТекста.UTF8); //// Где "ИмяФайлаЭкспортаCSV" полный путь к файлу
////меняем в готовом файле кодировку "с BOM" на "без BOM"
КонвертируемыйФайл = Новый ДвоичныеДанные(ИмяФайлаЭкспортаCSV);
Строка64=Base64Строка(КонвертируемыйФайл);
Строка64=Прав(Строка64,СтрДлина(Строка64)-4);
ДляЗаписиВФайл=Base64Значение(Строка64);
ДляЗаписиВФайл.Записать(ИмяФайлаЭкспортаCSV);
Показать
Так решил проблему:
ФП = Новый ФайловыйПоток(ИмяФайлаИсходного,РежимОткрытияФайла.СоздатьНовый,ДоступКФайлу.ЧтениеИЗапись);
Текст = Новый ЗаписьТекста(ФП,,, Истина, Ложь);//Последний параметр самый важный
Текст.Записать(СтрокаДанных);
Текст.Закрыть();
ФП.Закрыть();
Получилось так: вместо
Надо через поток вот так
ВременныйФайл = Новый ЗаписьТекста(ИмяФайла);
ВременныйФайл.Записать(ТекстJSON);
ВременныйФайл.Закрыть();
Надо через поток вот так
Тело = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(Тело);
ЗаписьДанных.ЗаписатьСтроку(ТекстJSON);
ЗаписьДанных.Закрыть();
ДанныеТела = Тело.ЗакрытьИПолучитьДвоичныеДанные();
ДанныеТела.Записать(ИмяФайла);
Показать