a)我的系统是英文XP+中文包+VS2005
b)我有一个文本文件"D:\\文件.txt",这个文件创建的时候保存为Unicode文本文件,里面的内容是"helloworld 我的"
c)程序的作用是读写D:\\文件.txt
我Debug自己的小程序,发现
1. 字符串变量a在内存里面是英语1个字节,中文两个字节。我怎么觉得英文也应该是2个字节?
2. 字符串变量b保存到文件里面去,会发现这个文件虽然是Unicode编码,可是用记事本打开却是乱码,像这样:
d : \ ‡eöNoR,g. t x t
中文变成了乱七八糟的东西
程序的源代码如下:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <sys/stat.h>
TCHAR a[]=_T("d:\\文件.txt");
TCHAR b[]=_T("d:\\文件副本.txt");
int main() {
struct _stat sb;
_tstat( a, &sb );
printf("File size=%d\n",sb.st_size);
FILE* pf=_tfopen(a,_T("r"));
if(NULL==pf){
_tprintf(_T("cannot open %s\n"),a);
exit(1);
}
unsigned char buf[40];
size_t ret=fread(buf, sizeof(char),sizeof(buf)-1,pf);
buf[ret]=0;
_tprintf(_T("%s\n%s\n"),a,buf);
printf("%s\n%s\n",a,buf);
fclose(pf);
FILE* pfb=_tfopen(b,_T("w"));
if(NULL==pfb){
_tprintf(_T("cannot open %s\n"),b);
exit(1);
}
fwrite(b,1,ret,pfb);
fclose(pfb);
return 0;
}
大牛帮我分析一下吧,我的问题在于
1. 为什么_T()在Unicode模式下,英文字符在内存中仍然是1个字节而不是2个字节
2. 为什么_T()字符串b,保存到了文件以后,其中的中文"我的副本"会变成一堆乱码?
谢谢!
11 个解决方案
#1
1、你怎么看的内存中显示是一个字节的
2、_tfopen打开的方式可以设置UNICODE模式的,或者写的时候,开头写入几个表示UNICODE的字符
2、_tfopen打开的方式可以设置UNICODE模式的,或者写的时候,开头写入几个表示UNICODE的字符
#2
下个工具看下你的.txt里的是什么格式的文本,再在程序里拿_T()字符串b单独写一个.txt文件,再拿工具看下新的txt是什么格式的文本,再根据情况来转换格式。。格式不是_T()这么简单就转换的,再网上有很多utf8,ansii,unicode之间的转换
#3
我在vc10编译环境
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <sys/stat.h>
#include <locale.h>//new
TCHAR a[]=_T("e:\\文件.txt");
TCHAR b[]=_T("e:\\文件副本.txt");
int main() {
setlocale(LC_ALL,"chs" );//new
struct _stat sb;
_tstat( a, &sb );
printf("size=%d\n",sb.st_size);
FILE* pf=_tfopen(a,_T("r"));
if(NULL==pf){
_tprintf(_T("cannot open %s\n"),a);
exit(1);
}
wchar_t buf[40];
size_t ret=fread(buf, sizeof(wchar_t),sizeof(buf)-1,pf);
buf[ret]=0;
_tprintf(_T("%s read %d bytes: %s\n"),a,ret,buf);
fclose(pf);
FILE* pfb=_tfopen(b,_T("w"));
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, b, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
fwrite(szANSIString ,sizeof(char),strlen(szANSIString),pfb);
fclose(pfb);/**/
return 0;
}
#4
按照你说的:
#5
很简单,_tfopen默认就是使用ANSI编码打开文件的。如果你要写Unicode内容,请使用
fopen("newfile.txt", "rw, ccs=<ENCODING>");
新建文件,ENCODING可以是UTF-8或者UTF-16L。一般来说保存文本时多用UTF-8,内存运算多用UTF-16。
对于UTF-8文件,请先写入{0xEF,0xBB,0xBF},对于UTF-16L文件,请先写入{0xFF,0xFE}作为BOM,以保证记事本能正确打开。此外你程序里如果要打开已经创建文件的话,请使用ccs=<UNICODE>让其检测BOM
fopen("newfile.txt", "rw, ccs=<ENCODING>");
新建文件,ENCODING可以是UTF-8或者UTF-16L。一般来说保存文本时多用UTF-8,内存运算多用UTF-16。
对于UTF-8文件,请先写入{0xEF,0xBB,0xBF},对于UTF-16L文件,请先写入{0xFF,0xFE}作为BOM,以保证记事本能正确打开。此外你程序里如果要打开已经创建文件的话,请使用ccs=<UNICODE>让其检测BOM
#6
学习
to dfasfdal : 驱动器我改成E:了 还有_tprintf(_T("%s read %d bytes: %s\n"),a,ret,buf);应该改称:
_tprintf(_T("%s read %d wchar_t: %s\n"),a,ret,buf);
#7
Unicode文件:格式就是前两个字节是0xFF,0xFE ,后面是Unicode格式的字符串。
fwrite写内容对应长度,内容的参数都一致了就行了
fwrite写内容对应长度,内容的参数都一致了就行了
#8
你没明白字符串存储、字符串查看、本地字符、bom头等一系列的关系。
字符串存储可以用任意格式
在vc6中,直接能查看的字符串只能是GB格式
文件存储如果不加入bom头,就必须要存储为本地字符格式,简体中文下就是GB
如果不存储成GB格式,就必须加入bom头,bom头就是说明后面的字符是什么格式的
这几个东西其实很简单
字符串存储可以用任意格式
在vc6中,直接能查看的字符串只能是GB格式
文件存储如果不加入bom头,就必须要存储为本地字符格式,简体中文下就是GB
如果不存储成GB格式,就必须加入bom头,bom头就是说明后面的字符是什么格式的
这几个东西其实很简单
#9
这样就行了.
用fwrite()先要写入BOM.
_tfopen(b,_T("wt,ccs=UNICODE"));
_tprintf(_T("%s read %d wchar_t: %s\n"),a,ret,buf);
用fwrite()先要写入BOM.
#10
#11
Unicode的开头是0xFF,0xFE
#1
1、你怎么看的内存中显示是一个字节的
2、_tfopen打开的方式可以设置UNICODE模式的,或者写的时候,开头写入几个表示UNICODE的字符
2、_tfopen打开的方式可以设置UNICODE模式的,或者写的时候,开头写入几个表示UNICODE的字符
#2
下个工具看下你的.txt里的是什么格式的文本,再在程序里拿_T()字符串b单独写一个.txt文件,再拿工具看下新的txt是什么格式的文本,再根据情况来转换格式。。格式不是_T()这么简单就转换的,再网上有很多utf8,ansii,unicode之间的转换
#3
我在vc10编译环境
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <sys/stat.h>
#include <locale.h>//new
TCHAR a[]=_T("e:\\文件.txt");
TCHAR b[]=_T("e:\\文件副本.txt");
int main() {
setlocale(LC_ALL,"chs" );//new
struct _stat sb;
_tstat( a, &sb );
printf("size=%d\n",sb.st_size);
FILE* pf=_tfopen(a,_T("r"));
if(NULL==pf){
_tprintf(_T("cannot open %s\n"),a);
exit(1);
}
wchar_t buf[40];
size_t ret=fread(buf, sizeof(wchar_t),sizeof(buf)-1,pf);
buf[ret]=0;
_tprintf(_T("%s read %d bytes: %s\n"),a,ret,buf);
fclose(pf);
FILE* pfb=_tfopen(b,_T("w"));
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, b, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
fwrite(szANSIString ,sizeof(char),strlen(szANSIString),pfb);
fclose(pfb);/**/
return 0;
}
#4
按照你说的:
#5
很简单,_tfopen默认就是使用ANSI编码打开文件的。如果你要写Unicode内容,请使用
fopen("newfile.txt", "rw, ccs=<ENCODING>");
新建文件,ENCODING可以是UTF-8或者UTF-16L。一般来说保存文本时多用UTF-8,内存运算多用UTF-16。
对于UTF-8文件,请先写入{0xEF,0xBB,0xBF},对于UTF-16L文件,请先写入{0xFF,0xFE}作为BOM,以保证记事本能正确打开。此外你程序里如果要打开已经创建文件的话,请使用ccs=<UNICODE>让其检测BOM
fopen("newfile.txt", "rw, ccs=<ENCODING>");
新建文件,ENCODING可以是UTF-8或者UTF-16L。一般来说保存文本时多用UTF-8,内存运算多用UTF-16。
对于UTF-8文件,请先写入{0xEF,0xBB,0xBF},对于UTF-16L文件,请先写入{0xFF,0xFE}作为BOM,以保证记事本能正确打开。此外你程序里如果要打开已经创建文件的话,请使用ccs=<UNICODE>让其检测BOM
#6
学习
to dfasfdal : 驱动器我改成E:了 还有_tprintf(_T("%s read %d bytes: %s\n"),a,ret,buf);应该改称:
_tprintf(_T("%s read %d wchar_t: %s\n"),a,ret,buf);
#7
Unicode文件:格式就是前两个字节是0xFF,0xFE ,后面是Unicode格式的字符串。
fwrite写内容对应长度,内容的参数都一致了就行了
fwrite写内容对应长度,内容的参数都一致了就行了
#8
你没明白字符串存储、字符串查看、本地字符、bom头等一系列的关系。
字符串存储可以用任意格式
在vc6中,直接能查看的字符串只能是GB格式
文件存储如果不加入bom头,就必须要存储为本地字符格式,简体中文下就是GB
如果不存储成GB格式,就必须加入bom头,bom头就是说明后面的字符是什么格式的
这几个东西其实很简单
字符串存储可以用任意格式
在vc6中,直接能查看的字符串只能是GB格式
文件存储如果不加入bom头,就必须要存储为本地字符格式,简体中文下就是GB
如果不存储成GB格式,就必须加入bom头,bom头就是说明后面的字符是什么格式的
这几个东西其实很简单
#9
这样就行了.
用fwrite()先要写入BOM.
_tfopen(b,_T("wt,ccs=UNICODE"));
_tprintf(_T("%s read %d wchar_t: %s\n"),a,ret,buf);
用fwrite()先要写入BOM.
#10
#11
Unicode的开头是0xFF,0xFE