Unicode & UTF-8

本文探讨了在Visual C++中使用不同编码(如ANSI、Unicode和UTF-8)进行字符串定义及文件写入的方法。针对不同项目设置和源文件编码,详细介绍了如何避免编码错误,以及如何在多种编码环境下正确输出文本。

 http://hi.baidu.com/%D0%A1%C0%EE%B7%C9%B5%B6%D4%D9%B7%C9%B5%B6/blog/item/1541356f34ef03d281cb4aad.html

VC默认是采用ANSI编码来保存源文件。如果你在源文件中定义了常量字符串,而这个字符串中的字符又采用了其他编码,保存的时候就会提醒你“有些Unicode字符不能被保存,请采用其他编码方式保存文件”。比如我的操作系统是繁体中文,那么如下的字符串定义因为既含有繁体又有简体,就会在保存的时候报错:
TCHAR * lpStr =_T( "蘋果快乐");
改正的方法就是在菜单中选择File->Save as->Save with Encoding,采用Unicode或者UTF-8编码都可以。
下面我们将这个字符串输出到一个txt文本文件中。

condition 1:
工程属性采用Unicode字符集,源文件保存为UTF-8编码。
void test()
{
   HANDLE hFile = ::CreateFile(_T("D://result.txt"),
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
   if(hFile == INVALID_HANDLE_VALUE)
   {
             //get the information
            LPVOID   lpMsgBuf;   //Windows   will   allocate    
            ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER   |   FORMAT_MESSAGE_FROM_SYSTEM,0,  
     GetLastError(),MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),   
                (LPTSTR)&lpMsgBuf,   0,   NULL   );  
   
            //show  
            ::MessageBox(0,   (LPCTSTR)lpMsgBuf,   _T("GetLastError"),   MB_OK|MB_ICONINFORMATION   );  
            //lpMsgBuf is the eror stirng
   
             //release memory
            ::LocalFree(   lpMsgBuf   );  
    
    return ;
   }
   CFile file(hFile);

   TCHAR * str1 =_T( "蘋果快乐");
   int len1 = _tcslen(str1);

   char * str2 = "蘋果快乐";
   int len2 = (int)strlen(str2) ;

   file.Write((const void*)str2, len2);
}

这里的TCHAR实际上就是wchar_t。str1指向的内存的值是3f00 5e5f 3f00 7965 1d60 3f00 0000,得到的字符串长度len1为6。而str2指向的内存的值是e8 98 8b e6 9e 9c e5 bf ab e4 b9 90 00,得到的字符串长度len2是12。
str1为什么会变成这些值?_T对字符串做了什么操作?
用记事本打开result.txt文件可以发现显示正确,并且是用UTF-8解码的。
condition 2:
工程属性采用Unicode字符集,源文件保存为Unicode编码。
   TCHAR * str1 =_T( "蘋果快乐");
   int len1 = _tcslen(str1);

   char * str2 = "蘋果快乐";
   int len2 = (int)strlen(str2) ;

    file.Write((const void*)str1, len1*2);
这里的TCHAR实际上就是wchar_t。str1指向的内存的值是0b86 9c67 eb5f 504e 0000,得到的字符串长度len1为6。而str2指向的内存的值是e8 98 8b e6 9e 9c e5 bf ab e4 b9 90 00,得到的字符串长度len2是12。
str2为什么被转换成了UTF-8的编码值?
用记事本打开result.txt文件发现显示乱码,但是重新用Unicode方式打开显示正确。是否记事本要正确判读其是Unicode编码需要添加标志吗?
也可将Unicode编码转换成UTF-8编码输出:
   TCHAR * str1 =_T( "Ä«ªG§Ö乐");
   int len1 = _tcslen(str1);

   int len2 = WideCharToMultiByte(CP_UTF8, 0, str1, len1, NULL, 0 , NULL, NULL );
   char * str2 = new char[len2];
   WideCharToMultiByte(CP_UTF8, 0, str1, len1, str2, len2, NULL, NULL );

   file.Write((const void*)str2, len2);

   delete str2;
用记事本打开result.txt文件可以发现显示正确,并且是用UTF-8解码的。
condition 3:
工程属性采用MBCS字符集,源文件保存为Unicode编码。
   TCHAR * str1 =_T( "蘋果快乐");
   int len1 = _tcslen(str1);

    file.Write((const void*)str1, len1);
这里的TCHAR实际上就是char。在上面的condition2中知道,str1这时的值就是UTF-8编码。可直接写往txt文件,也可以转换成Unicode再写入文件。转换的步骤如下:
   TCHAR * str1 =_T( "蘋果快乐");
   int len1 = _tcslen(str1);

   int len2 = MultiByteToWideChar(CP_UTF8, 0, str1, len1, NULL, 0);
   wchar_t * str2 = new wchar_t[len2];
   MultiByteToWideChar(CP_UTF8, 0, str1, len1, str2, len2);

    file.Write((const void*)str2, len2*2);
   delete str2;
用记事本打开result.txt文件发现显示乱码,重新用Unicode方式打开显示正确。
condition 4:
工程属性采用MBCS字符集,源文件保存为UTF-8编码。
与condition3类似,可以直接将UTF-8编码写入文件,也可转换成Unicode写入。
MultiByteToWideChar&WideCharToMutiByte
See MSDN
CodePage常用的是CP_ACP(ANSI),CP_UTF8(UTF-8)
注意先计算所需的长度(此时无需给出dest的pointer和length),再分配空间,最后要释放

*****************************************小李飞刀再飞刀**************************************************

                                                           版权所有,转载请注明

*****************************************小李飞刀再飞刀**************************************************

 

<think>首先,用户的问题是:“我想在数据库连接字符串中添加时区参数以支持UnicodeUTF-8编码 请问jdbc connection string add serverTimezone parameter with useUnicode and characterEncoding UTF-8”。这翻译成英文是:“I want to add a timezone parameter to the database connection string to support Unicode and UTF-8 encoding. How to add the serverTimezone parameter with useUnicode and characterEncoding UTF-8 in the JDBC connection string.” 用户的核心需求是:在JDBC连接字符串中添加serverTimezone参数,同时使用useUnicode和characterEncoding=UTF-8参数。 从系统级指令中,我有几个关键点要遵守: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 参考提供的引用内容,但用户的问题是关于JDBC连接字符串的,所以我需要基于引用内容来回答。 - 回答结构清晰,帮助用户逐步解决问题。 提供的引用内容: - 引用[1]:包含一个application.yml文件,其中有JDBC连接字符串示例:`jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;autoReconnect=true` - 引用[2]:另一个配置文件,有JDBC URL:`jdbc:mysql://localhost:3306/database1?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8&amp;useSSL=false` - 引用[3]:关于字符串创建的Java内容,不直接相关。 - 引用[4]:关于Iceberg和StarRocks的,不直接相关。 用户的问题直接涉及JDBC连接字符串的参数添加,所以我应该引用[1]和[2],因为它们有具体的例子。 用户的问题是如何添加serverTimezone参数,同时使用useUnicode和characterEncoding=UTF-8。在引用[1]中,URL是:`jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;autoReconnect=true`。这里已经包含了useUnicode=true, characterEncoding=UTF-8, 和serverTimezone=UTC。 同样,在引用[2]中:`jdbc:mysql://localhost:3306/database1?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8&amp;useSSL=false`。 所以,我可以基于这些例子来回答。 回答结构: 1. 解释如何在JDBC连接字符串中添加这些参数。 2. 提供一个示例。 3. 解释每个参数的作用。 4. 确保使用中文。 5. 在末尾添加相关问题。 6. 在引用段落添加引用标识。 步骤: - 首先,确认用户的需求:添加serverTimezone参数以支持时区,同时使用useUnicode和characterEncoding=UTF-8- 然后,解释JDBC连接字符串的格式:它以`jdbc:mysql://host:port/database?`开头,后跟参数。 - 参数之间用`&amp;`分隔(在URL中,&amp;需要转义为`&amp;`,但在代码中通常直接写`&amp;`)。 - 提供示例,基于引用[1]或[2]。 - 解释参数: - `useUnicode=true`:启用Unicode支持。 - `characterEncoding=UTF-8`:指定字符编码为UTF-8- `serverTimezone=UTC`:设置服务器时区为UTC(或其他时区,如GMT+8)。 - 建议用户根据实际时区设置serverTimezone值。 - 添加引用:在提到示例时,引用[1]或[2]。 生成相关问题: - 基于主题,JDBC连接字符串的常见参数。 - 例如: 1. 如何设置JDBC连接的其他常见参数? 2. 时区设置对数据库操作的影响是什么? 3. 如何测试JDBC连接是否正常工作? 确保LaTeX:用户的问题没有数学表达式,但如果有数学内容,我需要使用$...$。这里可能不需要数学表达式,除非涉及计算。 回答在中文中。</think>### JDBC 连接字符串中添加时区参数 在 JDBC 连接字符串中添加 `serverTimezone` 参数以支持时区处理,同时使用 `useUnicode=true` 和 `characterEncoding=UTF-8` 来确保 UnicodeUTF-8 编码兼容,是数据库连接中的常见需求。MySQL JDBC 驱动(如 Connector/J)使用查询参数(query parameters)来配置这些选项。以下是详细的步骤和示例,帮助您实现这一目标。 #### 步骤 1: 理解 JDBC 连接字符串格式 JDBC 连接字符串的基本结构为: `jdbc:mysql://<host>:<port>/<database>?<参数1>=<值1>&amp;<参数2>=<值2>&amp;...` 其中: - `<host>`: 数据库服务器地址(如 `localhost` 或 IP)。 - `<port>`: 数据库端口(默认 `3306`)。 - `<database>`: 数据库名称。 - 参数部分:使用 `&amp;` 分隔多个参数,在配置文件中需转义为 `&amp;`(例如在 YAML 或 XML 中)。 关键参数说明: - `useUnicode=true`:启用 Unicode 支持,确保数据库能处理非 ASCII 字符(如中文)。 - `characterEncoding=UTF-8`:指定字符编码为 UTF-8,避免乱码问题。 - `serverTimezone=<时区值>`:设置数据库服务器的时区,解决日期/时间转换错误(如 `UTC`、`GMT+8`)。 - 其他可选参数:如 `autoReconnect=true`(自动重连)、`useSSL=false`(禁用 SSL)等。 #### 步骤 2: 添加参数到连接字符串 在您的连接字符串中,直接将 `serverTimezone` 与 `useUnicode`、`characterEncoding` 组合使用。参数顺序无关紧要,但需确保正确分隔。以下是基于实际配置的示例(参考引用内容): - **示例 1**(来自 `application.yml` 配置): 在引用[1]中,连接字符串已包含 `useUnicode=true`、`characterEncoding=UTF-8` 和 `serverTimezone=UTC`: `jdbc:mysql://192.168.43.10:3306/bill?zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;autoReconnect=true` 这确保了 Unicode 支持和时区处理[^1]。 - **示例 2**(优化版,适用于您的需求): 假设您的数据库服务器在 `localhost:3306`,数据库名为 `mydb`,时区设为 `Asia/Shanghai`(或 `GMT+8`),连接字符串如下: `jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai` 在代码或配置文件中,可直接使用此格式。 #### 步骤 3: 实现方式 - **在 Java 代码中**: 直接在 JDBC URL 字符串中添加参数。 ```java String url = "jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"; Connection conn = DriverManager.getConnection(url, "username", "password"); ``` (注意:在 Java 字符串中,使用 `&amp;` 无需转义。) - **在配置文件(如 YAML)中**: 参考引用[1]和[2],在 `application.yml` 或类似文件中设置: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai username: root password: your_password ``` 这里 `&amp;` 转义为 `&amp;` 以避免 YAML 解析错误[^1][^2]。 #### 步骤 4: 验证和注意事项 - **验证参数生效**: 连接数据库后,执行简单查询(如 `SELECT NOW();`)检查时间是否正确,或插入中文字符测试编码。 - **时区值选择**: - `serverTimezone=UTC`:通用协调时区。 - `serverTimezone=GMT+8`:东八区(中国标准时间),在引用[2]中使用过[^2]。 - 使用 `TimeZone.getAvailableIDs()` 获取有效时区列表。 - **常见问题**: - 如果省略 `serverTimezone`,可能导致日期/时间错误(如 `java.sql.SQLException`)。 - 确保所有参数拼写正确(如 `characterEncoding` 非 `characterEncoding`)。 - **性能影响**: 添加这些参数不会显著影响性能,但建议测试连接池设置(如引用[1]中的 `hikari` 配置)[^1]。 #### 总结 通过上述步骤,您可以在 JDBC 连接字符串中轻松添加 `serverTimezone`、`useUnicode` 和 `characterEncoding` 参数,确保数据库操作正确处理时区和 Unicode 字符。核心是参数组合:`?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=<时区值>`。实际应用时,根据您的数据库环境调整主机、端口和时区值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值