字符编码存储

字符编码存储

字符编码查看

  1. 可以使用notepad++ 更改编码方式,然后用hex查看
  2. Ue的话有快捷键ctrl+H

mark

中的gbk编码是D6D0,unicode的编码是4E2D

utf8的解码很简单,我们以E4 B8 AD来解析.

对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

1110 0100 , 1011 1000 , 1010 1101
xxx 表示3个字节表示unicode
   x 这个表示长度结束符号
     开始编码
 

mark

字体

一个文字,怎么显示?通过一个编码,找到具体的字模来达到具体的显示(点阵,公式等)

所以一个字体应该包括了字符编码和字体显示点阵数据

mark

代码测试

我们写下这样一句

char * str_put="123中";

这个里面到底是怎么存储的呢?实际上默认是按照代码文件的格式存储的.

#include <stdio.h>

int main(int argc, char ** argv)
{
	unsigned char * str_put="123中";
	unsigned char * pt=str_put;
	while(*pt)
	{
		printf("%02x ",*pt);
		pt++;
	}
	printf("\n");
	return 0;
	
}

测试保存不同的编码,我在保存u16编码的时候,无法编译过去


[2019-02-26 21:57.29]  /mnt/d/test_encode
[layty.layty-PC] ➤ gcc -o utf8 utf8.c
───────────────────────────────────────────────────────
[2019-02-26 21:59.32]  /mnt/d/test_encode
[layty.layty-PC] ➤ ./utf8.exe
31 32 33 e4 b8 ad

[layty.layty-PC] ➤ ./ansi.exe
31 32 33 d6 d0

为什么?

其实是编码为gbk的时候,没有被gcc检测出错误,但不一定每次都能通过的.

指定编码的理解

man gcc 
查找 charset
// 输入文件编码 默认以utf-8编码
-finput-charset=charset
//生成的可执行程序的编码
-fexec-charset=charset
-fwide-exec-charset=charset


-finput-charset=GBK
-fexec-charset=UTF-8

GBK
UTF-8
UTF-16BE 
UTF-16LE 

理解

这里的指定文件编码应该这么理解

  1. 假设现在我们有一个char a="中";文件的编码是GBK

  2. gbk是兼容asc编码的,所以代码上一些其他的文字读取下来是没什么问题的,比如#include xxx

  3. 文件的具体的二进制实际上是已经定死的,也就是说你保存为GBK的时候,存储的就是d6 d0

  4. 这个时候指定输入文件为gbk,则解码d6 d0,我觉得这里内部会有一个转换为unicode编码的中间文件

  5. 然后如果我们不指定输出文件的格式,则默认就是utf8,也就是将d6 d0当作utf8,输出

    • 这个时候如果指定编码,我们再去转换这个中间文件的编码到指定的编码,默认还是utf8,所以输出还是d6 d0

原始文件=按照-finput-charset=charset读取>按照-fwide-exec-charset=charset重新编码新的文件

  1. 所以如果我们指定输入文件格式为gbk的时候,他能正确解码d6 b0,转换成正确的unicode码,然后你就需要指定输出文件的编码才能打印出你想要的了

比如存在如下代码

char *s = "中国";
printf("raw char[] is :");
for(i=0;i<10;i++)
    printf("%x ",(*(s+i)&0xFF));
输入 输出编码 打印
utf8 utf8 d6 d0 b9 fa
utf8 gbk 报错
gbk utf8 e4 b8 ad e5 9b bd
gbk gbk d6 d0 b9 fa

如果文件是utf8编码的,则

输入 输出编码(实际raw的存储的二进制) 打印
utf8 utf8 e4 b8 ad e5 9b bd
utf8 gbk d6 d0
gbk utf8 报错
gbk gbk 报错

下面的代码以不同的编码保存,但是可以输出相同的结果


char *s="中国";
char buf[10];  

printf("this file is encoding by gbk\n");
g2u(s, strlen(s), buf, sizeof(buf)); 

printf("raw char[] is :");
for(i=0;i<10;i++)
    printf("%x ",(*(s+i)&0xFF));
printf("\n");

book@100ask:~/stu/code$ gcc -finput-charset=GBK  -fexec-charset=GBK  gbk_show.c
book@100ask:~/stu/code$ ./a.out
this file is encoding by gbk
raw char[] is :d6 d0 b9 fa 0 74 68 69 73 20
utf8 char[] is :e4 b8 ad e5 9b bd 0 0 0 0
book@100ask:~/stu/code$ gcc   -fexec-charset=GBK  utf8_show.c
book@100ask:~/stu/code$ ./a.out
this file is encoding by gbk
raw char[] is :d6 d0 b9 fa 0 74 68 69 73 20
utf8 char[] is :e4 b8 ad e5 9b bd 0 0 0 0
    
    
    

这样可以将gbk编码的文件编译成utf8编码的执行文件

book@100ask:~/stu/code/yy$ gcc -finput-charset=GBK  -fexec-charset=UTF-8  ansi.c
book@100ask:~/stu/code/yy$ ./a.out
31 32 33 e4 b8 ad

但是依然无法解决utf16编码的,后来查找原因有说该是<stdio.h>这个文件不是utf16编码导致的,尝试删除这个文件,去除printf后依然无法编译

文件编码转换

在搜索的时候发现可以使用iconv来转换文件,使用iconv -l能够列出字符集

iconv -f UTF-16BE -t UTF-8 -o ff.c utf16-big.c  确实转换了格式拿到win7下查看

然而我先转换为 UTF-16BE,再编译这个文件依然过不去

iconv -t  UTF-16BE -f UTF-8 -o ff.c utf8.c
book@100ask:~/stu/code/yy$ gcc -finput-charset=UTF-16BE -fexec-charset=UTF-8 -o -o aa ff.c

所以我觉得可以先将文件转换为utf-8,再来编译

posted @ 2019-03-07 21:23  zongzi10010  阅读(531)  评论(0编辑  收藏  举报