jdcb query SQL Server data garbled problem solution

When using jdcb to query the SQL Server data source data, there is no abnormality in the data in the window environment, but in the linux environment, there is no problem with English and numbers, but Chinese characters are garbled. So, starting from the implementation of the SQLServer driver, find out that the Mysql configuration url is, and the encoding attribute configuration:
//SQLServerDriver
public Connection connect(String s, Properties properties)
        throws SQLServerException
    {
        try
        {
            Logger.setLogWriter(this, DriverManager.getLogWriter());
        }
        catch(NoSuchMethodError nosuchmethoderror)
        {
            Util.println("This version of sqlserver jdbc driver needs the JVM to support level 1.4 or higher");
            Util.println("The current JVM level is:" + Util.sJDKVersion);
            try
            {
                Logger.setLogStream(this, DriverManager.getLogStream());
            }
            catch(Exception exception) { }
        }
        SQLServerConnection sqlserverconnection = null;
	// Parse the URL
        Properties properties1 = Util.parseUrl(s);
        if(properties1 == null)
            return null;
        Object obj = null;
        Object obj1 = null;
        int i = DriverManager.getLoginTimeout();
        if(i > 0)
            properties1.put("loginTimeout", (new Integer(i)).toString());
        for(int j = 0; j < driverProperties.length; j++)
        {
            String s1 = driverProperties[j];
            if(properties1.getProperty(s1) != null)
                continue;
            String s2 = properties.getProperty(s1);
            if(s2 != null)
                properties1.put(s1, s2);
        }

        connProperties = properties1;
        String s3 = properties1.getProperty("logfile");
        if(s3 != null)
            Logger.setCustomLogFile(this, s3);
        sqlserverconnection = new SQLServerConnection();
        sqlserverconnection.sConnectURL = s;
        try
        {
	    // get connection
            sqlserverconnection.connect(properties1, null);
        }
        catch(SQLException sqlexception)
        {
            throw new SQLServerException(sqlserverconnection, "Failed Logon:" + sqlexception.toString() + " url:" + s, sqlexception.getSQLState(), sqlexception.getErrorCode(), false);
        }
        return sqlserverconnection;
    }


Let's first look at parsing the url:
Properties properties1 = Util.parseUrl(s);


//Useful
public static Properties parseUrl(String s)
   {
       Properties properties = new Properties();
       String s1 = s;
       Object obj = null;
       Object obj1 = null;
       String s3 = "jdbc:sqlserver://";
       if(!s1.startsWith(s3))
           return null;
       s1 = s1.substring(s3.length());
       try
       {
           StringTokenizer stringtokenizer = new StringTokenizer(s1, ":/&?;", true);
           String s2 = stringtokenizer.nextToken();
           properties.put("serverName", s2);
           String s4 = stringtokenizer.nextToken();
           if(s4.equals(":"))
           {
               String s7 = stringtokenizer.nextToken();
               properties.put("portNumber", s7);
               String s5 = stringtokenizer.nextToken();
           }
           int i = 0;
           do
           {
               if(!stringtokenizer.hasMoreTokens())
                   break;
               String s6 = stringtokenizer.nextToken();
               if(++i % 2 != 0)
               {
                   StringTokenizer stringtokenizer1 = new StringTokenizer(s6, "=", true);
                   String s8 = stringtokenizer1.nextToken();
                   if(stringtokenizer1.hasMoreTokens())
                   {
                       stringtokenizer1.nextToken();
                       if(stringtokenizer1.hasMoreTokens())
                       {
                           String s9 = stringtokenizer1.nextToken();
                           properties.put(s8, s9);
                       }
                   } else
                   {
                       properties.put("databaseName", s8);
                   }
               }
           } while(true);
       }
       catch(NoSuchElementException nosuchelementexception) { }
       return properties;
}

The property configuration related

to Let's look at getting the connection:
//SQLServerConnection
public Connection connect(Properties properties, BasePooledConnection basepooledconnection)
        throws SQLServerException
    {
        int k;
        ConnectionProperties connectionproperties;
        int l;
        int i1;
        int i2;
        activeConnectionProperties = properties;
        pooledConnectionParent = basepooledconnection;
        conPropertiesArray = new ConnectionProperties[10];
        for(int i = 0; i < 10; i++)
            conPropertiesArray[i] = new ConnectionProperties();
        String s = null;
        String s1 = null;
	//Get database connection property configuration
        s = properties.getProperty("enableFailover");
        boolean flag = s != null && s.equals("true");
        s = "user";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = "";
        buildConnectionProperties(s, s1, flag);
        s = "password";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = "";
        buildConnectionProperties(s, s1, flag);
        s = "databaseName";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = properties.getProperty("database");
        buildConnectionProperties(s, s1, flag);
        String s2 = s1;
        s = "serverName";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = properties.getProperty("host");
        if(s1 == null)
            s1 = "localhost";
        String s3 = s1;
        int j = s1.indexOf('\\');
        String s4 = null;
        if(j >= 0)
        {
            String s5 = s1.substring(j + 1, s1.length());
            s1 = s1.substring(0, j);
            s4 = getInstancePort(s1, s5);
        } else
        {
            String s6 = properties.getProperty("instanceName");
            if(s6 != null)
                s4 = getInstancePort(s1, s6);
        }
        buildConnectionProperties(s, s1, flag);
        s = "portNumber";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = properties.getProperty("port");
        if(s1 == null || s1.equals("0"))
            if(s4 == null)
                s1 = "1433";
            else
                s1 = s4;
        buildConnectionProperties(s, s1, flag);
        s = "sqlVersion";
        s1 = properties.getProperty(s);
        if(s1 == null)
            s1 = properties.getProperty("sqlversion");
        buildConnectionProperties(s, s1, flag);
        s = "asciiStringParameters";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "booleanLiterals";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "applicationName";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "instanceName";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "lastUpdateCount";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "disableStatementPooling";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "trustedAuthentication";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "codepage";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "loginTimeout";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "lockTimeout";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "xopenStates";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "enableFailover";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "selectMethod";
        s1 = properties.getProperty(s);
        if(s1 == null || !s1.equals("cursor"))
            s1 = "default";
        buildConnectionProperties(s, s1, flag);
        s = "preExecuteMetaData";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "iterativeBatching";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "connectionRetryCount";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "connectionRetryWait";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "trustedAuthenticationPort";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "ntlmAuthentication";
        s1 = properties.getProperty(s);
        buildConnectionProperties(s, s1, flag);
        s = "domain";
        s1 = properties.getProperty(s);
	...
}

Still haven't found the corresponding character encoding related property:

what could be the reason?

When I think about it, in the articles related to Mysql jdbc, we see that Mysql jdbc communicates with the client through the socket connection, so the idea of ​​MS SqlServer must be the same, then the received byte data of the socket must be converted into String, it must be Use the
following method:
//String
public String(byte bytes[], Charset charset) {
    this(bytes, 0, bytes.length, charset);
}

If no encoding is configured, use such as:
public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}

public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    / / Delegate to StringCoding decoding
    this.value = StringCoding.decode(bytes, offset, length);
}


//StringCoding
static char[] decode(byte[] ba, int off, int len) {
    //The key is to get the system default character encoding in this sentence
    String csn = Charset.defaultCharset().name();
    try {
        // use charset name decode() variant which provides caching.
        return decode(csn, ba, off, len);
    } catch (UnsupportedEncodingException x) {
        warnUnsupportedCharset(csn);
    }
    try {
        return decode("ISO-8859-1", ba, off, len);
    } catch (UnsupportedEncodingException x) {
        // If this code is hit during VM initialization, MessageUtils is
        // the only way we will be able to get any kind of error message.
        MessageUtils.err("ISO-8859-1 charset not available: "
                         + x.toString());
        // If we can not find ISO-8859-1 (a required encoding) then things
        // are seriously wrong with the installation.
        System.exit(1);
        return null;
    }
}
public static Charset defaultCharset() {
    if (defaultCharset == null) {
        synchronized (Charset.class) {
	    //Under the access control permission of the current thread, get the system file code
            String csn = AccessController.doPrivileged(
                new GetPropertyAction("file.encoding"));
            Charset cs = lookup(csn);
            if (cs != null)
                defaultCharset = cs;
            else
	       //If the system encoding is empty, the default is UTF-8
                defaultCharset = forName("UTF-8");
        }
    }
    return defaultCharset;
}


Guess it is caused by system coding? The encoding of the linux system is UTF-8
donald@linux:~/tomcat/bin>locale
...
LC_ALL=zh_CN.UTF-8
LANG = zh_CN.UTF-8  


Modify the system code to GBK, modify /etc/profile, and add the following two lines:
export LC_ALL=zh_CN.G
export LANG=zh_CN.GBK


donald@linux:~/tomcat/bin>source /etc/profile
donald@linux:~/tomcat/bin> tail -n 20 /etc/profile
...
export LC_ALL=zh_CN.GBK  
export LANG=zh_CN.GBK  
donald@linux:~/tomcat/bin>


Restart the application, test, it is ok, feel good...

If this is not the case, you can try to get the data from the result set first, and then convert the data to GBK encoding format:

String oname=rs.getString("name");
byte[] namebyte=oname.getBytes("GBK2312");
name=new String(namebyte);


There is no problem with this method in theory. I have not tested it. If the above method does not work, you can try this method.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326125621&siteId=291194637