首页
社区
课程
招聘
[讨论]"内存映射文件"文本文件内容逆转
发表于: 2007-7-20 20:14 5920

[讨论]"内存映射文件"文本文件内容逆转

2007-7-20 20:14
5920
"内存映射文件"文本文件内容逆转, 内容逆转到是简单:
<关键点>:用到_strrev函数(ANSI)或者_wcsrev函数(Unicode)


俺本来准备在程序里面加载一个BMP图片的,可是死活加载不进去!  cool
运行出来的程序像隐形了一样,只能看到部分的画面! 效果上就像电脑运行久了以后响应用户鼠标操作很缓慢很迟钝的样子....

无语了, 高手有兴趣的帮俺看看哦~
-------------------------------------------------------------------------------------------------------------------------------------
其实在程序里面插入图片的步骤是非常简单的(由于偶没有插入成功,所以要把步骤写出来,R...):

1.新建WIN32 项目, 插入资源, 插入BMP图象:

注意啊,BMP位图必须是256色的,俺原打算自己用PhotoShop做一个的,鉴于太菜了,就没做....

2.在程序的框架里面用通用控件大致画个框架,加载图片时用,先给它起个名字: IDC_BMP:



3. CPP里面写代码:
先定义全局变量
HBITMAP g_hBitmap;


在WinMain中用::LoadBitmap (昨天发帖子的时候打忘了....)

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE, PTSTR pszCmdLine, int)
{
        // 加载图片.呵呵,自己弄个图片上去看看效果,HOHO~
//        g_hBitmap =::LoadBitmap (hInstance, (LPCTSTR) IDB_BITMAP1);
        
        ::DialogBoxParam (hInstance, (LPCTSTR)(IDD_DIALOG), NULL, DlgProc, NULL);

        return 0;
}



接着在对话框函数DlgProc里面进行初始化和加载:
int WINAPI DlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG nStyle;
HWND hWndBmp;

switch (uMsg)
{
/////////////////////////////////////////////////////////////////////////////////////
case WM_INITDIALOG:

// 初始化显示图片的静态边框
hWndBmp = ::GetDlgItem (hDlg, IDC_BMP);

// 设置SS_BITMAP 风格
nStyle = ::GetWindowLong (hWndBmp, GWL_STYLE);
::SetWindowLong (hDlg, GWL_STYLE, nStyle | SS_BITMAP);

// 设置图片
::SendDlgItemMessage (hDlg, IDC_BMP, STM_SETIMAGE,IMAGE_BITMAP, (long)g_hBitmap);

::EnableWindow (::GetDlgItem (hDlg, IDC_FILEREV), FALSE);
break;
..
.
..
..



这样一个图片就应该能被加到程序里了....
-------------------------------------------------------------------------------------------------------------------------------------
基础知识
① 要对文本文件的内容进行倒序输出,其实就是用到了_strrev函数,这是一个C运行期函数,由于字符串的最后一个字符必须是个0结束符号,而文本文件不以0为结束符,所以必须在打开文件的时候在它的一个副本里面附加一个0, 副本就是用CreateFileMapping函数创建:
DWORD dwFileSize = ::GetFileSize (hFile, NULL);
	
	//取得文件长度后,在末尾要加一个0结束符, sizeof(WCHAR) 一个宽字符
	HANDLE hFileMap = ::CreateFileMapping (hFile, NULL, PAGE_READWRITE,
		0, dwFileSize + sizeof(WCHAR), NULL);


② 另外注意文本文件不同于2进制文件,它的每一行结尾都是\r\n, '\r'是换行,'\n'是回车.
倒叙后位置就变成\n\r了,所以还要再逆转回来:
PSTR pchANSI = (PSTR)pvFile;
		pchANSI[dwFileSize / sizeof (CHAR)] = 0; // 字符末尾+一个0结束符

		_strrev (pchANSI);  // ANSI 下的字符倒置函数 _strrev

		// 将文本文件中的"\n\r"还原为原来的"\r\n"
		pchANSI = strchr (pchANSI, '\n');

		while (pchANSI != NULL)
		{
			*pchANSI++ = '\r';
			*pchANSI++ = '\n';

			pchANSI = strchr (pchANSI, '\n');
		}


③ 尤其要注意ANSI和Unicode的不同,如果你对这2者不是很清楚,建议回顾<WINDOWS核心编程>第2章.
现在的WINDOWS NT默认是支持Unicode 的,所以用Unicode编写代码效率高,否则还需要转换,浪费时间...

④ 在一本"高质量编程"的书中看到如下的话(大意):
* “C++的目标之一就是使C的预处理器成为多余,应尽量避免使用宏
* 几乎每个宏都说明程序设计语言、程序或程序员存在缺陷”
* 我怀疑这种思想有一定的偏激性,孤在必要时应该还是需要用到宏的

----------------------------------------------------------------------------------------------------
效果丢个图:


由于图片没加载上去,界面很不好看的哦~~

代码如下:
/**********************************************************************************
* Modual : 1.CPP
* Author : sudami
* Time   : 2007/07/20
* Comment: 【内存映射学习笔记】将文本文件的内容倒置输出
*            <关键点>:用到_strrev函数(ANSI)或者
*			_wcsrev函数(Unicode),所以要预先判断字符格式;
**********************************************************************************/


/////////////////////////////////////////////////////////////////////////////////

#include  <windows.h>
#include  <tchar.h>
#include  <string.h>  // 用于 _strrev 函数
#include  <commdlg.h>   // 用于对话框中的浏览框
#include  "resource.h"

/////////////////////////////////////////////////////////////////////////////////

//HBITMAP g_hBitmap;

#define FILENAME  TEXT("sudami.dat")   // Unicode 意识 -- TEXT

/* 在一本"高质量编程"的书中看到如下的话(大意):
 * “C++的目标之一就是使C的预处理器成为多余,应尽量避免使用宏
 * 几乎每个宏都说明程序设计语言、程序或程序员存在缺陷”
 * 我怀疑这种思想有一定的偏激性,孤在必要时应该还是需要用到宏的
 */
/////////////////////////////////////////////////////////////////////////////////

/*******************************************************************************************
*   模块:   FileReverse
*   返回值: TRUE | FALSE
*   参数:  (PCTSTR)pszPathname 传递文件路径;
*          (PBOOL)pfIsTextUnicode 指明文本文件的字符格式(ANSI | Unicode),便于在程序响应
*           WM_FILEREV消息时调用相应的字符处理函数[strrev函数(ANSI)或者_wcsrev函数(Unicode)]
********************************************************************************************/

BOOL FileReverse (PCTSTR pszPathname, PBOOL pfIsTextUnicode)
{
	*pfIsTextUnicode = FALSE;

	// 以独占方式打开文件
	HANDLE hFile = ::CreateFile (pszPathname, GENERIC_WRITE | GENERIC_READ,
		0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
		::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);

		return FALSE;
	}

	DWORD dwFileSize = ::GetFileSize (hFile, NULL);
	
	//取得文件长度后,在末尾要加一个0结束符, sizeof(WCHAR) 一个宽字符
	HANDLE hFileMap = ::CreateFileMapping (hFile, NULL, PAGE_READWRITE,
		0, dwFileSize + sizeof(WCHAR), NULL);

	if (hFileMap == NULL)
	{
		::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);
		::CloseHandle (hFile);

		return FALSE;
	}

	// 获得文件映射内核对象映射后的指针
    LPVOID pvFile = ::MapViewOfFile (hFileMap, FILE_MAP_WRITE, 0, 0, 0);

	if (pvFile == NULL)
	{
		::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);
		::CloseHandle (hFileMap);
		::CloseHandle (hFile);

		return FALSE;
	}

	///////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////
	//      已经成功映射,现在要判断字符格式是ANSI还是Unicode     //////
	///////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////

	int iUnicodeTestFlags = -1;
	*pfIsTextUnicode = ::IsTextUnicode (pvFile, dwFileSize, &iUnicodeTestFlags);

	// 如果是ANSI格式
	if (!*pfIsTextUnicode)
	{
		PSTR pchANSI = (PSTR)pvFile;
		pchANSI[dwFileSize / sizeof (CHAR)] = 0; // 字符末尾+一个0结束符

		_strrev (pchANSI);  // ANSI 下的字符倒置函数 _strrev

		// 将文本文件中的"\n\r"还原为原来的"\r\n"
		pchANSI = strchr (pchANSI, '\n');

		while (pchANSI != NULL)
		{
			*pchANSI++ = '\r';
			*pchANSI++ = '\n';

			pchANSI = strchr (pchANSI, '\n');
		}
	}

	// 如果是Unicode格式
	else
	{
		PWSTR pchUnicode = (PWSTR)pvFile;
		pchUnicode[dwFileSize / sizeof (WCHAR)] = 0;

		if ((iUnicodeTestFlags & IS_TEXT_UNICODE_SIGNATURE) != 0)
		{
			pchUnicode++;
		}

		_wcsrev (pchUnicode);  // Unicode 下的字符倒置函数 _wcsrev

		pchUnicode = wcschr (pchUnicode,L'\n');

		while (pchUnicode != NULL)
		{
			*pchUnicode++ = '\r';
			*pchUnicode++ = '\n';

			pchUnicode = wcschr (pchUnicode,L'\n');
		}

	}

	//////////////////////////////////////////////////////////////////////////
	::UnmapViewOfFile (pvFile);
	::CloseHandle (hFileMap);

	// 必须删除附加给文件结尾处的0字符,否则再进行倒置的时候就得不到正确结果
	::SetFilePointer (hFile, dwFileSize, NULL, FILE_BEGIN);
	::SetEndOfFile (hFile);

	::CloseHandle (hFile);

	return TRUE;
}


/*******************************************************************************************
*
*   模块:   主入口函数 _tWinMain
*   Comment: 调用 DialogBoxParam函数创建对话框
*
********************************************************************************************/

int WINAPI DlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE, PTSTR pszCmdLine, int)
{
	// 加载图片.呵呵,自己弄个图片上去看看效果,HOHO~
//	g_hBitmap =::LoadBitmap (hInstance, (LPCTSTR) IDB_BITMAP1);
	
	::DialogBoxParam (hInstance, (LPCTSTR)(IDD_DIALOG), NULL, DlgProc, NULL);

	return 0;
}

/*******************************************************************************************
*
*   模块:   对话框函数 DlgProc
*   Comment: 初始化对话框,响应WM_COMMAND消息
*
********************************************************************************************/

int WINAPI DlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//	LONG nStyle;
//	HWND hWndBmp;

	switch (uMsg)
	{
	/////////////////////////////////////////////////////////////////////////////////////
	case WM_INITDIALOG:
/*		
		// 初始化显示图片的静态边框
	    hWndBmp = ::GetDlgItem (hDlg, IDC_BMP);
		
		// 设置SS_BITMAP 风格
		nStyle = ::GetWindowLong (hWndBmp, GWL_STYLE);
		::SetWindowLong (hDlg, GWL_STYLE, nStyle | SS_BITMAP);

		// 设置图片
		::SendDlgItemMessage (hDlg, IDC_BMP, STM_SETIMAGE,IMAGE_BITMAP, (long)g_hBitmap);
*/	
		::EnableWindow (::GetDlgItem (hDlg, IDC_FILEREV), FALSE);
		break;

	///////////////////////////////////////////////////////////////////////////////////
	case WM_COMMAND:
		TCHAR szPathname[MAX_PATH];
		
		switch (LOWORD(wParam))
		{
			case IDCANCEL:
				EndDialog(hDlg, IDCANCEL);
				break;
			
			// 路径栏里面有路径之后就激活"转换"按钮
			case IDC_FILENAME:
				EnableWindow(GetDlgItem(hDlg, IDC_FILEREV), 
					TRUE);
				break;
			
			//////////////////////////////////////////////////////////////////////////
			case IDC_FILEREV:
				GetDlgItemText(hDlg, IDC_FILENAME, szPathname, sizeof (szPathname));

				if (!CopyFile(szPathname, FILENAME, FALSE))
				{
					::MessageBox (NULL, "复制失败", "sudami", MB_OK);
					break;
				}

				BOOL fIsTextUnicode;
				if (FileReverse (FILENAME, &fIsTextUnicode))
				{
					::SetDlgItemText (hDlg, IDC_TEXTTYPE,
						fIsTextUnicode ? TEXT("Unicode"):TEXT("ANSI"));

					// 创建一个记事本程序来显示倒置的文字
					// 比如CMD下: notepad.exe sudami.dat
					STARTUPINFO si = { sizeof(si) };
                    PROCESS_INFORMATION pi;
					TCHAR sz[] = TEXT("Notepad ") FILENAME;
					
					if (::CreateProcess(NULL, sz,
						NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
							CloseHandle(pi.hThread);
							CloseHandle(pi.hProcess);
					}
				}
				break;

				///////////////////////////////////////////////////////////////////////
			case IDC_BROWSE:
				OPENFILENAME ofn = { sizeof (ofn) };
				ofn.hwndOwner = hDlg;
				ofn.lpstrFile = szPathname;
				ofn.lpstrFile[0] = 0;
				ofn.nMaxFile = sizeof (szPathname);
				ofn.lpstrTitle = TEXT("Select file for reversing");
				ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;

				GetOpenFileName(&ofn);
				SetDlgItemText(hDlg, IDC_FILENAME, ofn.lpstrFile);

				SetFocus(GetDlgItem(hDlg, IDC_FILEREV));
				break;
		}


	} //switch

	return 0;
}
/////////////////////////////// END OF FILE //////////////////////////////////////////

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这不是Windows核心编程里的一个例子吗。。
2007-7-21 19:58
0
雪    币: 709
活跃值: (2590)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
3
嗯,按照自己的理解打的代码,哈哈,一种学习过程嘛.

动手实践才能掌握的更牢固啊~
2007-7-21 20:30
0
游客
登录 | 注册 方可回帖
返回