解决Oracle中C语言乱码问题(c oracle乱码问题)

解决Oracle中C语言乱码问题

在Oracle数据库中,如果需要通过C语言程序连接、查询数据库,常常会遇到中文乱码的情况。本文将介绍如何解决Oracle中C语言乱码问题。

1. 设置NLS_LANG环境变量

在Oracle服务器或客户端操作系统上,需要设置NLS_LANG环境变量为相应的字符集。例如,如果Oracle数据库中使用的是UTF8字符集,则需要设置NLS_LANG为”AMERICAN_AMERICA.UTF8″。具体设置方式可以查找操作系统的相关资料,以下是Windows系统下设置NLS_LANG的方法:

– 打开“控制面板”-“系统”-“高级系统设置”-“环境变量”;

– 在“系统变量”或“用户变量”中新建或修改“NLS_LANG”变量,值为相应字符集;

2. 使用Unicode转换函数

在C语言程序中调用Oracle数据库时,可以使用Unicode转换函数将字符串转换为Unicode编码,避免中文乱码的情况。Oracle提供了多种Unicode转换函数,常用的有以下几种:

– OCILobCharSetToUnicode():将CLOB类型的字符串从指定字符集转换为Unicode编码;

– OCIUnicodeToChar():将Unicode编码转换为指定字符集;

– OCIUTF8ToWChar():将UTF8编码的字符串转换为Unicode编码。

以下是一个示例代码,演示如何使用OCILobCharSetToUnicode()函数将CLOB类型的字符串从GBK字符集转换为Unicode编码:

OCIError *errhp;

OCIEnv *envhp;

OCISvcCtx *svchp;

OCIStmt *stmthp;

OCILobLocator *lob;

int inLen, outLen, lobLen;

char *inStr = “测试”;

ub2 *outStr;

OCICharSet *srcCs, *dstCs;

uword csid;

// 初始化

envhp = NULL;

errhp = NULL;

svchp = NULL;

stmthp = NULL;

OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);

OCIHandleAlloc(envhp, &errhp, OCI_HTYPE_ERROR, 0, NULL);

OCIHandleAlloc(envhp, &svchp, OCI_HTYPE_SVCCTX, 0, NULL);

OCIHandleAlloc(envhp, &stmthp, OCI_HTYPE_STMT, 0, NULL);

// 连接数据库

OCILogon2(envhp, errhp, &svchp, “user”, strlen(“user”), “pass”, strlen(“pass”), “db”, strlen(“db”), OCI_DEFAULT);

OCIStmtPrepare(stmthp, errhp, “INSERT INTO lob_table (lob_col) VALUES (:1)”, strlen(“INSERT INTO lob_table (lob_col) VALUES (:1)”), OCI_NTV_SYNTAX, OCI_DEFAULT);

// 分配LOB

OCIDescriptorAlloc(envhp, &lob, OCI_DTYPE_LOB, 0, NULL);

// 设置字符集

srcCs = OCICharsetWithName(envhp, “GBK”);

dstCs = OCICharsetWithName(envhp, “AL32UTF8”);

csid = OCINlsCharSetNameToId(envhp, “AL32UTF8”);

OCIAttrSet(lob, OCI_DTYPE_LOB, &csid, 0, OCI_ATTR_CHARSET_ID, errhp);

// 插入数据

inLen = strlen(inStr);

OCILobWrite(svchp, errhp, lob, &inLen, 1, (dvoid*)inStr, strlen(inStr), OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);

OCIStmtBindByPos(stmthp, &lob, sizeof(OCILobLocator*), OCI_BIND_IN, 1, OCI_DTYPE_LOB, NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);

OCIStmtExecute(svchp, stmthp, errhp, 1, 0, NULL, NULL, OCI_DEFAULT);

OCICommit(svchp, errhp, OCI_DEFAULT);

// 读取数据

OCIAttrGet(lob, OCI_DTYPE_LOB, &lobLen, 0, OCI_ATTR_LOB_LENGTH, errhp);

outLen = lobLen/2 + lobLen%2;

outStr = (ub2*)malloc(outLen * sizeof(ub2));

OCILobRead(svchp, errhp, lob, &lobLen, 1, (dvoid*)outStr, outLen, NULL, NULL, 0, SQLCS_IMPLICIT);

outStr[outLen-1] = L’\0′;

OCIUnicodeToChar(envhp, (char*)outStr, outLen*sizeof(ub2), dstCs, inLen, srcCs, &outLen);

// 释放资源

OCILogoff(svchp, errhp);

OCIHandleFree(errhp, OCI_HTYPE_ERROR);

OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);

OCIHandleFree(stmthp, OCI_HTYPE_STMT);

OCIDescriptorFree(lob, OCI_DTYPE_LOB);

OCIEnvFree(envhp);

3. 使用NCHAR类型

在Oracle中,NCHAR类型是一种固定长度的Unicode字符类型,可以存储任何Unicode字符。如果需要在C语言程序中处理中文时避免乱码问题,可以将数据库表中的字符类型改为NCHAR类型,然后使用Unicode转换函数操作即可。

例如,如果有一个表mytable,其中有一个name字段需要存储中文,可以将该字段改为NCHAR类型:

ALTER TABLE mytable MODIFY (name NCHAR(10));

然后在C语言程序中使用OCILobWrite()函数写入数据:

OCIStmtPrepare(stmthp, errhp, “INSERT INTO mytable (name) VALUES (:1)”, strlen(“INSERT INTO mytable (name) VALUES (:1)”), OCI_NTV_SYNTAX, OCI_DEFAULT);

OCILobLocator *lob;

OCIDescriptorAlloc(envhp, &lob, OCI_DTYPE_LOB, 0, NULL);

int inLen = strlen(“测试”);

OCILobWrite(svchp, errhp, lob, &inLen, 1, (dvoid*)”测试”, inLen, OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);

OCIStmtBindByPos(stmthp, &lob, sizeof(OCILobLocator*), OCI_BIND_IN, 1, OCI_DTYPE_LOB, NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);

OCIStmtExecute(svchp, stmthp, errhp, 1, 0, NULL, NULL, OCI_DEFAULT);

OCICommit(svchp, errhp, OCI_DEFAULT);

在读取数据时,可以使用OCIUnicodeToChar()函数将Unicode编码转换为指定字符集:

OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DESCRIBE_ONLY);

int colNameLen;

OCIAttrGet(stmthp, OCI_HTYPE_STMT, &colNameLen, NULL, OCI_ATTR_PARAM_COUNT, errhp);

char colName[20];

ub2 ubuf[20];

OCIDefine *colNameDef;

OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);

OCIAttrGet(stmthp, OCI_HTYPE_STMT, &colNameDef, NULL, OCI_ATTR_DESCRIBE_HANDLE, errhp);

OCIAttrGet(colNameDef, OCI_HTYPE_DESCRIBE, &colNameLen, NULL, OCI_ATTR_NAME, errhp);

OCIParamGet(colNameDef, OCI_DTYPE_PARAM, errhp, &colNameDef, 1);

OCIDefineByPos(stmthp, &colNameDef, errhp, 1, colName, sizeof(colName), SQLT_STR, NULL, NULL, NULL, OCI_DEFAULT);

OCILobLocator *lob;

OCIDescriptorAlloc(envhp, &lob, OCI_DTYPE_LOB, 0, NULL);

OCIDefineByPos(stmthp, &lob, errhp, 2, NULL, 0, SQLT_BLOB, NULL, NULL, NULL, OCI_DEFAULT);

OCIStmtExecute(svchp, stmthp, errhp, 1, 0, NULL, NULL, OCI_DEFAULT);

while (OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT) == OCI_SUCCESS) {

OCILobLocator *lob;

OCIDescriptorAlloc(envhp, &lob, OCI_DTYPE_LOB, 0, NULL);

OCIDefineByPos(stmthp, &lob, errhp, 2, NULL, 0, SQLT_BLOB, NULL, NULL, NULL, OCI_DEFAULT);

OCIDefineByPos(stmthp, &colNameDef, errhp, 1, colName, sizeof(colName), SQLT_STR, NULL, NULL, NULL, OCI_DEFAULT);

OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI


数据运维技术 » 解决Oracle中C语言乱码问题(c oracle乱码问题)