不同字符集的 utl_raw.cast_to_varchar2 行为
我正在使用一个名为 pl_fpdf
的 Oracle pl/sql pdf 包来动态创建 pdf(这是我目前必须使用的)。它适用于一个数据库,但不适用于另一个数据库。我相信在尝试将图像二进制文件转换为 ascii (base64) 时,我已将问题范围缩小到字符集和 utl_raw.cast_to_varchar2 行为的差异。
工作字符集是 WE8MSWIN1252 ,另一个是 AL32UTF8 (现在似乎更常见)
我的问题是,如何制作 utl_raw.cast_to_varchar2 对 AL32UTF8
的行为与对 WE8MSWIN1252
的行为相同,因此生成的 base64 图像数据是正确的?
这是我认为问题所在的代码。如果我在这里完全错了,请告诉我。
procedure p_putstream(pData in out NOCOPY blob) is
offset integer := 1;
lv_content_length number := dbms_lob.getlength(pdata);
buf_size integer := 2000;
buf raw(2000);
begin
p_out('stream');
-- read the blob and put it in small pieces in a varchar
while offset < lv_content_length loop
dbms_lob.read(pData,buf_size,offset,buf);
p_out(utl_raw.cast_to_varchar2(buf), false);
offset := offset + buf_size;
end loop;
-- put a CRLF at te end of the blob
p_out(chr(10), false);
p_out('endstream');
exception
when others then
error('p_putstream : '||sqlerrm);
end p_putstream;
I'm using a pdf package for oracle pl/sql called pl_fpdf
to create pdfs on the fly (this is what I have to use at the moment). It works on one database, but doesn't work on the other. I believe I've narrowed down the issue to a difference in character set and the behavior of utl_raw.cast_to_varchar2
when trying to convert image binary to ascii (base64).
The working character set is WE8MSWIN1252
, and the other is AL32UTF8
(seems to be much more common these days)
My question is, how do I make utl_raw.cast_to_varchar2
behave the same with AL32UTF8
as it does with WE8MSWIN1252
so that the resulting base64 image data is correct?
Here's the code where I think the issue is. If I'm completely wrong here, then please let me know.
procedure p_putstream(pData in out NOCOPY blob) is
offset integer := 1;
lv_content_length number := dbms_lob.getlength(pdata);
buf_size integer := 2000;
buf raw(2000);
begin
p_out('stream');
-- read the blob and put it in small pieces in a varchar
while offset < lv_content_length loop
dbms_lob.read(pData,buf_size,offset,buf);
p_out(utl_raw.cast_to_varchar2(buf), false);
offset := offset + buf_size;
end loop;
-- put a CRLF at te end of the blob
p_out(chr(10), false);
p_out('endstream');
exception
when others then
error('p_putstream : '||sqlerrm);
end p_putstream;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
什么是 p_out ?围绕
dbms_output.put_line
的包装器?这可能是客户端字符集问题吗?根据 utl_raw.cast_to_varchar2 文档 :
“转换为 VARCHAR2 时,当前的全球化支持字符集用于其中的字符VARCHAR2。”
例如
但是
当数据库字符集是
What is
p_out
? A wrapper arounddbms_output.put_line
?Could this be a client character set issue ? According to the utl_raw.cast_to_varchar2 documentation:
"When casting to a VARCHAR2, the current Globalization Support character set is used for the characters within that VARCHAR2."
E.g.
But
When database character set is
我解决了我自己的问题。事实证明,我用来导入 DBF 文件的代码库将 VARCHAR2 数据类型误认为是 RAW。我可能真的应该重写它以使用 RAW 操作构建 DBF 标头。话虽这么说,我只是把它又砍了一些。特别是,我使用了 nchar_cs、utl_raw.cast_to_varchar2 的自定义版本和自定义 substr(以返回 nvarchar2)
极大地说明了根本原因(最上面的情况在我的 XE 安装中显示为 0,但在我的 11g 企业设置中显示为 194)。我真的很想发布这段代码,因为它是一个黑客工作,但它现在确实有效。
I solved my own issue. As it turns out, the codebase I am using to import DBF files bastardizes the VARCHAR2 datatype as a RAW. I probably should really rewrite it to build the DBF header using RAW operations. That being said, I just hacked it up some more. In particular, I used nchar_cs, a customized version of utl_raw.cast_to_varchar2 and a customized substr (to return nvarchar2)
greatly illustrates the root cause (The top case shows as 0 on my XE installation, but 194 on my 11g enterprise setup). I'm really gunshy about posting this code because it is such a hackjob, but it does work now.