您的位置:首页 > 数据库 > MySQL

C请求MySQL数据输出中文乱码

2014-03-29 20:32 316 查看
作者:金良(golden1314521@gmail.com) csdn博客:http://blog.csdn.net/u012176591

做socket,之前用Java试过,感觉Java封装的太好,以至于在那个过程中没学到什么东西,所以这次我铁了心要用C/C++来写相关应用.我要实现的功能是从socket服务器端(C语言实现)接受客户端(Android)的请求,从MySQL数据库中读取数据,并把数据处理后用发给Android客户端.我先在Linux机器上尝试用C程序从MySQL数据库读几条数据,然后字符串打印,发现乱码了,发现每个汉字输出了一个问号表示.开始我还以为是MySQL设置不正确,按照网上给的建议,鼓捣一通,并没有解决问题.后来一拍脑袋,自己真是太傻了,
我的输出语句是这样的

while ((row = mysql_fetch_row(res)) != NULL)
        printf("%s \n", row[0]);


我竟然用字符串输出,怎么可能输出中文呢.,不过我还是有疑问,为什么一个汉字对应一个问号,而不是两个,估计是C语言对国标编码的特定反应吧.

int main() {
  char *s = "乱码了吗?";
  printf("%s\n",s);
}


发现输出的中文并没有乱码.从这儿可以看到,上述的乱码问题并不是C语言的问题,而是MySQL的问题,莫非MySQL不支持中文?需要说明的是,直接在命令行的MySQL管理环境下请求中文数据是不乱码的.

然后我查了好多资料,找到了好多解决方法,比如,修改my.conf文件,或者 [client]里面的或者 [server] 里面的内容等,大多都是加上一条set_default_charcter=utf8语句,但是都没有解决问题.

功夫不负有心人,最终我还是找到了解决方法的,网上大牛真多,仅仅在C语言文件中加入这样几句,就彻底解决问题了

int utf8;
utf8=mysql_query(mysql,"set character_set_results=utf8");
printf("utf8=%d\n",utf8);
assert(utf8==0);


我的程序代码如下,注意与本文主题无关的内容的干扰哦:

/*server.c  
linux 下socket网络编程简例  - 服务端程序 
服务器端口设为 0x8888   (端口和地址可根据实际情况更改,或者使用参数传入) 
服务器地址设为 
作者:golden1314521#gmail.com (将#换为@) 
*/  
  
#include <stdlib.h>   
#include <sys/types.h>   
#include <stdio.h>   
#include <sys/socket.h>   
#include <linux/in.h>   
#include <string.h>
#include <mysql.h>
#include <string.h>
#include <assert.h>

int init_sfp(unsigned short);
void getdata(char *);

  
int main()  
{  
    int sfp;   
    unsigned short port = 0x8888;   
    

    if(-1 == (sfp=init_sfp(port)))  
    {  
        printf("init_socket fail ! \r\n");  
        return -1;  
    }  
    if(-1 == listen(sfp,5))  
    {  
        printf("listen fail !\r\n");  
        return -1;  
    } else {
        printf("Server started,port:%d\r\n",port);  
    }    

  
    while(1)  
    {
          
        struct sockaddr_in c_add;
      	int sin_size = sizeof(struct sockaddr_in);  
	int nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);  

        printf("\n**********************************************\n\n");

        char buffer[1024]={0};    /* 接受缓冲区 */
        int recbytes;
        if(-1 == nfp)  
        {  
            printf("accept fail !\r\n");  
            return -1;  
        }  
        printf("accept ok!\r\nServer start get connect from %#x : %#x\r\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));  
  
        if(-1 == (recbytes = read(nfp,buffer,1024)))
        {
            printf("read data fail !\r\n");
            return -1;
        }
        printf("read ok\rthe num of bytes is %d:\r\n",recbytes);

        buffer[recbytes]='\0';
        printf("request from client : %s\r\n",buffer);

        /* 这里使用write向客户端发送信息,也可以尝试使用其他函数实现 */
        if(0==strcmp(buffer,"getNameList")) {
            memset(buffer,0,1024);
            getdata(buffer);
            if(-1 == write(nfp,buffer,1024))  
            {  
                printf("write fail!\r\n");  
                return -1;
            } 
            printf("write ok!\r\n");  
        } 
        close(nfp);  
        printf("\n**********************************************\n\n");
  
    }  

    close(sfp);  
    return 0;  
} 

 
int init_sfp(unsigned short port) {
    int sfp;
    unsigned short portnum=port;/*端服务器使用端口 */  
    struct sockaddr_in s_add;

    //printf("Hello,welcome to my server !\r\n%d\n",portnum);  
    sfp = socket(AF_INET, SOCK_STREAM, 0);  
    if(-1 == sfp)  
    {    
        return -1;  
    }    
  
    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */  
    bzero(&s_add,sizeof(struct sockaddr_in));  
    s_add.sin_family=AF_INET;  
    s_add.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */  
    s_add.sin_port=htons(portnum);  
    /* 使用bind进行绑定端口 */  
    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))  
    {  
        return -1;  
    }  
    
    return sfp;  
}

   
void getdata(char *packets){

    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;
   
    char *server = "localhost";
    char *user = "root";
    char *password = "jobs1991"; /* 此处改成你的密码 */
    char *database = "moviedatabase";

    conn = mysql_init(NULL);

   /* Connect to database */
   if (!mysql_real_connect(conn, server,
          user, password, database, 0, NULL, 0)) {
      fprintf(stderr, "%s\n", mysql_error(conn));
     // return 1;
   }

   /* send SQL query */
   
   int utf8;
   utf8=mysql_query(conn,"set character_set_results=utf8");
   printf("utf8=%d\n",utf8);
   assert(utf8==0);          //其实你需要的就是这行上面的部分 然后你就什么都会了  ^_^    这四行代码以上和以下的代码几乎都是没有意义的,因为这不是个问题
   //mysql_set_character_set(conn,"utf-8");
   if (mysql_query(conn, "SELECT name from streamMovieList")) {
      fprintf(stderr, "%s\n", mysql_error(conn));
      //return 1;
   }

    res = mysql_use_result(conn);

   /* output table name */
   printf("MySQL Tables in mysql database:\n");
   while ((row = mysql_fetch_row(res)) != NULL)
   {
      strcat(packets,row[0]);
      strcat(packets,"?");
   }
   strcat(packets,"$");//$identify the end 
   mysql_free_result(res);
   mysql_close(conn);
   
}


C语言客户端如下:

/*client.c  
linux 下socket网络编程简例  - 客户端程序 
服务器端口设为 0x8888   (端口和地址可根据实际情况更改,或者使用参数传入) 
服务器地址设为 192.168.1.104 
作者:kikilizhm#163.com (将#换为@) 
*/  
  
#include <stdlib.h>  
#include <sys/types.h>  
#include <stdio.h>  
#include <sys/socket.h>  
#include <linux/in.h>  
#include <string.h>  
  
int main()  
{  
    int cfd; /* 文件描述符 */  
    int recbytes;  
    int sin_size;  
    char buffer[1024]={0};    /* 接受缓冲区 */  
    struct sockaddr_in s_add,c_add; /* 存储服务端和本端的ip、端口等信息结构体 */  
    unsigned short portnum=0x8888;  /* 服务端使用的通信端口,可以更改,需和服务端相同 */  
  
    printf("Hello,welcome to client !\r\n");  
    /* 建立socket 使用因特网,TCP流传输 */  
    cfd = socket(AF_INET, SOCK_STREAM, 0);  
    if(-1 == cfd)  
    {  
        printf("socket fail ! \r\n");  
        return -1;  
    }  
    printf("socket ok !\r\n");  
    /* 构造服务器端的ip和端口信息,具体结构体可以查资料 */  
    bzero(&s_add,sizeof(struct sockaddr_in));  
    s_add.sin_family=AF_INET;  
    s_add.sin_addr.s_addr= inet_addr("10.109.16.157"); /* ip转换为4字节整形,使用时需要根据服务端ip进行更改 */  
  
    s_add.sin_port=htons(portnum); /* 这里htons是将short型数据字节序由主机型转换为网络型,其实就是将2字节数据的前后两个字节倒换,和对应的ntohs效果、实质相同,只不过名字不同。htonl和ntohl是操作的4字节整形。将0x12345678变为0x78563412,名字不同,内容两两相同,一般情况下网络为大端,PPC的cpu为大端,x86的cpu为小端,arm的可以配置大小端,需要保证接收时字节序正确. */  
  
    printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port); /* 这里打印出的是小端和我们平时看到的是相反的。 */  
  
    /* 客户端连接服务器,参数依次为socket文件描述符,地址信息,地址结构大小 */  
    if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))  
    {  
        printf("connect fail !\r\n");  
        return -1;  
    }    
    printf("connect ok !\r\n");  
    /*连接成功,从服务端接收字符*/ 
    if(-1 == write(cfd,"getNameList",32))
    {
        printf("write fail!\r\n");
        return -1;
    }
    printf("write request to server is ok\n");
 
    if(-1 == (recbytes = read(cfd,buffer,1024)))  
    {  
        printf("read data fail !\r\n");  
        return -1;  
    }  
    printf("read ok\r\nREC:\r\n");  
  
    buffer[recbytes]='\0';  
    printf("%s\r\n",buffer);  
  
    //getchar(); /* 此句为使程序暂停在此处,可以使用netstat查看当前的连接 */  
    close(cfd); /* 关闭连接,本次通信完成 */  
    return 0;  
  
}


Android客户端如下:

public String getdata(String address,int port) {

		String data="";
		int length;
		String[] nameList = null;
		byte[] b = new byte[1024];
        Socket client = new Socket();
        InetSocketAddress isa = new InetSocketAddress(address, port);
        
        try {
        	client.connect(isa, 10000);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("failed to connect to the server");
		}
            
		try {
			BufferedOutputStream out = new BufferedOutputStream(client
					.getOutputStream());
			BufferedInputStream in = new BufferedInputStream(client
					.getInputStream());
	        out.write("getNameList".getBytes());
	        out.flush();

            while ((length = in.read(b)) > 0)//
            {
            	data += new String(b, 0, length);
            }
            int pos = data.indexOf("$");
            data = data.substring(0, pos);
	        out.close();
	        out = null;
            in.close();
            in = null;
	        client.close();
	        client = null;
	            
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("failed at the I/O stream");
		}
		//return nameList;
		System.out.println("getdata()中 : "+data);
		
		return data;

	}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: