Win32 API、VC++、C# 文件操作函数的初步比较

一 C#


File.ReadAllText(FilePath) ;
一次将文本内容全部读完,

File.ReadAllLines;
该方法返回一个字符串数组。每一行都是一个数组元素。
string[] strs = File.ReadAllLines(@"c:\temp\ascii.txt"); 


FileStream fs = new FileStream(@"C:\temp\utf-8.txt", FileMode.Open, FileAccess.Read, FileShare.None); 
StreamReader sr3 = new StreamReader(fs); 
StreamReader sr4 = new StreamReader(fs, Encoding.UTF8);

FileInfo myFile = new FileInfo(@"C:\temp\utf-8.txt"); 
// OpenText 创建一个UTF-8 编码的StreamReader对象 
StreamReader sr5 = myFile.OpenText();

// OpenText 创建一个UTF-8 编码的StreamReader对象 
StreamReader sr6 = File.OpenText(@"C:\temp\utf-8.txt");

初始化完成之后,你可以每次读一行,也可以每次读一个字符 ,还可以每次读几个字符,甚至也可以一次将所有内容读完。
      
      string nextLine = sr.ReadLine();    // 读一行       
      int nextChar = sr.Read();    // 读一个字符 

      // 读100个字符 
      int nChars = 100; 
      char[] charArray = new char[nChars]; 
      int nCharsRead = sr.Read(charArray, 0, nChars);      
         
      string restOfStream = sr.ReadToEnd();    // 全部读完 

二 VC


      文件的读写定位
  定位文件中的数据是很重要的,这决定了写入的数据在文件中的位置。

  CFile类的文件数据定位函数有:
LONG Seek(LONG lOff,UINT nFrom);
throw(CFileException);
  如果要求的位置合法,则Seek返回从文件开始起的新字节偏移量
  lOff:指针移动的字节数。
  nFrom:指针移动的模式。可以是CFile::begin,CFile::current,CFile::end
void SeekToBegin( );
  DWORD SeekToEnd( );//返回文件长度(字节数)。
  
  读取数据:
  CFile的成员函数有:
UINT Read (void* lpBuf,UINT nCount);
throw(CFileException);// 返回值是传输到缓冲区的字节数。

三 win32 api


    设置文件指针setfilepointer
    在对打开的文件进行操作时需要知道当前文件指针位置,是在文件开头还是文件末尾还是在哪里,打开文件时文件指针默认在文件开头,如果不设置文件指针的话,下次写入文件内容就会覆盖掉前面的;

DWORD WINAPI SetFilePointer(
①HANDLE hFile, //文件句柄
②LONG lDistanceToMove, //32位有符号long型,表示要移动的位置(正数表示向后,负数表示向前)
③PLONG lpDistanceToMoveHigh, //
④DWORD dwMoveMethod //移动模式
);

④dwMoveMethod 移动模式
一共有三种移动模式
FILE_BEGIN 从文件开始位置定位(此时参数②不能为负)
FILE_CURRENT 从文件当前位置向前或向后移动指针(比如写了一句话之后发现写错了,可以将指针移动至写之前的位置,再次写入)
FILE_END 从文件的末尾向前或向后定位指针
返回值:当前所处位置距文件开头的字符数,可以借此查看当前文件有多大

判断文件长度GetFileSize
DWORD GetFileSize(
HANDLE hFile, //文件句柄
LPDWORD LPFileSizeHigh //指向高阶双字的文件大小的指针(此参数一般为NULL)
);

返回值:返回文件的大小

从文件中读取数据ReadFile
BOOL ReadFile(
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用于保存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead, //要读入的字节数
LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
LPOVERLAPPED lpOverlapped //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
  );

四 基本差别


    C#的比较简单易用;读取全部内容,读取行,读取多少个字符;不需要数据定位;
    VC和Win32 API需要数据定位,设置文件指针;
    VC和Win32 API可按字节数读取;但VC的要好用些;Win32 API有更多的属性控制;
    VC也可以按行读取;Win32 API应该是不能;
    如果要直接用Win32 API按行读取,需要自己逐字节判断是否读到回车换行符;
    VC和Win32 API可能数据类型还有些差别;VC指定字节数是UINT;win32 API指定字节数是DWORD;


五 Win32 API 读文件示例程序

/*-------------------------------------------------
bobo, 2020.01.04
-------------------------------------------------*/

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	PSTR  szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("readFileDemo");
	HWND         hwnd;
	MSG          msg;
	WNDCLASS     wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("Program requires Windows NT!"),
			szAppName, MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(szAppName, TEXT("readFileDemo"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC         hdc;
	int         x, y;
	PAINTSTRUCT ps;
	RECT        rect;
	char path[50]="";
	char buffer[100];
	unsigned long lpNumber = 0;

	switch (message)
	{
	case WM_SIZE:		
		return 0;

	case WM_RBUTTONDOWN:		
		return 0;

	case WM_LBUTTONDOWN:
		hdc = GetDC(hwnd);
		//strcat(path, "1.txt");
		strcat_s(path, 50, "1.txt");
		HANDLE hFile = CreateFile(path,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
		if (hFile == INVALID_HANDLE_VALUE)
		{
			MessageBox(NULL, "创建文件句柄出错", "error", MB_OK);
		}
		int filesucc = ReadFile(hFile,buffer,100,&lpNumber,NULL);
		CloseHandle(hFile);
		if (filesucc == 0)
		{
			MessageBox(NULL, "读取文件失败", "error", MB_OK);
		}
		TextOut(hdc, 100, 100, buffer, 101);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);		
		EndPaint(hwnd, &ps);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

读取100个字节;单击鼠标左键输出;

读取的文件放到源代码文件同一目录,否则 创建文件句柄失败;

文件内容;

使用strcat_s代替传统C的strcat;否则将出现C4996错误;

C4996    'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

发布了434 篇原创文章 · 获赞 512 · 访问量 294万+

猜你喜欢

转载自blog.csdn.net/bcbobo21cn/article/details/103797706