一、ANSI和UNICODE知识点
二、 用内存映射文件来把一个ANSI或UNICODE文本文件内容颠倒过来。
三、进程间共享数据,参考API一日一练
一、ANSI和UNICODE知识点
1、 判断一个文本是ANSI还是UNICODE
2、 如何对字符串进行有选择的比较
3、 让程序支持UNICODE
4、 Windows定义的UNICODE数据类型
5、 如何对UNICODE操作
6、 ANSI和UNICODE的相互转换
1、判断一个文本是ANSI还是UNICODE
1)判断如果文本文件的开头两个字节是0xFF和0xFE,那么就是Unicode,否则是ANSI。
2)用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法,以便猜测缓存的内容。由于这不是一种确切的科学方法,因此 IsTextUnicode有可能返回不正确的结果。
2、通过调用CompareString来实现。
标志 含义
NORM_IGNORECASE 忽略字母的大小写
NORM_IGNOREKANATYPE 不区分平假名与片假名字符
NORM_IGNORENONSPACE 忽略无间隔字符
NORM_IGNORESYMBOLS 忽略符号
NORM_IGNOREWIDTH 不区分单字节字符与作为双字节字符的同一个字符
SORT_STRINGSORT 将标点符号作为普通符号来处理
3、在vc编译选项上,在vc7.0以上在工程的属性页中的“字符集”选上 "使用 Unicode 字符集 "即可,在vc6.0下可能麻烦一点,得先把vc运行库的unicode版本复制到vc路径下,一般都是和xxx.lib的ansi对应xxxU.lib,默认装vc时是不会装的,再在工程属性
1)改语言定义:
在project settings的 "C++ "页中的 "preprocessor definitions "中改_MBCS为_UNICODE
2)改入口函数:
在 "link "页中的 "project Options "加入/entry: "wWinMainCRTStartup "即可.
3)在代码上,处理字符中的多用TCHAR.H中的宏,如strcpy用_tcscpy代替,用TCHAR代char,
用TCHAR m_mystr[]=_T( "xxxx ")代替 char m_mystr[]= "xxxx ";
4)注意调试UNICODE程序时,需要在安装时VC选择所有选项,否则会缺少动态库和相应的.lib文件
4、Windows定义的UNICODE数据类型
数据类型 说明
WCHAR Unicode字符
PWSTR 指向Unicode字符串的指针
PCWSTR 指向一个恒定的Unicode字符串的指针
对应的ANSI数据类型为CHAR,LPSTR和LPCSTR。
ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR。
5、如何对UNICODE操作
字符集 特性 实例
ANSI 操作函数以str开头 strcpy
Unicode 操作函数以wcs开头 wcscpy
MBCS 操作函数以_mbs开头 _mbscpy
ANSI/Unicode 操作函数以_tcs开头 _tcscpy(C运行期库)
ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数
6、ANSI和UNICODE的相互转换
1)将ANSI转换到Unicode
(1)通过L这个宏来实现,例如: CLSIDFromProgID( L "MAPI.Folder ",&clsid);
(2)通过MultiByteToWideChar函数实现转换,例如:
char *szProgID = "MAPI.Folder ";
WCHAR szWideProgID[128];
CLSID clsid;
long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));
szWideProgID[lLen] = '\0 ';
(3)通过A2W宏来实现,例如:
USES_CONVERSION;
CLSIDFromProgID( A2W(szProgID),&clsid);
2)将Unicode转换到ANSI
(1)使用WideCharToMultiByte,例如:
// 假设已经有了一个Unicode 串 wszSomeString...
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
(2)使用W2A宏来实现,例如:
USES_CONVERSION;
pTemp=W2A(wszSomeString);
注意在转换时可能存在的问题:
因为ANSI转UNICODE,如果使用A2W或MultiByteToWideChar(第一个参数是CP_ACP)的话,是根据系统默认的转码表,把转入的ANSI字符串看作Multi-Bytes字符串处理的,如果是中文(中文windows默认就是中文),一个大于0x87的byte可能和下一byte一起被看作一个汉字,然后根据汉字的Unicode编码转换为相同的Unicode汉字,如果找不到相应的编码,一般就用一个默认的字符来取代它(一般是问号“?”),由此看,如果随便把一段数据给他转,转化很复杂而且极可能不可逆,而且你加密过的ANSI码是相当混乱的有很多〉0x87的byte,转换就变得不可逆了。
建议自己直接就这样写:
CHAR lpANSI[COUNT];
WCHAR lpUnicode[COUNT];
int i = 0;
while(lpANSI[i] != '\0 ' ) {
lpUnicode[i] = (WCHAR)lpANSI[i];
}
lpUnicode[i] = L '\0 ';
然后按相同的方法转回来,因为对于0~0x87的ANSI字符串,对应的Unicode码就是相同的16位值,至于其他的,你的字符串反正加了密,没必要转换成显示出来是一样的字符,就按同样的方法处理了,其实如果中间的字符串不用显示或别的,直接reutrn (LPWSTR)lpANSI;过去也可以, 反正接受的时候自己清楚就可以了。
二、用内存映射文件来把一个ANSI或UNICODE文本文件内容颠倒过来。
两个注意点:颠倒前,先给指定文件复制一份,防止颠倒后文件不可逆。
Ø 因文本文件并非以字符0结尾,而C语言格式字符串最后一个字符必须是0。所以创建文件映射对象时,文件长度增加一个宽字符的大小(用来存放字符0)。
Ø 在一个文本文件中,每行末尾的回车换行符”\r\n”也会被颠倒,用_strrev倒序后需将”\n\r”转为”\r\n”。
BOOL FileReverse(LPCTSTR pszPathname) { //Open the file for reading and writing HANDLE hFile = CreateFile(pszPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) { AfxMessageBox(_T("File could not be opened.")); return FALSE; } //Create the file-mapping object. DWORD dwFileSize = GetFileSize(hFile, NULL); HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize + sizeof(TCHAR), NULL); if (NULL == hFileMap) { AfxMessageBox(_T("File map could not be opened.")); CloseHandle(hFile); return FALSE; } //Get the address where the first byte of the file is mapped into memory. PVOID pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0); if (NULL == pvFile) { AfxMessageBox(_T("Could not map view of file")); CloseHandle(hFileMap); CloseHandle(hFile); return FALSE; } //Does the buffer contain ANSI or Unicode int iUnicodeTestFlags = -1; BOOL bIsTextUnicode = IsTextUnicode(pvFile, dwFileSize, &iUnicodeTestFlags); if (!bIsTextUnicode) { //把一个字符0写到文件末尾并颠倒字符串 PSTR pchANSI = (PSTR)pvFile; pchANSI[dwFileSize / sizeof(char)] = 0; //reverse the contexts of the file _strrev(pchANSI); //ansi用_strrev(pvFile); //convert all "\n\r" combinations back to "\r\n" to preserve //the normal end-of-line sequence. pchANSI = strstr(pchANSI, "\n\r"); while (pchANSI != NULL) { *pchANSI++ = '\r'; *pchANSI++ = '\n'; pchANSI = strstr(pchANSI, "\n\r"); } } else { //把一个字符0写到文件末尾并颠倒字符串 PWSTR pchUnicode = (PWSTR)pvFile; pchUnicode[dwFileSize / sizeof(WCHAR)] = 0; if ((iUnicodeTestFlags & IS_TEXT_UNICODE_SIGNATURE) !=0) { //if the first character is the Unicode BOM(byte-order-mark) //0xFEFF,keep the character at the begining of the file. pchUnicode++; } _wcsrev(pchUnicode); //convert all "\n\r" combinations back to "\r\n" to preserve //the normal end-of-line sequence. pchUnicode = wcsstr(pchUnicode, L"\n\r"); while (pchUnicode!=NULL) { *pchUnicode++ = L'\r'; *pchUnicode++ = L'\n'; pchUnicode = wcsstr(pchUnicode, L"\n\r"); } } //Clean up everything before exiting. UnmapViewOfFile(pvFile); CloseHandle(hFileMap); //Remove trailing zero character added earlier. SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN); SetEndOfFile(hFile); CloseHandle(hFile); return TRUE; }