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

Собственно вопро: как так?
Или я что-то не заметил в особенностях их использования?
Ну ладно, я. Но ведь и многие другие вовсю колхозят и велосипедят
на тему удаления переносов строк:
Base64
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717395
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Oracle base64 FRC version?
    #39717400
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-,
Спасибо, подогнать решение под ответ я могу.
Выкусывать по одной строке, конечно можно.
Но кодирующая функция умеет давать на выходе сразу несколько строк.
Значит, и декодирующая должна уметь так же: не по одной строке.

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

ART-CODEВ статье, на которую я привел ссылку какраз критикуется такой построчный метод как медленный.Это не проблема "алгоритма", а вопрос размерности raw. Если объем кодированных данных больше 32767, то приходится резать так или иначе.
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717458
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В целом, я исхожу из того, что
кодирует по 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
Oracle base64 FRC version?
    #39717486
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ой, забыл:
report the erroneous encoding to the user
Надо проверять и ругаться, если есть переносы далее 76, но это что же получается?
Нельзя ограничиться контрольной строкой, надо ве проверять?
Накладно, однако.
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717630
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче, в основном цикле декодирования делаем
проверку:
Код: 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
Oracle base64 FRC version?
    #39717650
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так пример-то
ART-CODE"UTL_ENCODE.base64_decode
Не может правильно обработать
Вывод своей же кодирующей сестры - близняшки."
будет?
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717665
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ок, вечером.
Впрочем, если нет желания ждать, то достаточно из моего декодера выкинуть цикл удаления переносов строк, чтобы получить на выходе битый файл, который ранее был щакодирован оракловой энкоде.
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717704
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ART-CODEполучить на выходе битый файл, который ранее был щакодирован оракловой энкоде.
Вам уже привели пример, демонстрирующий совместимость
21703864
Контрпримера пока нет
...
Рейтинг: 0 / 0
Oracle base64 FRC version?
    #39717716
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ясно, похоже, что в парном режиме они работают, но только для небольших размеров.

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

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

Я, видимо, очень спешил, и даже ту статью невнимательно прочитал. ("по верхам")
Подправил свой код, и успешно раскодировал с переносами строк.
Правда, там есть допущение о том, что размер буфера во входящем 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
Oracle base64 FRC version?
    #39718417
ART-CODE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот же, елки-палки!
Я понял, наконец, в чем была проблема.

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

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

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

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

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


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