二进制字节文本转换

2023-12-21 17:23:38

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

文章来源:https://blog.csdn.net/Flame_Cyclone/article/details/135132553
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。