Skip to content

C++ windows实用函数

Published: at 10:08 AM | 10 min read

收集的一些比较实用的函数,头文件依赖(不包括全部):

#include <TlHelp32.h>
#include <psapi.h>
#include <Windows.h>
#include <time.h>
#include <algorithm>
#include <iterator>
#include <io.h>
#include <direct.h>
#include <assert.h>
#include <sstream>
  1. 获取当前系统内存信息
std::string getMemoryInfo() {
	const int MB = 1024 * 1024;
	MEMORYSTATUSEX statex;
	statex.dwLength = sizeof(statex);
	GlobalMemoryStatusEx(&statex);
	DWORD memoryPercent = statex.dwMemoryLoad;
	DWORD  memoryAll = statex.ullTotalPhys / MB;
	DWORD memoryFree = statex.ullAvailPhys / MB;
	DWORD memoryUse = memoryAll - memoryFree;
	char buffer[1024] = { 0 };
	sprintf_s(buffer, "memory all:%dMB, free:%dMB, use:%dMB", memoryAll, memoryFree, memoryUse);
	return buffer;
}
  1. 获取当前进程内存大小
size_t getCurrentProcessMemory()
{
	const int MB = 1024 * 1024;
	PROCESS_MEMORY_COUNTERS pmc;
	if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
		return pmc.WorkingSetSize / MB;
	}
	return 0;
}
  1. 获取当前进程使用的线程数
int getThreadAmount()
{
	PROCESSENTRY32 pe32;
	pe32.dwSize = sizeof(pe32);

	int processid = GetCurrentProcessId();
	HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE) {
		printf("CreateToolhelp32Snapshot() failed. error code:%d.\n", GetLastError());
		return 0;
	}

	int i = 0;
	BOOL bMore = ::Process32First(hProcessSnap, &pe32);
	HANDLE hProcess;
	while (bMore) {
		if (pe32.th32ProcessID == processid) {
			i = pe32.cntThreads;
			break;
		}

		bMore = Process32Next(hProcessSnap, &pe32);
	}
	CloseHandle(hProcessSnap);
	return i;
}
  1. 减少当前进程使用的内存大小
    谨慎使用,参考https://msdn.microsoft.com/en-us/library/windows/desktop/ms686234(v=vs.85).aspx
::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1);
  1. 获取系统当前时间
	bool CurrentTime(int &year, int &month, int &day, int &hour, int &min, int &sec)
	{
		struct tm t;
		time_t tt;
		time(&tt);
		if (0 == localtime_s(&t, &tt)) {
			year = t.tm_year + 1900;
			month = t.tm_mon + 1;
			day = t.tm_mday;
			hour = t.tm_hour;
			min = t.tm_min;
			sec = t.tm_sec;
			return true;
		}
		return false;
	}

    // 格式化后的时间
    std::string CurrentFormatTime()
	{
		int year, month, day, hour, min, sec;
		if (CurrentTime(year, month, day, hour, min, sec)) {
			char buffer[256];
			sprintf_s(buffer, "%04d%02d%02d%02d%02d%02d", year, month, day, hour, min, sec);
			return buffer;
		}
		return "";
	}
  1. 字符串编码转换
	std::wstring ansi2unicode(const std::string& ansi)
	{
		if (ansi.empty()) {
			return std::wstring(L"");
		}
		int len = MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, NULL, 0);
		std::wstring unicode(len+1, L'\0');
		len = MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), ansi.size(), &unicode[0], len);
		return unicode;
	}

	std::string unicode2ansi(const std::wstring& unicode)
	{
		if (unicode.empty()) {
			return std::string("");
		}
		int len = WideCharToMultiByte(CP_ACP, 0, unicode.c_str(), -1, NULL, 0, NULL, NULL);
		std::string ansi(len+1, '\0');
		WideCharToMultiByte(CP_ACP, 0, unicode.c_str(), unicode.size(), &ansi[0], len, NULL, NULL);
		return ansi;
	}

	std::string string_to_utf8(const std::string& srcStr)  
	{  
		if (srcStr.empty()) 
		{
			return "";
		}

		int nwLen = MultiByteToWideChar(CP_ACP, 0, srcStr.c_str(), -1, NULL, 0);  
		wchar_t * pwBuf = new wchar_t[nwLen + 1];  
		ZeroMemory(pwBuf, nwLen * 2 + 2);  
		MultiByteToWideChar(CP_ACP, 0, srcStr.c_str(), srcStr.length(), pwBuf, nwLen);  
		int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);  
		char * pBuf = new char[nLen + 1];  
		ZeroMemory(pBuf, nLen + 1);  
		WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);  
		string retStr(pBuf);  
		delete []pwBuf;  
		delete []pBuf;  
		pwBuf = NULL;  
		pBuf = NULL;  
		return retStr;
	}  

	std::string utf8_to_string(const std::string& srcStr)  
	{  
		if (srcStr.empty()) 
		{
			return "";
		}

		int nwLen = MultiByteToWideChar(CP_UTF8, 0, srcStr.c_str(), -1, NULL, 0);  
		wchar_t * pwBuf = new wchar_t[nwLen + 1]; 
		memset(pwBuf, 0, nwLen * 2 + 2);  
		MultiByteToWideChar(CP_UTF8, 0, srcStr.c_str(), srcStr.length(), pwBuf, nwLen);  
		int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);  
		char * pBuf = new char[nLen + 1];  
		memset(pBuf, 0, nLen + 1);  
		WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);  
		string retStr = pBuf;  
		delete []pBuf;  
		delete []pwBuf;  
		pBuf = NULL;  
		pwBuf = NULL;  
		return retStr; 
	}

	std::wstring UTF8ToWString(const std::string& str)
	{
		int len = str.size();
		int unicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
		wchar_t* pUnicode;
		pUnicode = new wchar_t[unicodeLen + 1];
		memset((void*)pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
		::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen);
		wstring wstrReturn(pUnicode);
		delete [] pUnicode;
		return wstrReturn;
	}

	std::string WStringToUTF8(const std::wstring& str)
	{
		char* pElementText = NULL;
		int iTextLen = ::WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)str.c_str(), -1, NULL, 0, NULL, NULL);
		pElementText = new char[iTextLen + 1];
		memset((void*)pElementText, 0, (iTextLen + 1) * sizeof(char));
		::WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)str.c_str(), -1, pElementText, iTextLen, NULL, NULL);
		std::string strReturn(pElementText);
		delete [] pElementText;
		return strReturn;
	}
  1. 目标是否存在
	bool IsTargetExist(const std::string& target)
	{
		return 0 == _waccess(UTF8ToWString(target).c_str(), 0);
	}
  1. 递归创建目录
	bool CreateDir(std::string& dir)
	{
		std::replace(dir.begin(), dir.end(), '/', '\\');
		if (dir.size() < 3) {
			return false;
		}

		if (IsTargetExist(dir)) {
			return true;
		}

		int nPosition = dir.rfind("\\");
		if (-1 != nPosition) {
			std::string parentDir = dir.substr(0, nPosition);
			if (!IsTargetExist(parentDir)) {
				CreateDir(parentDir);
			}
		}
		
		return 0 == _wmkdir(UTF8ToWString(dir).c_str());
	}
  1. GetLastError转换为字符串信息
	std::string getWindowsLastErrString()
	{
		DWORD errCode = GetLastError();
		TCHAR buffer[1024];
		std::string errString;
		if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL, errCode, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
			(LPTSTR)&buffer[0],
			sizeof(buffer), NULL) == 0) {
				errString = getFormatString("Cannot get text error describing (%u)", errCode);
		} else {
			errString = getFormatString("%s (%u)", unicode2ansi(buffer).c_str(), errCode);
		}
		return errString;
	}
  1. 可变参数格式化
	std::string getFormatString(const char *fmt, ...)
	{
		char buffer[1024] = {0};
		va_list vaList;
		va_start(vaList, fmt);
		vsnprintf_s(buffer, _countof(buffer), _TRUNCATE, fmt, vaList);
		va_end(vaList);
		return buffer;
	}
  1. 获取当前应用程序目录
	std::string GetCurrentAppPath()
	{
		wchar_t szFilePath[1024] = {0};
		GetModuleFileNameW(NULL, szFilePath, 1024);
		wchar_t* p = wcsrchr(szFilePath, L'\\');
		if (NULL != p)
		{
			*p = 0;
			return WStringToUTF8(szFilePath);
		}
		return "";
	}
  1. 获取当前应用程序名字
	std::string GetCurrentAppName()
	{
		wchar_t szFilePath[1024] = {0};
		GetModuleFileNameW(NULL, szFilePath, 1024);
		std::wstring wstr(szFilePath);
		if (wstr[wstr.size() - 1] == L'\\') {
			wstr[wstr.size() - 1] = L'\0';
		}
		int pos = wstr.find_last_of(L'\\');
		if (pos != -1) {
			wstr = wstr.substr(pos+1);
		}
		return WStringToUTF8(wstr);
	}
  1. 字符串的拆分/组合
template <typename ITR>
	static inline void SplitStringToIteratorUsing(const std::string& full, const char* delim, ITR& result)
	{
		// Optimize the common case where delim is a single character.
		if (delim[0] != '\0' && delim[1] == '\0') {
			char c = delim[0];
			const char* p = full.data();
			const char* end = p + full.size();
			while (p != end) {
				if (*p == c) {
					++p;
				} else {
					const char* start = p;
					while (++p != end && *p != c);
					*result++ = std::string(start, p - start);
				}
			}
			return;
		}

		std::string::size_type begin_index, end_index;
		begin_index = full.find_first_not_of(delim);
		while (begin_index != std::string::npos) {
			end_index = full.find_first_of(delim, begin_index);
			if (end_index == std::string::npos) {
				*result++ = full.substr(begin_index);
				return;
			}
			*result++ = full.substr(begin_index, (end_index - begin_index));
			begin_index = full.find_first_not_of(delim, end_index);
		}
	}

	void SplitStringUsing(const std::string& full, const char* delim, std::vector<std::string>* result)
	{
			std::back_insert_iterator< std::vector<std::string> > it(*result);
			SplitStringToIteratorUsing(full, delim, it);
	}

	template <typename StringType, typename ITR>
	static inline void SplitStringToIteratorAllowEmpty(const StringType& full, const char* delim, int pieces, ITR& result) 
	{
		std::string::size_type begin_index, end_index;
		begin_index = 0;
		for (int i = 0; (i < pieces-1) || (pieces == 0); i++) {
			end_index = full.find_first_of(delim, begin_index);
			if (end_index == std::string::npos) {
				*result++ = full.substr(begin_index);
				return;
			}
			*result++ = full.substr(begin_index, (end_index - begin_index));
			begin_index = end_index + 1;
		}
		*result++ = full.substr(begin_index);
	}

	void SplitStringAllowEmpty(const std::string& full, const char* delim, std::vector<std::string>* result)
	{
		std::back_insert_iterator< std::vector<std::string> > it(*result);
		SplitStringToIteratorAllowEmpty(full, delim, 0, it);
	}

	template <class ITERATOR>
	static void JoinStringsIterator(const ITERATOR& start, const ITERATOR& end, const char* delim, std::string* result)
	{
		assert(result != NULL);
		result->clear();
		int delim_length = strlen(delim);
		// Precompute resulting length so we can reserve() memory in one shot.
		int length = 0;
		for (ITERATOR iter = start; iter != end; ++iter) {
			if (iter != start) {
				length += delim_length;
			}
			length += iter->size();
		}
		result->reserve(length);
		// Now combine everything.
		for (ITERATOR iter = start; iter != end; ++iter) {
			if (iter != start) {
				result->append(delim, delim_length);
			}
			result->append(iter->data(), iter->size());
		}
	}

	void JoinStrings(const std::vector<std::string>& components, const char* delim, std::string * result)
	{
		JoinStringsIterator(components.begin(), components.end(), delim, result);
	}

	char *FastInt64ToBuffer(__int64 i, char* buffer)
	{
		// We could collapse the positive and negative sections, but that
		// would be slightly slower for positive numbers...
		// 22 bytes is enough to store -2**64, -18446744073709551616.
		static const int kFastInt64ToBufferOffset = 21;
		char* p = buffer + kFastInt64ToBufferOffset;
		*p-- = '\0';
		if (i >= 0) {
			do {
				*p-- = '0' + i % 10;
				i /= 10;
			} while (i > 0);
			return p + 1;
		} else {
			// On different platforms, % and / have different behaviors for
			// negative numbers, so we need to jump through hoops to make sure
			// we don't divide negative numbers.
			if (i > -10) {
				i = -i;
				*p-- = '0' + (char)i;
				*p = '-';
				return p;
			} else {
				// Make sure we aren't at MIN_INT, in which case we can't say i = -i
				i = i + 10;
				i = -i;
				*p-- = '0' + i % 10;
				// Undo what we did a moment ago
				i = i / 10 + 1;
				do {
					*p-- = '0' + i % 10;
					i /= 10;
				} while (i > 0);
				*p = '-';
				return p;
			}
		}
	}
  1. 字符串与整型之间的转换
std::string toStr(const ULONG64 &num)
	{
		return std::to_string(num);
	}

	__int64 toInt64(const std::string &str)
	{
		if (str.empty()) {
			return 0;
		}
		char *end;
		return std::strtoll(str.c_str(), &end, 10);
	}

	ULONG64 fromStr(const std::string &str)
	{
		char *end;
		return std::strtoull(str.c_str(), &end, 10);
	}
  1. 获取系统时间,毫秒
	ULONG64 GetMilliseconds()
	{
		time_t now = time(0);
		SYSTEMTIME sys;
		GetLocalTime( &sys );
		return 1000 * now + sys.wMilliseconds;
	}
  1. 文件相关函数
	UINT32 GetFileSize(const std::string& filePath)
	{
		UINT32 size = 0;
		FILE* pFile = NULL;
		_wfopen_s(&pFile, UTF8ToWString(filePath).c_str(), L"rb");
		if (NULL != pFile)
		{
			fseek(pFile, 0, SEEK_END);
			size = ftell(pFile);
			fclose(pFile);
		}
		return size;
	}

	char* GetFileContent(const std::string& filePath, UINT32& nSize)
	{
		FILE* pFile = NULL;
		_wfopen_s(&pFile, UTF8ToWString(filePath).c_str(), L"rb");
		if (NULL != pFile)
		{
			fseek(pFile, 0, SEEK_END);
			nSize = ftell(pFile);

			char* pContent = NULL;
			if (nSize > 0)
			{
				pContent = new char[nSize + 1];
				memset(pContent, 0, nSize + 1);
				fseek(pFile, 0, SEEK_SET);
				fread(pContent, 1, nSize, pFile);
			}
			fclose(pFile);
			return pContent;
		}
		return NULL;
	}

	char* GetPartFileContent(FILE* pFile, UINT32 nBegin, UINT32 nSize)
	{
		char* pContent = NULL;
		if (NULL != pFile)
		{
			fseek(pFile, nBegin, SEEK_SET);
			pContent = new char[nSize + 1];
			memset(pContent, 0, nSize + 1);
			fread(pContent, 1, nSize, pFile);
		}
		return pContent;
	}
	void GetFileNameFromPath(const std::string& filePath, std::string& fileName, std::string& fileExt)
	{
		UINT32 nSize = filePath.size();
		UINT32 nBegin = filePath.find_last_of("\\");
		if(nBegin == -1)
		{
			nBegin = filePath.find_last_of("/");
		}
		nBegin++;
		fileName = filePath.substr(nBegin, nSize - nBegin);

		int nPose = filePath.find_last_of(".");
		if(nPose >= 0)
		{
			fileExt = filePath.substr(nPose, nSize - nPose);
		}
	}
	bool GetFileNameFromDir(const std::string& fileDir, const std::string& fileExt, std::vector<std::string>& fileList)
	{
		bool ret = false;
		std::string fileName = fileDir + "*" + fileExt;
		wchar_t SearchName[256];
		memset((void*)SearchName, 0, sizeof(SearchName));
		memcpy(SearchName, util::UTF8ToWString(fileName).c_str(), fileName.length() * sizeof(wchar_t));
		WIN32_FIND_DATA FileData;
		HANDLE hFile = FindFirstFile(SearchName, &FileData);
		if(hFile != INVALID_HANDLE_VALUE)
		{
			do
			{
				std::string Name = util::unicode2ansi(FileData.cFileName);
				std::string filePath = fileDir + Name;
				fileList.push_back(filePath);
				ret = true;
			}
			while (FindNextFile(hFile, &FileData));
		}
		return ret;
	}

    bool ifFileInUse(const STRINGUTF8 &filepath)
	{
		HANDLE s_result = CreateFile(UTF8ToWString(filepath).c_str(), GENERIC_READ, 0 , NULL, OPEN_EXISTING, NULL, NULL);
		if (s_result == INVALID_HANDLE_VALUE)
		{
			return true;
		}
		CloseHandle(s_result); 
		return false;
	}

	bool FileIsExist(const STRINGUTF8 &filepath)
	{
		if(_access(filepath.c_str(), 0) != -1)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
  1. 创建UUID
	std::string CreatUUID()
	{
		GUID guid;
		CoCreateGuid(&guid);
		char buf[64] = {0};
		sprintf(buf, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
			guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
			guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
		return std::string(buf);
	}

    std::string uuid()
	{
		UUID uuid;
		UuidCreate(&uuid);
		char *str;
		UuidToStringA(&uuid, (RPC_CSTR*)&str);
		std::string result = str;
		RpcStringFreeA((RPC_CSTR*)&str);
		return result;
	}