|
v7: Слишком долго происходит преобразование строки в UTF8 | ☑ | ||
---|---|---|---|---|
0
zenon46
02.03.22
✎
19:01
|
Доброго дня!
Понадобилось из 7.7 сделать выгрузку на сайт на битриксе, разрабы запросили в формате json, сделать сделал, но преобразование в строку в формате UTF8 занимает слишком много времени. Вот по такому алгоритму, строка длиной 6.5млн символов, обрабатывается минут 40, что очень долго ( Длина=СтрДлина(Стр); Итог=""; Для Н=1 По Длина Цикл Знак=Сред(Стр,Н,1); Код=КодСимв(Знак); Если Код<128 Тогда Итог=Итог+Знак; Иначе Если (Код>=КодСимв("А"))И(Код<=КодСимв("п")) Тогда Итог=Итог+Симв(208)+Симв(144+Код-КодСимв("А")); ИначеЕсли (Код>=КодСимв("р"))И(Код<=КодСимв("я")) Тогда Итог=Итог+Симв(209)+Симв(128+Код-КодСимв("р")); ИначеЕсли (Знак="ё") Тогда Итог=Итог+Симв(209)+Симв(145); ИначеЕсли (Знак="Ё") Тогда Итог=Итог+Симв(208)+Симв(129); КонецЕсли; КонецЕсли; КонецЦикла; |
|||
1
Garikk
02.03.22
✎
19:13
|
вот даже если не вникать в то что это 7.7, надо выкинуть все КодСимв для константных значений, это уже ускорит работу, также Симв(код) - с фиксированными кодами также переделать на константы
это просто с точки зрения программинга улучшит производительность |
|||
2
NorthWind
02.03.22
✎
19:39
|
(0) Наскок я помню, через ADO Stream можно было забубенить и быстро работает.
Вот пример гуглится https://forum.script-coding.com/viewtopic.php?id=997 |
|||
3
NorthWind
02.03.22
✎
19:42
|
(1) на скрипте 6 лямов символов строки даже если просто выбирать в переменную по одному и больше ничего не делать - уже, по-моему, долго выйдет. На машинном коде должна быть такая операция.
|
|||
4
acanta
02.03.22
✎
20:00
|
А Стрзаменить это цикл в цикле?
|
|||
5
АгентБезопасной Нацио
02.03.22
✎
20:06
|
||||
6
NorthWind
02.03.22
✎
20:09
|
(4) нужно смотреть реализацию. Но замена тормозная сама по себе еще и потому, что новая строка может быть длиннее прежней, соответственно, нужно выделять кучу под новую строку и, если не повезет, то много раз.
|
|||
7
NorthWind
02.03.22
✎
20:12
|
(5) "теперь мы временно без", как пел БГ. Архив временно отключён :)
|
|||
8
АгентБезопасной Нацио
02.03.22
✎
20:15
|
(7) А как я туда попал?
впрочем, я ТС'у уже скинул код оттуда |
|||
9
Злопчинский
02.03.22
✎
21:15
|
//********************************************************************************************************************************
// http://www.skalnyy.com/1s-perekodirovka-fajla/ // ВОЗМОЖНЫЕ ВАРИАНТЫ КОДИРОВОК "UTF-8" "KOI8-R" "Windows-1251" "ISO-8859-5" Процедура глИзменитьКодовуюСтраницуФайла(имяФайла, исходнКодировка, нужнаяКодировка) Экспорт Если ФС.СуществуетФайл(имяФайла) = 0 Тогда Сообщить("Файл " + имяФайла + " - не найден! Изменение кодировки отменено.", "!"); Возврат; КонецЕсли; ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl"); ScrptCtrl.Language = "VBScript"; ScrptCtrl.AddCode(" |Function StrConv(Text,SourceCharset,DestCharset) | Set Stream=CreateObject(""ADODB.Stream"") | Stream.Type=2 | Stream.Mode=3 | Stream.Open | Stream.Charset=DestCharset | Stream.WriteText Text | Stream.Position=0 | Stream.Charset=SourceCharset | StrConv=Stream.ReadText |End Function | |sub ConvertCodepage( fileName, SourceCharset, DestCharset ) | set fs = CreateObject(""Scripting.FilesystemObject"") | originalText = fs.openTextFile(fileName,1).readAll() | convertedText = strConv(originalText, SourceCharset, DestCharset ) | fs.openTextFile(fileName,2,true).write(convertedText) |end sub | |"); Module = ScrptCtrl.Modules("Global"); CodeObject = Module.CodeObject; CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка); КонецПроцедуры //ИзменитьКодовуюСтраницуФайла() |
|||
10
Garikk
02.03.22
✎
22:13
|
прям кровь из глаз...писать конвертор стрингов через промежуточный файл прям девяностыми повеяло и костылями
а вот так если сделать не лучше? http://www.moretechtips.net/2008/10/convert-string-to-bytes-and-vice-versa.html |
|||
11
Злопчинский
02.03.22
✎
22:16
|
(10) я хз что там у ТС, может ему этот конвертор 100 раз в секунду надо по каналу отдавать данные и не успевает...
|
|||
12
Злопчинский
02.03.22
✎
22:17
|
ждем рабочий код для выполнения в 77 из (10) типа как в (9) ;-)
|
|||
13
Garikk
02.03.22
✎
22:18
|
(12) ну его достаточно скопипастить в (9)
p.s. мне прям щас проверить негде, если завтра тема не помрет то почекаю |
|||
14
Злопчинский
02.03.22
✎
22:34
|
(13) ок, ждемс
|
|||
15
PloAl
02.03.22
✎
23:09
|
Имхо функции конвертирования не помогут, т.к. насколько помню 7.7 код похож на вставку символов кириллицы utf8 в виде "\u1035" и.т.д.
Код какой то малопонятный, помню сам писал функцию перевода из win1251 в utf8, там все просто получилось сдвиг вроде был 848. Имхо проблема в (0) это конкатенация большой строки, и писать надо в файл не помню насколько это удобно в 7.7 получиться возможно лишних переносов строк будет много. |
|||
16
Смотрящий
03.03.22
✎
00:09
|
ТЗЗамены = СозадтьОбъект("ТаблицаЗначений);
ТЗЗамены.НоваяКолонка("Символ", "Строка", 1); ТЗЗамены.НоваяКолонка("ЗаменитьНа", "Строка"); ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "А"; ТЗЗамены.ЗаменитьНа = Симв(208) + Симв(144 + КодСимв("А") - КодСимв("А")); ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "Б"; ТЗЗамены.ЗаменитьНа = Симв(208) + Симв(144 + КодСимв("Б") - КодСимв("А")); .... ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "р"; ТЗЗамены.ЗаменитьНа = Симв(208) + Симв(128 + КодСимв("р") - КодСимв("р")); ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "с"; ТЗЗамены.ЗаменитьНа = Симв(208) + Симв(128 + КодСимв("с") - КодСимв("р")); ... ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "ё"; ТЗЗамены.ЗаменитьНа = Симв(209) + Симв(145); ТЗЗамены.НоваяСтрока(); ТЗЗамены.Символ = "Ё"; ТЗЗамены.ЗаменитьНа = Симв(208) + Симв(129); ТЗЗамены.ВыбратьСтроки(); Пока ТЗЗамены.ПолучитьСтроку() = 1 Цикл Стр = СтрЗаменить(Стр, ТЗЗамены.Символ, ТЗЗамены.ЗаменитьНа); УонецЦикла; ЗЫ. Движок 7.7 может рухнуть на какой либо итерации - не сожрет преобразование строки 6.2 мега 128 раз подряд Приходи - нарежем строку по килобайту, например |
|||
17
Chai Nic
03.03.22
✎
06:47
|
А не проще создать файл в нативной 1251 кодировке, а потом на него натравить экзешник перекодировщика?
|
|||
18
Kigo_Kigo
03.03.22
✎
08:43
|
(17) Я так и делал, только вот екзешник перекодировщика не помню какой был, Нотепад++ что ле
|
|||
19
ДедМорроз
03.03.22
✎
08:46
|
А на си написать?
Там самое главное,память правильно использовать,чтобы не было операций копирования. В остальном,запись двух байт вместо одного в память-это очень быстро. |
|||
20
1snik_d
03.03.22
✎
08:51
|
Я когда-то делал через ADODB.Stream, работало очень шустро и там необязательно использовать промежуточные файлы, можно прям в памяти фигачить
|
|||
21
1snik_d
03.03.22
✎
08:52
|
Чисто на 1С делать конвертер - это задница, медленно очень работает.
|
|||
22
NorthWind
03.03.22
✎
09:00
|
(20) стримы в памяти точно есть, но у меня нет уверенности, что существует "мостик" между семерочными строками и указателем, откуда стриму забирать-отдавать данные. Скорее всего файл будет нужен именно на этом этапе.
|
|||
23
1snik_d
03.03.22
✎
09:06
|
(22) Делал через MSScriptControl.ScriptControl, передавая туда строку из переменной 1С. Насколько помню там была единственная проблема с длинными строками
|
|||
24
1snik_d
03.03.22
✎
09:07
|
(23) Их приходилось дробить на части и кусками конвертировать
|
|||
25
NorthWind
03.03.22
✎
09:20
|
(24) ну уже хлеб...
|
|||
26
NorthWind
03.03.22
✎
09:21
|
(21) это неудивительно, скриптом посимвольно такие строки никто не дербанит, это несерьезно
|
|||
27
1snik_d
03.03.22
✎
09:47
|
(25) Даже многомегабайтные ответы от сервера обрабатывались очень шустро, сначала конвертация, потом разбор XML и все через MSScriptControl.ScriptControl с javascript функциями и ADO Stream
|
|||
28
ДедМорроз
03.03.22
✎
10:25
|
В 1с 7.7 строки однобайтовые и в кодировке windows-1251.
При передаче этой строки в любой com-объект,строка преобразуется в двухбайтовую - для этого выделяется блок памяти и делается преобразование - так как оно на машинном уровне,то мы его почти не замечаем,но доя больших строк будет критично. При записи в файл никаких преобразований нет,но есть проблемы с символом с кодом 0. Но,при чтении файла,например,через Scripting FileSystemObject происходит такое же преобразование,но при чтении каждой строки. Adodb.stream читает файл в память в буфер,используя функции чтения файла и информацию о кодировке. При преобразовании кодировок он самый быстрый,но подъем всего файла в память - часто очень критично. |
|||
29
ДедМорроз
03.03.22
✎
10:32
|
На Си из win-1251 в utf достаточно просто.
Первый проход,считаем сколько байт на каждый символ,там,насколько я помню,символ номера - тир байта,остальные со старшим битом-два. Получаем размер будущей строки-выделяем память и вперед перекодировать по таблице. |
|||
30
zenon46
03.03.22
✎
10:37
|
В памяти не получилось, предприятие просто закрывалось, пришлось делать через файл. Работает быстро.
Байт=255; СтримВход=СоздатьОбъект("ADODB.Stream"); СтримВход.Type=2; СтримВход.charset="windows-1251"; СтримВход.Open(); СтримВход.LoadFromFile(Путь+Имя); СтримВыход=СоздатьОбъект("ADODB.Stream"); СтримВыход.Type=2; СтримВыход.charset="utf-8"; СтримВыход.LineSeparator=-1; СтримВыход.Open(); Всего=СтримВход.size; Пока СтримВход.EOS=0 Цикл СтримВыход.WriteText(СтримВход.ReadText(Байт),?(Байт=-2,1,0)); Состояние("" + Формат(100 * СтримВход.position/Всего,"Ч(0)5.2")+"%"); КонецЦикла; СтримВыход.SaveToFile(Путь+Имя,2); |
|||
31
ДедМорроз
03.03.22
✎
11:24
|
Там,скорее,проблема с передачей utf-8 обратно в 1с,так как для этого строку нужно специально готовить - каждый байт из utf-8 нужно преобразовать в двухбайтовое представление согласно win-1251 to unicode.
Тогда полученная в 7.7 строка будет записана в utf-8. |
|||
32
НЕА123
03.03.22
✎
11:38
|
||||
33
zenon46
03.03.22
✎
11:57
|
(32) жаль имени файла нет, через гугл я не смог найти
|
|||
34
Злопчинский
03.03.22
✎
18:43
|
В формексе есть кодирование утф8 но только в одну сторону
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |