首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Windows核心编程17章-后续

2013-03-17 
Windows核心编程17章------后续一、ANSI和UNICODE知识点 二、 用内存映射文件来把一个ANSI或UNICODE文本文件

Windows核心编程17章------后续

一、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 writingHANDLE 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 Unicodeint 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;}



 

热点排行