CBytesUtils.h
#pragma once
#include <stdint.h>
#include <string>
#include <vector>
#include <fstream>
#ifdef _UNICODE
#define _T(x) L ## x
using TCHAR = wchar_t;
#else
#define _T(x) x
using TCHAR = char;
#endif
#ifdef _UNICODE
using _tstring = std::wstring;
using _tfstream = std::wfstream;
#else
using _tstring = std::string;
using _tfstream = std::fstream;
#endif
class CBytesUtils
{
public:
//
// @brief: 将指定地址内存转字节序列
// @param: pData 地址内存
// @param: nSize 内存长度
// @ret: std::vector<uint8_t> 字节序列
static std::vector<uint8_t> BytesFromMemory(
const void* pData,
size_t nSize
);
//
// @brief: 将文件数据转字节序列
// @param: vBytes 字节容器
// @param: strFilePath 文件路径
// @ret: bool 执行结果
static bool BytesFromFile(
std::vector<uint8_t>& vBytes,
const _tstring& strFilePath
);
//
// @brief: 十六进制字符串转字节序列
// @param: strInput 十六进制字符串
// @ret: std::vector<uint8_t> 字节序列
static std::vector<uint8_t> BytesFromHexString(
const _tstring& strInput
);
//
// @brief: 字节序列转字符串
// @param: vBytes 字节容器
// @param: nLineSize 每行转换字节数
// @param: strDelimiter 字符分隔
// @param: strPrefix 字符前缀
// @param: strLinePrefix 单行前缀
// @param: strReturn 转行内容
// @ret: _tstring 执行结果字符串
static _tstring BytesFormat(
const std::vector<uint8_t>& vBytes,
size_t nLineSize = 16,
const _tstring& strDelimiter = _T(""),
const _tstring& strPrefix = _T(""),
const _tstring& strLinePrefix = _T(""),
const _tstring& strReturn = _T("\r\n")
);
//
// @brief: 字节序列存到文件
// @param: strFilePath 文件路径
// @param: vBytes 字节容器
// @ret: bool 执行结果
static bool BytesToFile(
const _tstring& strFilePath,
const std::vector<uint8_t>& vBytes
);
//
// @brief: 指定地址内存存到文件
// @param: strFilePath 文件路径
// @param: pData 地址内存
// @param: nSize 内存长度
// @ret: bool 执行结果
static bool MemoryToFile(
const _tstring& strFilePath,
const void* pData,
size_t nSize
);
//
// @brief: 字节序列转字符串存到文件
// @param: strFilePath 文件路径
// @param: vBytes 字节容器
// @param: nLineSize 每行转换字节数
// @param: strDelimiter 字符分隔
// @param: strPrefix 字符前缀
// @param: strLinePrefix 单行前缀
// @param: strReturn 转行内容
// @ret: bool 执行结果
static bool BytesFormatToFile(
const _tstring& strFilePath,
const std::vector<uint8_t>& vBytes,
size_t nLineSize = 16,
const _tstring& strDelimiter = _T(""),
const _tstring& strPrefix = _T(""),
const _tstring& strLinePrefix = _T(""),
const _tstring& strReturn = _T("\r\n")
);
//
// @brief: 格式化的字符串转字节序列
// @param: strFilePath 文件路径
// @param: strDelimiter 字符分隔
// @param: strPrefix 字符前缀
// @param: strLinePrefix 单行前缀
// @param: strReturn 转行内容
// @ret: std::vector<uint8_t> 字节序列
static std::vector<uint8_t> BytesFormatFromFile(
const _tstring& strFilePath,
const _tstring& strDelimiter = _T(""),
const _tstring& strPrefix = _T(""),
const _tstring& strLinePrefix = _T(""),
const _tstring& strReturn = _T("\r\n")
);
//
// @brief: 格式化的字符串转字节序列
// @param: strInput 格式化的字符串, 如 " .DB $4D,$69,$63,$72,$6F,$73,$6F,$66,$74,$20,$43,$2F,$43,$2B,$2B,$20"
// @param: vBytes 字节容器
// @param: strDelimiter 字符分隔, 如 ","
// @param: strPrefix 字符前缀, 如 "$"
// @param: strLinePrefix 单行前缀, 如 " .DB"
// @param: strReturn 转行内容, 如 "\r\n"
// @ret: std::vector<uint8_t> 字节序列
static std::vector<uint8_t> BytesFromString(
const _tstring& strInput,
const _tstring& strDelimiter = _T(""),
const _tstring& strPrefix = _T(""),
const _tstring& strLinePrefix = _T(""),
const _tstring& strReturn = _T("\r\n")
);
private:
//
// @brief: 分割字符串
// @param: str 待分割字符串
// @param: delim 分割标识字符串
// @ret: std::vector<_tstring> 分割结果
static std::vector<_tstring> SplitStr(const _tstring& str, const _tstring& delim);
};
CBytesUtils.cpp
#include "CBytesUtils.h"
std::vector<uint8_t> CBytesUtils::BytesFromMemory(
const void* pData,
size_t nSize
)
{
std::vector<uint8_t> vResult;
if (nullptr != pData && 0 != nSize)
{
//分配容器内存
vResult.resize(nSize);
const uint8_t* pBytes = reinterpret_cast<const uint8_t*>(pData);
for (size_t i = 0; i < nSize; i++)
{
//直接赋值
vResult[i] = pBytes[i];
}
}
return vResult;
}
bool CBytesUtils::BytesFromFile(
std::vector<uint8_t>& vBytes,
const _tstring& strFilePath
)
{
std::vector<uint8_t> vOutput;
bool bResult = false;
std::fstream inputFile(strFilePath, std::ios::binary | std::ios::in);
if (!inputFile.is_open())
{
return false;
}
//获取文件大小
inputFile.seekg(0, std::ios::end);
std::streampos nSize = inputFile.tellg();
inputFile.seekg(0, std::ios::beg);
do
{
if (nSize <= 0)
{
break;
}
//分配读取缓冲
uint8_t* pByteBuf = new (std::nothrow) uint8_t[nSize];
if (nullptr == pByteBuf)
{
break;
}
//读取文件到缓冲
inputFile.read(reinterpret_cast<char*>(pByteBuf), nSize);
std::streamsize nByteSize = inputFile.gcount();
//分配容器内存
vOutput.resize(nSize);
for (std::streamsize i = 0; i < nByteSize; i++)
{
//直接赋值
vOutput[i] = pByteBuf[i];
}
delete[]pByteBuf;
pByteBuf = nullptr;
bResult = true;
} while (false);
inputFile.close();
if (bResult)
{
vBytes = vOutput;
}
return bResult;
}
std::vector<_tstring> CBytesUtils::SplitStr(const _tstring& str, const _tstring& delim)
{
std::vector<_tstring> vectorOut;
size_t iStart = 0;
size_t iEnd = 0;
while ((iStart = str.find_first_not_of(delim, iEnd)) != _tstring::npos)
{
iEnd = str.find(delim, iStart);
vectorOut.push_back(str.substr(iStart, iEnd - iStart));
}
return vectorOut;
}
std::vector<uint8_t> CBytesUtils::BytesFromString(
const _tstring& strInput,
const _tstring& strDelimiter/* = _T("")*/,
const _tstring& strPrefix/* = _T("")*/,
const _tstring& strLinePrefix/* = _T("")*/,
const _tstring& strReturn/* = _T("\r\n")*/
)
{
_tstring strHexTemp;
size_t strLinePrefixLength = strLinePrefix.size();
size_t strPrefixLength = strPrefix.size();
//单行分离
std::vector<_tstring> vLineContent = SplitStr(strInput, strReturn);
for (const auto& item : vLineContent)
{
//当个元素分离
std::vector<_tstring> vLineItem = SplitStr(item.substr(strLinePrefixLength), strDelimiter);
for (auto chItem : vLineItem)
{
strHexTemp += chItem.substr(strPrefixLength);
}
}
return BytesFromHexString(strHexTemp);
}
std::vector<uint8_t> CBytesUtils::BytesFromHexString(
const _tstring& strInput
)
{
std::vector<uint8_t> vResult;
uint8_t byte = 0;
size_t nIndex = 0;
for (const auto& ch : strInput)
{
uint8_t byteHalf = 0;
if (ch >= _T('0') && ch <= _T('9'))
{
byteHalf = (uint8_t)(ch - _T('0'));
}
else if (ch >= _T('A') && ch <= _T('F'))
{
byteHalf = (uint8_t)(ch - _T('A')) + 10;
}
else if (ch >= _T('a') && ch <= _T('f'))
{
byteHalf = (uint8_t)(ch - _T('a')) + 10;
}
else
{
continue;
}
if (!(nIndex & 0x01))
{
byte = byteHalf << 4;
}
else
{
vResult.push_back(byte |= byteHalf);
}
nIndex++;
}
return vResult;
}
_tstring CBytesUtils::BytesFormat(
const std::vector<uint8_t>& vBytes,
size_t nLineSize/* = 16*/,
const _tstring& strDelimiter/* = _T("")*/,
const _tstring& strPrefix/* = _T("")*/,
const _tstring& strLinePrefix/* = _T("")*/,
const _tstring& strReturn/* = _T("\r\n")*/
)
{
_tstring strHex;
const TCHAR szHex[] = _T("0123456789ABCDEF");
size_t nIndex = 0;
for (const auto& byte : vBytes)
{
if (0 == nIndex)
{
strHex += strLinePrefix;
}
if ((0 != nIndex) && (0 == nIndex % nLineSize))
{
strHex += strReturn;
strHex += strLinePrefix;
}
strHex += strPrefix;
strHex += szHex[byte >> 4];
strHex += szHex[byte & 0x0F];
if (0 != (nIndex + 1) % nLineSize && ((nIndex + 1) != vBytes.size()))
{
strHex += strDelimiter;
}
nIndex++;
}
return strHex;
}
bool CBytesUtils::BytesToFile(
const _tstring& strFilePath,
const std::vector<uint8_t>& vBytes
)
{
return MemoryToFile(strFilePath, vBytes.data(), vBytes.size());
}
bool CBytesUtils::MemoryToFile(
const _tstring& strFilePath,
const void* pData,
size_t nSize
)
{
std::ofstream outputFile(strFilePath, std::ios::binary | std::ios::trunc);
if (!outputFile.is_open())
{
return false;
}
outputFile.write(reinterpret_cast<const char*>(pData), nSize);
outputFile.close();
return true;
}
bool CBytesUtils::BytesFormatToFile(
const _tstring& strFilePath,
const std::vector<uint8_t>& vBytes,
size_t nLineSize/* = 16*/,
const _tstring& strDelimiter/* = _T("")*/,
const _tstring& strPrefix/* = _T("")*/,
const _tstring& strLinePrefix/* = _T("")*/,
const _tstring& strReturn/* = _T("\r\n")*/
)
{
std::ofstream outputFile(strFilePath, std::ios::binary | std::ios::trunc);
if (!outputFile.is_open())
{
return false;
}
_tstring strOut = BytesFormat(vBytes, nLineSize, strDelimiter, strPrefix, strLinePrefix, strReturn);
outputFile.write(reinterpret_cast<const char*>(strOut.c_str()), strOut.size() * sizeof(TCHAR));
outputFile.close();
return true;
}
std::vector<uint8_t> CBytesUtils::BytesFormatFromFile(
const _tstring& strFilePath,
const _tstring& strDelimiter/* = _T("")*/,
const _tstring& strPrefix/* = _T("")*/,
const _tstring& strLinePrefix/* = _T("")*/,
const _tstring& strReturn/* = _T("\r\n")*/
)
{
_tstring strContent;
std::fstream inputFile(strFilePath, std::ios::binary | std::ios::in);
if (!inputFile.is_open())
{
return std::vector<uint8_t>();
}
//获取文件大小
inputFile.seekg(0, std::ios::end);
std::streampos nSize = inputFile.tellg();
inputFile.seekg(0, std::ios::beg);
do
{
if (nSize <= 0)
{
break;
}
TCHAR* pBuf = reinterpret_cast<TCHAR*> (new (std::nothrow) uint8_t[nSize]);
if (nullptr == pBuf)
{
break;
}
inputFile.read(reinterpret_cast<char*>(pBuf), nSize);
inputFile.close();
strContent = pBuf;
delete[]pBuf;
} while (false);
return BytesFromString(strContent, strDelimiter, strPrefix, strLinePrefix, strReturn);
}
测试
#include <iostream>
#include <vector>
#include <stdarg.h>
#include <tchar.h>
#include <thread>
#include <strsafe.h>
#include "Win32Utils/CBytesUtils.h"
#include "Win32Utils/CTimeUtils.h"
int _tmain(int argc, LPCTSTR argv[])
{
setlocale(LC_ALL, "");
std::vector<uint8_t> buffer;
//
int64_t timeBegin = CTimeUtils::GetCurrentTickCount();
CBytesUtils::BytesFromFile(buffer, _T(R"(Win32Utils.exe)"));
CBytesUtils::BytesFormatToFile(_T("out.txt"), buffer, 16, _T(","), _T("$"), _T(" .DB "), _T("\r\n"));
int64_t timeEnd = CTimeUtils::GetCurrentTickCount();
_tprintf(_T("save cost time: %d ms\r\n"), timeEnd - timeBegin);
timeBegin = CTimeUtils::GetCurrentTickCount();
buffer = CBytesUtils::BytesFormatFromFile(_T("out.txt"), _T(","), _T("$"), _T(" .DB "), _T("\r\n"));
CBytesUtils::BytesToFile(_T("out2.exe"), buffer);
timeEnd = CTimeUtils::GetCurrentTickCount();
_tprintf(_T("read cost time: %d ms size: %d\r\n"), timeEnd - timeBegin, buffer.size());
_tprintf(_T("file crc32: %s\n"), CCrc32Utils::GetFileCrc32Str(_T(R"(Win32Utils.exe)"), true).c_str());
return 0;
}