首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >oracle中的Base64编码与解码

oracle中的Base64编码与解码
EN

Stack Overflow用户
提问于 2010-09-27 21:34:33
回答 4查看 162.5K关注 0票数 44

如何在Oracle中对值进行Base64编码/解码?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-09-28 01:27:16

我已经实现了这一点,以便通过我的MS Exchange服务器发送西里尔文电子邮件。

代码语言:javascript
复制
function to_base64(t in varchar2) return varchar2 is
 begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
end to_base64;

试试看。

更新:经过一个小的调整后,我想出了这个,所以现在它是双向工作的:

代码语言:javascript
复制
function from_base64(t in varchar2) return varchar2 is
begin
  return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(t)));
end from_base64;

你可以查看它:

代码语言:javascript
复制
SQL> set serveroutput on
SQL> 
SQL> declare
  2    function to_base64(t in varchar2) return varchar2 is
  3    begin
  4      return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
  5    end to_base64;
  6  
  7    function from_base64(t in varchar2) return varchar2 is
  8    begin
  9      return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw    (t)));
 10    end from_base64;
 11  
 12  begin
 13    dbms_output.put_line(from_base64(to_base64('asdf')));
 14  end;
 15  /

asdf

PL/SQL procedure successfully completed

upd2:好的,这是我刚刚想出来的适用于CLOB的转换示例。试着为你的乳房解决这个问题。:)

代码语言:javascript
复制
declare

  clobOriginal     clob;
  clobInBase64     clob;
  substring        varchar2(2000);
  n                pls_integer := 0;
  substring_length pls_integer := 2000;

  function to_base64(t in varchar2) return varchar2 is
  begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
  end to_base64;

  function from_base64(t in varchar2) return varchar2 is
  begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(t)));
  end from_base64;

begin

  select clobField into clobOriginal from clobTable where id = 1;

  while true loop

    /*we substract pieces of substring_length*/
    substring := dbms_lob.substr(clobOriginal,
                                 least(substring_length, substring_length * n + 1 - length(clobOriginal)),
                                 substring_length * n + 1);  
    /*if no substring is found  - then we've reached the end of blob*/

    if substring is null then
      exit;
    end if;  

    /*convert them to base64 encoding and stack it in new clob vadriable*/
    clobInBase64 := clobInBase64 || to_base64(substring);          
    n := n + 1;  

  end loop;

  n := 0;
  clobOriginal := null;

  /*then we do the very same thing backwards - decode base64*/
  while true loop 

    substring := dbms_lob.substr(clobInBase64,
                                 least(substring_length, substring_length * n + 1 - length(clobInBase64)),
                                 substring_length * n + 1);  
    if substring is null then
      exit;
    end if;  
    clobOriginal := clobOriginal || from_base64(substring);  
    n := n + 1;  
  end loop; 

      /*and insert the data in our sample table - to ensure it's the same*/
  insert into clobTable (id, anotherClobField) values (1, clobOriginal);

end;
票数 58
EN

Stack Overflow用户

发布于 2016-11-29 03:37:38

使用utl_encode.base64_encodeutl_encode.base64_decode解决方案有一个限制,它们只能处理最多32,767个字符/字节的字符串。

如果你不得不转换更大的字符串,你将面临几个障碍。

  • BASE64_ENCODE该函数必须读取3个字节并对其进行转换。在多字节字符的情况下(例如,以UTF-8存储的öäüè€,也称为AL32UTF8),3字符不一定也是3字节。为了始终读取3个字节,你必须首先将你的CLOB转换成BLOB
  • 同样的问题也适用于BASE64_DECODE。该函数必须读取4个字节并将其转换为3个字节。这3个字节不一定也是3个,base64-- NEW_LINE (CR和/或LF)字符,每个64个字符。这样的换行符在解码时必须忽略。

考虑到所有这些,全功能的解决方案可能是这样的:

代码语言:javascript
复制
CREATE OR REPLACE FUNCTION DecodeBASE64(InBase64Char IN OUT NOCOPY CLOB) RETURN CLOB IS

    blob_loc BLOB;
    clob_trim CLOB;
    res CLOB;

    lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    warning INTEGER;
    ClobLen INTEGER := DBMS_LOB.GETLENGTH(InBase64Char);

    amount INTEGER := 1440; -- must be a whole multiple of 4
    buffer RAW(1440);
    stringBuffer VARCHAR2(1440);
    -- BASE64 characters are always simple ASCII. Thus you get never any Mulit-Byte character and having the same size as 'amount' is sufficient

BEGIN

    IF InBase64Char IS NULL OR NVL(ClobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF ClobLen<= 32000 THEN
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(InBase64Char)));
    END IF;        
    -- UTL_ENCODE.BASE64_DECODE is limited to 32k, process in chunks if bigger    

    -- Remove all NEW_LINE from base64 string
    ClobLen := DBMS_LOB.GETLENGTH(InBase64Char);
    DBMS_LOB.CREATETEMPORARY(clob_trim, TRUE);
    LOOP
        EXIT WHEN read_offset > ClobLen;
        stringBuffer := REPLACE(REPLACE(DBMS_LOB.SUBSTR(InBase64Char, amount, read_offset), CHR(13), NULL), CHR(10), NULL);
        DBMS_LOB.WRITEAPPEND(clob_trim, LENGTH(stringBuffer), stringBuffer);
        read_offset := read_offset + amount;
    END LOOP;

    read_offset := 1;
    ClobLen := DBMS_LOB.GETLENGTH(clob_trim);
    DBMS_LOB.CREATETEMPORARY(blob_loc, TRUE);
    LOOP
        EXIT WHEN read_offset > ClobLen;
        buffer := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(clob_trim, amount, read_offset)));
        DBMS_LOB.WRITEAPPEND(blob_loc, DBMS_LOB.GETLENGTH(buffer), buffer);
        read_offset := read_offset + amount;
    END LOOP;

    DBMS_LOB.CREATETEMPORARY(res, TRUE);
    DBMS_LOB.CONVERTTOCLOB(res, blob_loc, DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset,  DBMS_LOB.DEFAULT_CSID, lang_context, warning);

    DBMS_LOB.FREETEMPORARY(blob_loc);
    DBMS_LOB.FREETEMPORARY(clob_trim);
    RETURN res;    

END DecodeBASE64;




CREATE OR REPLACE FUNCTION EncodeBASE64(InClearChar IN OUT NOCOPY CLOB) RETURN CLOB IS

    dest_lob BLOB;  
    lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    warning INTEGER;
    ClobLen INTEGER := DBMS_LOB.GETLENGTH(InClearChar);

    amount INTEGER := 1440; -- must be a whole multiple of 3
    -- size of a whole multiple of 48 is beneficial to get NEW_LINE after each 64 characters 
    buffer RAW(1440);
    res CLOB := EMPTY_CLOB();

BEGIN

    IF InClearChar IS NULL OR NVL(ClobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF ClobLen <= 24000 THEN
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(InClearChar)));
    END IF;
    -- UTL_ENCODE.BASE64_ENCODE is limited to 32k/(3/4), process in chunks if bigger    

    DBMS_LOB.CREATETEMPORARY(dest_lob, TRUE);
    DBMS_LOB.CONVERTTOBLOB(dest_lob, InClearChar, DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset, DBMS_LOB.DEFAULT_CSID, lang_context, warning);
    LOOP
        EXIT WHEN read_offset >= dest_offset;
        DBMS_LOB.READ(dest_lob, amount, read_offset, buffer);
        res := res || UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(buffer));       
        read_offset := read_offset + amount;
    END LOOP;
    DBMS_LOB.FREETEMPORARY(dest_lob);
    RETURN res;

END EncodeBASE64;
票数 12
EN

Stack Overflow用户

发布于 2013-11-13 02:28:40

所有之前的帖子都是正确的。剥猫皮的方法不止一种。下面是做同样事情的另一种方法:(只需将"what_ever_you_want_to_convert“替换为您的字符串并在Oracle中运行它:

代码语言:javascript
复制
    set serveroutput on;
    DECLARE
    v_str VARCHAR2(1000);
    BEGIN
    --Create encoded value
    v_str := utl_encode.text_encode
    ('what_ever_you_want_to_convert','WE8ISO8859P1', UTL_ENCODE.BASE64);
    dbms_output.put_line(v_str);
    --Decode the value..
    v_str := utl_encode.text_decode
    (v_str,'WE8ISO8859P1', UTL_ENCODE.BASE64);
    dbms_output.put_line(v_str);
    END;
    /

source

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3804279

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档