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