有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

utf 8 Java字符问题修复,但希望了解错误数据是如何生成的

试图在Oracle表中插入这样的字符串:ABčDE

Oracle表的定义如下:

SQL> create table DUMMY_TEST (Field1 number, Name_Test varchar2(20));

下面是正在使用的Java/JDBC代码。它有两个插入。 一个Insert硬编码到代码中,第二个Insert从文件中检索

import java.sql.*;
import java.util.*;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Locale;


class JdbcTest
{
    static StringBuffer sbuff = new StringBuffer();

    public static void main (String a[])
    {
        //Creating the connection
        String url = "jdbc:oracle:thin:@//server:port/ServiceName";
        String user = "xa21appdb";
        String pass = "neptune";

        //Inserting data using SQL query
        String sql = "INSERT INTO DUMMY_TEST VALUES(1, 'ABèDE')";

        loadDataFromFile();

        Connection con=null;
        try
        {
            DriverManager.registerDriver(new oracle.jdbc.OracleDriver());

            //Reference to connection interface
            con = DriverManager.getConnection(url,user,pass);

            Statement st = con.createStatement();
            System.out.println("Executing 1st INSERT");
            int m = st.executeUpdate(sql);
            if (m == 1)
                System.out.println("1st inserted successfully ");
            else
                System.out.println("1st insertion failed");

            System.out.println("Executing 2nd INSERT");
            m = st.executeUpdate(sbuff.toString());
            if (m == 1)
                System.out.println("2nd inserted successfully ");
            else
                System.out.println("2nd insertion failed");

            con.close();
        }
        catch(Exception ex)
        {
            System.err.println(ex);
        }
    }

    static void loadDataFromFile()
    {
        try
        {
            InputStream inputStream = new FileInputStream("/tmp/input.txt");
         Reader      inputStreamReader = new InputStreamReader( inputStream, "UTF-8");

            int ch = inputStreamReader.read();

            while(ch != -1)
            {
                sbuff.append((char) ch);
                ch = inputStreamReader.read();
            }
            inputStreamReader.close();
        }
        catch(Exception e){}
    }
}

以下是文件的内容,其中包含与硬编码值相同的SQL

> cat /tmp/input.txt
INSERT INTO DUMMY_TEST VALUES(2, 'ABèDE')

为了确保硬编码SQL和文件中的SQL相同,使用xxd命令显示十六进制值

这仅显示INSERT语句以及要插入的ABčDE字符串

> xxd -b JdbcTest.java
    :
    :
000019e: 01101100 00100000 00111101 00100000 00100010 01001001  l = "I
00001a4: 01001110 01010011 01000101 01010010 01010100 00100000  NSERT
00001aa: 01001001 01001110 01010100 01001111 00100000 01000100  INTO D
00001b0: 01010101 01001101 01001101 01011001 01011111 01010100  UMMY_T
00001b6: 01000101 01010011 01010100 00100000 01010110 01000001  EST VA
00001bc: 01001100 01010101 01000101 01010011 00101000 00110001  LUES(1
00001c2: 00101100 00100000 00100111 01000001 01000010 11101000  , 'AB.
00001c8: 01000100 01000101 00100111 00101001 00100010 00111011  DE')";

这显示了使用要插入的ABčDE字符串读取的整个文件代码

> xxd -b /tmp/input.txt
0000000: 01001001 01001110 01010011 01000101 01010010 01010100  INSERT
0000006: 00100000 01001001 01001110 01010100 01001111 00100000   INTO
000000c: 01000100 01010101 01001101 01001101 01011001 01011111  DUMMY_
0000012: 01010100 01000101 01010011 01010100 00100000 01010110  TEST V
0000018: 01000001 01001100 01010101 01000101 01010011 00101000  ALUES(
000001e: 00110010 00101100 00100000 00100111 01000001 01000010  2, 'AB
0000024: 11101000 01000100 01000101 00100111 00101001 00001010  .DE').  

比较2文件时,确认硬代码和文件之间的字符串相同

00100111 01000001 01000010 11101000 01000100 01000101 00100111
   '        A         B       .        D        E         '

运行代码时,将以下两行插入到Oracle中

SQL> select * from dummy_test;

    FIELD1 NAME_TEST
---------- --------------------
         1 ABèDE
         2 AB?DE

使用DUMP命令获取每个的详细信息

SQL> select field1,  dump(name_test, 1016) from dummy_test;

    FIELD1   DUMP(NAME_TEST,1016)
----------   -------------------------------------------------------------
         1   Typ=1 Len=6 CharacterSet=AL32UTF8: 41,42,c4,8d,44,45
         2   Typ=1 Len=7 CharacterSet=AL32UTF8: 41,42,ef,bf,bd,44,45

如果代码是根据此修改的:

Reader      inputStreamReader = new InputStreamReader( inputStream, "UTF-8");

为此:

Reader      inputStreamReader = new InputStreamReader( inputStream);

这两行都将显示以下内容:

SQL> select field1,  dump(name_test, 1016) from dummy_test;

    FIELD1   DUMP(NAME_TEST,1016)
----------   -------------------------------------------------------------
         1   Typ=1 Len=6 CharacterSet=AL32UTF8: 41,42,c4,8d,44,45
         2   Typ=1 Len=6 CharacterSet=AL32UTF8: 41,42,c4,8d,44,45

现在回答3个问题

1-在这种情况下,当它工作并且正确插入“特殊”字符时,这可以得到确认,因为Oracle字符集AL32UTF8显示c4 8d代表č,但我的问题是Oracle为什么打印č

2-当UTF-8与读卡器一起使用时,将插入3个字节(ef、bf、bd)。 如果我正确地进行UTF-8计算,结果如下:

‭11101111‬  ‭10111111‬  ‭10111101‬
1111‬111111‬111101‬
FF FD

这是一个非常不寻常的角色

虽然我知道这与转换有冲突,但你能准确解释发生了什么吗

编辑以添加第三个问题

3-My Putty session的字符集设置为:ISO-8859-1:1998(拉丁语-1,西欧) 为什么在命令提示符下看到的是ABèDE而不是ABčDE


共 (0) 个答案