Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Oracle base64 FRC version? / 17 сообщений из 17, страница 1 из 1
15.10.2018, 08:52
    #39717389
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Заметил я одну странную вещь.
UTL_ENCODE.base64_encode кодирует с переносами строк CRLF через каждые 65 символов, что соответствует RFC 2045.
Но при этом парная ей функция
UTL_ENCODE.base64_decode
Не может правильно обработать
Вывод своей же кодирующей сестры - близняшки.
Ей нужно подавать на вход без пробелов.

Собственно вопро: как так?
Или я что-то не заметил в особенностях их использования?
Ну ладно, я. Но ведь и многие другие вовсю колхозят и велосипедят
на тему удаления переносов строк:
Base64
...
Рейтинг: 0 / 0
15.10.2018, 09:11
    #39717395
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
ART-CODEUTL_ENCODE.base64_decode
Не может правильно обработать
Вывод своей же кодирующей сестры - близняшки
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select utl_raw.length(utl_encode.base64_decode(enc)) l, 
       utl_raw.substr(enc, 64, 4) crlf,
       utl_raw.cast_to_varchar2(enc) s
from (select utl_encode.base64_encode(utl_raw.copies('41', 200)) enc from dual);

         L CRLF     S                                                                
---------- -------- -----------------------------------------------------------------
       200 420D0A51 QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB 
                    QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB 
                    QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB 
                    QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB 
                    QUFBQUFBQUE=                                                     
                                               
...
Рейтинг: 0 / 0
15.10.2018, 09:26
    #39717400
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
-2-,
Спасибо, подогнать решение под ответ я могу.
Выкусывать по одной строке, конечно можно.
Но кодирующая функция умеет давать на выходе сразу несколько строк.
Значит, и декодирующая должна уметь так же: не по одной строке.

В статье, на которую я привел ссылку какраз критикуется такой построчный метод как медленный.
...
Рейтинг: 0 / 0
15.10.2018, 10:20
    #39717412
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
ART-CODEСпасибо, подогнать решение под ответ я могу.Тогда приведи пример, подтверждающий то, на что я отвечал:ART-CODEUTL_ENCODE.base64_decode
Не может правильно обработать
Вывод своей же кодирующей сестры - близняшки

ART-CODEВ статье, на которую я привел ссылку какраз критикуется такой построчный метод как медленный.Это не проблема "алгоритма", а вопрос размерности raw. Если объем кодированных данных больше 32767, то приходится резать так или иначе.
...
Рейтинг: 0 / 0
15.10.2018, 11:30
    #39717458
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
В целом, я исхожу из того, что
кодирует по RFC 2045,
Но декодирует по RFC 4648

Вот мое "творение", с учетом этого утверждения.
Сейчас тестирую.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
CREATE OR REPLACE PROCEDURE decode_base64_NOCOPY ( 
                                                  p_clob_in IN OUT NOCOPY CLOB,  -- ЧТО ДЕКОДИРОВАТЬ 
                                                  p_blob_in IN OUT NOCOPY BLOB   -- КУДА ДЕКОДИРОВАТЬ  
                                                  ) -- (ВСЕ ОБЬЕКТЫ СОЗДАЮТСЯ ЗАРАНЕЕ !!!) 
IS 
   v_offset           INTEGER; 
   v_buffer_size      BINARY_INTEGER := 23808; 
   v_buffer_varchar   VARCHAR2 (32767); 
   v_buffer_raw       RAW (32767); 
   v_MaxIN NUMBER := NVL(DBMS_LOB.getlength (p_clob_in),0) ; 
   -- создаем из входного CLOB, соответствующего RFC2045 (с переносами строк) - внутренний CLOB, соответствующий RFC4648 (без переносов) 
   v_Clb_RFC4648 CLOB;   -- этот обьект и будем декодировать 
   v_ControlStr varchar2(100);   -- проверочная строка 
BEGIN 
   IF p_clob_in IS NULL or v_MaxIN=0  -- ничего нет, ничего не делаем 
   THEN 
      RETURN; 
   END IF; 
    
 -- проверим - нужно ли удалять CRLF из входящего CLOB: 
 /* 
 RFC 2045  
 Encoded lines must not be longer than 76 characters, not counting the trailing CRLF.  
 If longer lines are found in incoming, encoded data, a robust implementation might nevertheless decode the lines,  
 and might report the erroneous encoding to the user.  
 */ 
  
 -- берем тестовую строку для определения версии RFC входящего обьекта  
 v_ControlStr:=DBMS_LOB.SubStr(p_clob_in,(case when v_MaxIN<100 then v_MaxIN else 100 end),1); 
    if (instr(v_ControlStr,CHR(10))>0 or instr(v_ControlStr,CHR(13))>0)  
     then 
       DBMS_LOB.createtemporary (v_Clb_RFC4648, TRUE);   
       v_offset := 1;      
       LOOP EXIT WHEN v_offset >= v_MaxIN;  -- перезапишем входящие данные во внутренний обьект без переносов строк 
            v_buffer_varchar:=Replace(Replace(DBMS_LOB.SubStr(p_clob_in,v_buffer_size,v_offset), CHR(10),''), CHR(13),'');  
            DBMS_LOB.writeappend(v_Clb_RFC4648,DBMS_LOB.GetLength(v_buffer_varchar),v_buffer_varchar); 
            v_offset := v_offset + v_buffer_size; 
       END LOOP;      
   else 
      v_Clb_RFC4648:= p_clob_in;  -- ничего изменять не надо.   
   end if; 
    
   -- Теперь основной процесс декодирования по RFC4648 
       v_MaxIN :=DBMS_LOB.getlength (v_Clb_RFC4648); 
       v_offset := 1; 
       LOOP EXIT WHEN v_offset >= v_MaxIN; 
            -- возьмем кусок строки, размером, кратным 4  
            v_buffer_varchar:= DBMS_LOB.SubStr(v_Clb_RFC4648,v_buffer_size,v_offset); 
            -- теперь можно конвертировать 
            v_buffer_raw := UTL_RAW.cast_to_raw (v_buffer_varchar); 
            v_buffer_raw := UTL_ENCODE.base64_decode (v_buffer_raw); 
            DBMS_LOB.writeappend (p_blob_in, UTL_RAW.LENGTH (v_buffer_raw), v_buffer_raw); 
            v_offset := v_offset + v_buffer_size; 
       END LOOP; 
 
-- удалять обьекты не нужно! 
END decode_base64_NOCOPY; 

...
Рейтинг: 0 / 0
15.10.2018, 12:01
    #39717486
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Ой, забыл:
report the erroneous encoding to the user
Надо проверять и ругаться, если есть переносы далее 76, но это что же получается?
Нельзя ограничиться контрольной строкой, надо ве проверять?
Накладно, однако.
...
Рейтинг: 0 / 0
15.10.2018, 13:55
    #39717630
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Короче, в основном цикле декодирования делаем
проверку:
Код: plsql
1.
2.
3.
4.
if regexp_instr(v_buffer_varchar,'['||chr(10)||'|'||chr(13)||']')>0
Then
Raise_application_error(-2064,'Base64 decoder by RFC4648 - not supported CRLF');
end if;
...
Рейтинг: 0 / 0
15.10.2018, 14:20
    #39717650
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Так пример-то
ART-CODE"UTL_ENCODE.base64_decode
Не может правильно обработать
Вывод своей же кодирующей сестры - близняшки."
будет?
...
Рейтинг: 0 / 0
15.10.2018, 14:41
    #39717665
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Ок, вечером.
Впрочем, если нет желания ждать, то достаточно из моего декодера выкинуть цикл удаления переносов строк, чтобы получить на выходе битый файл, который ранее был щакодирован оракловой энкоде.
...
Рейтинг: 0 / 0
15.10.2018, 15:39
    #39717704
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
ART-CODEполучить на выходе битый файл, который ранее был щакодирован оракловой энкоде.
Вам уже привели пример, демонстрирующий совместимость
21703864
Контрпримера пока нет
...
Рейтинг: 0 / 0
15.10.2018, 15:55
    #39717716
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Ясно, похоже, что в парном режиме они работают, но только для небольших размеров.

Когда начинается нарезка фрагментов больших файлов, то все становится плохо.
Кажется, я оказался одновременно и не прав в теории, но все-же прав в реализации - для больших файлов.

Потестирую еще.
...
Рейтинг: 0 / 0
15.10.2018, 17:09
    #39717763
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
ART-CODEКогда начинается нарезка фрагментов больших файлов
Нарезать надо не абы как - и все получится.
...
Рейтинг: 0 / 0
15.10.2018, 17:31
    #39717776
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
ART-CODEКогда начинается нарезка фрагментов больших файлов, то все становится плохо.При энкодировании резать кратно выходным строкам - 48 входных байт.
При декодировании достаточно искать crlf от конца предыдущего буфера плюс 32767 минус запас на размер строки, например, =32000. Удалять crlf не нужно. Если crlf отсутствует, можно читать кратно 4 байтам.
...
Рейтинг: 0 / 0
15.10.2018, 18:20
    #39717793
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
-2-Если crlf отсутствует, можно читать кратно 4 байтам.
Проще читать из лоба кратно 4 байтам.
Если буфер не полон (вычитано меньше, чем запрошено) - декодировать.
Если буфер полон "под крышку" - то пробовать обрезать хвост поиском crlf справа (с соответствующей корректировкой смещения lob), при отсутствии хвоста - просто декодировать.
...
Рейтинг: 0 / 0
16.10.2018, 00:45
    #39717872
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Да, огромное спасибо, все работает :)

Я, видимо, очень спешил, и даже ту статью невнимательно прочитал. ("по верхам")
Подправил свой код, и успешно раскодировал с переносами строк.
Правда, там есть допущение о том, что размер буфера во входящем CLOB - не меняется,
и переносы строк всегда на том же месте, как и в первой строке.
И не уверен, что правильно поступил с проверкой на кратность 4.

И еще я заменил определение размера буфера - в статье для этого применялся Instr ко всему CLOB, а
я побоялся так делать для больших файлов, на всякий случай забираю первые 100 символов и уже там ищу перенос строки.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
CREATE OR REPLACE PROCEDURE decode_base64_NOCOPY ( 
                                                  p_clob_in IN OUT NOCOPY CLOB,  -- ЧТО ДЕКОДИРОВАТЬ 
                                                  p_blob_in IN OUT NOCOPY BLOB   -- КУДА ДЕКОДИРОВАТЬ  
                                                  ) -- (ВСЕ ОБЬЕКТЫ СОЗДАЮТСЯ ЗАРАНЕЕ !!!) 
IS 
   v_offset           INTEGER  :=1; 
   v_buffer_size      BINARY_INTEGER; 
   v_buffer_varchar   VARCHAR2 (32767); 
   v_buffer_raw       RAW (32767); 
   v_MaxIN NUMBER := NVL(DBMS_LOB.getlength (p_clob_in),0) ; 

BEGIN 
   IF p_clob_in IS NULL or v_MaxIN=0  -- ничего нет, ничего не делаем 
   THEN 
      RETURN; 
   END IF; 
    
 v_buffer_size:=regexp_instr(DBMS_LOB.SubStr(p_clob_in,(case when v_MaxIN<100 then v_MaxIN else 100 end),1),'['||chr(10)||'|'||chr(13)||']')-1;
 v_buffer_size:= case when v_buffer_size<0 then 32760 else floor(32767/v_buffer_size)*v_buffer_size end;

if mod(v_buffer_size,4)>0
then
 Raise_application_error(-20064,'Base64 decoder must have buffer size divided by 4, instead of '||to_char(v_buffer_size));
end if;
    
   -- Теперь основной процесс декодирования
       LOOP EXIT WHEN v_offset >= v_MaxIN; 
            -- возьмем кусок строки, размером, кратным 4  
            v_buffer_varchar:= DBMS_LOB.SubStr(p_clob_in,v_buffer_size,v_offset); 
            -- теперь можно конвертировать 
            v_buffer_raw := UTL_RAW.cast_to_raw (v_buffer_varchar); 
            v_buffer_raw := UTL_ENCODE.base64_decode (v_buffer_raw); 
            DBMS_LOB.writeappend (p_blob_in, UTL_RAW.LENGTH (v_buffer_raw), v_buffer_raw); 
            v_offset := v_offset + v_buffer_size; 
       END LOOP; 
 
-- удалять обьекты не нужно! 
END decode_base64_NOCOPY; 

...
Рейтинг: 0 / 0
16.10.2018, 20:04
    #39718417
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Вот же, елки-палки!
Я понял, наконец, в чем была проблема.

Oracle 11g и 12
По-разному делают энкоде.
11- пишет переносы строк внутри многострочного блока base64, но не пишет их в конце, и их нужно руками добавлять.
А 12 оракл кодирует нормально, и переносы строк есть всегда.

Поэтому мои опыты по раскодированию были настолько неудачны, что я не верил в возможность раскодировать.

А закодированный файл - как оказалось, был поврежден.
При этом, внешние программы, с которыми я сравнивал результат - о повреждении не сообщали, и успешно раскодировали.

Да что там, внешние программы, даже моя первая процедура декодирования из этого топика проблем не замечала, и хорошо раскодировала.

Какие кровавые грабли!
...
Рейтинг: 0 / 0
17.10.2018, 11:14
    #39718626
ART-CODE
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Oracle base64 FRC version?
Опечатка, все наоборот:
12с - мне закодировал без переноса строки в конце блока, а
11g - вернул с переносом строки в конце.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Oracle base64 FRC version? / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]