如何使用Oracle utl_file输出扩展的ascii字符

时间:2013-06-11 10:00:15

标签: oracle utl-file

我正在使用

编写文件
l_file := utl_file.fopen('OUT', 'a.txt', 'w');
utl_file.put_line(l_file, 'Rosëttenville');

但我将其更改为

l_file := utl_file.fopen_nchar('OUT', 'a.txt', 'w', 32767);
utl_file.put_line_nchar(l_file, 'Rosëttenville');

当我发现扩展的ASCII(代码127以上的字符)未正确写出时。但是第二个unicode版本也没有正确写入扩展字符。而不是Rosëttenville我得到Rosëttenville。任何人都知道如何解决这个问题?

2 个答案:

答案 0 :(得分:5)

你还没有说出你的数据库字符集是什么,因此在一个字符串中“扩展ascii”(可能是8859-1,在这种情况下是chr(235))是否合法,或者这只是一个演示。无论哪种方式,我认为,你的问题是试图隐式转换非unicode字符串。

ëcode point EB,也是UTF-8 C3 AB。您获得了单独的字符Ãcode point C3)和«code point AB)。因此,它无法从chr(235) 0x00EB直接转换为U+00EB。它似乎是通过UTF-8 C3 AB作为两个单独的字符。我不会试图理解为什么......

您可以使用convert function

l_file := utl_file.fopen('OUT', 'a.txt', 'w');
utl_file.put_line(l_file,
  convert('Rosëttenville', 'WE8ISO8859P1', 'UTF8'));

......或者,由于Oracle的阻止使用utl_raw.convert function

l_file := utl_file.fopen('OUT', 'a.txt', 'w');
utl_file.put_line(l_file,
  utl_raw.cast_to_varchar2(utl_raw.convert(utl_raw.cast_to_raw('Rosëttenville'),
    'ENGLISH_UNITED KINGDOM.WE8ISO8859P1', 'ENGLISH_UNITED KINGDOM.UTF8')));

两者都给了我你想要的价值,而你的原版给了我你看到的相同价值(我的数据库字符集在Linux上的11gR2中为AL32UTF8)。如果您的数据库字符集不是Unicode,那么您的国家字符集肯定会出现(如果您在两次尝试中获得相同的输出,则问题尚不清楚),因此nchar版本应该起作用:< / p>

l_file := utl_file.fopen_nchar('OUT', 'a.txt', 'w', 32767);
utl_file.put_line_nchar(l_file,
  utl_raw.cast_to_varchar2(utl_raw.convert(utl_raw.cast_to_raw('Rosëttenville'),
    'ENGLISH_UNITED KINGDOM.WE8ISO8859P1', 'ENGLISH_UNITED KINGDOM.UTF8')));

首先使用Unicode值可能会更好,特别是如果您当前在表中混合使用'extended ascii'和其他字符串类型;在这种情况下将转换应用于所有内容可能会产生一些奇怪的结果......

答案 1 :(得分:0)

UTL_FILE.PUT_LINE不会在数据库默认字符集中转换数据和导出数据。

所以你需要在写上进行适当的转换:

UTL_FILE.PUT_LINE(file,CONVERT(text,'WE8ISO8859P1'),FALSE);

您必须设置:

LANG=GERMAN_AUSTRIA.WE8ISO8859P1;export LANG
LC_CTYPE=ISO-8859-1;export LC_CTYPE
NLS_LANG=GERMAN_AUSTRIA.WE8ISO8859P1;export NLS_LANG