windows c++ 把文件编码为base64并复制到粘贴板

需要 1 读写粘贴板字符串 2 读文件编码 3 读粘贴板解码

Base3264.h

//
// Created by Amazing on 2024/12/22.
//

#ifndef BASE3264_H
#define BASE3264_H
#include <string>
#include <string.h>

class Base32 {
public:
    static std::string encode(const std::string& data);
    static char* encode(const char* data, size_t dataSize);
    static std::string decode(const std::string& code);
    static char* decode(const char* code, size_t& dataSize);
private:
    static const std::string _32keyStr;
};
const std::string Base32::_32keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";

class Base64 {
public:
    static std::string encode(const std::string& data);
    static char* encode(const char* data, size_t dataSize);
    static std::string decode(const std::string& code);
    static char* decode(const char* code, size_t& dataSize);
private:
    static const std::string _64keyStr;
};
const std::string Base64::_64keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

char* Base32::encode(const char *data, size_t dataSize) {
    if (dataSize == 0) return nullptr;
    // Base32 是每5个bit编码成一个字符,一个char8个bit,那么每次需要拿5个char共40(5*8=40)个bit,然后拆分成8个5bit
    // |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
    // |xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|
    std::string encodeStr;
    size_t codeSize = (dataSize / 5 + (dataSize % 5 ? 1 : 0)) * 8 + 1;
    char* code = (char*) malloc(codeSize);
    memset(code, 0, codeSize);
    unsigned char c5[5], c8[8];
    size_t index = 0, tail = 0;
    while (index < dataSize) {
        memset(c5, 0, sizeof(c5));
        memset(c8, 0, sizeof(c8));
        size_t cSize = 5 < dataSize - index ? 5 : dataSize - index;
        for (int i = 0; i < cSize; ++i) c5[i] = data[index++];
        c8[0]=c5[0]>>3;
        c8[1]=(c5[0]&7)<<2|(c5[1]>>6);
        c8[2]=(c5[1]>>1)&31;
        c8[3]=((c5[1]&1)<<4)|(c5[2]>>4);
        c8[4]=((c5[2]&15)<<1)|(c5[3]>>7);
        c8[5]=(c5[3]>>2)&31;
        c8[6]=((c5[3]&3)<<3)|(c5[4]>>5);
        c8[7]=c5[4]&31;
        for (size_t i=cSize*8/5+1;i<8;++i) c8[i]=32;
        for (int i=0;i<8;++i) code[tail++]=_32keyStr[c8[i]];
    }
    return code;
}

std::string Base32::encode(const std::string &data) {
    // Base32 是每5个bit编码成一个字符,一个char8个bit,那么每次需要拿5个char共40(5*8=40)个bit,然后拆分成8个5bit
    // |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
    // |xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|
    const size_t dataSize = data.size();
    if (dataSize == 0) return "";
    std::string encodeStr;
    size_t codeSize = (data.size() / 5 + (data.size() % 5 ? 1 : 0)) * 8;
    std::string code(codeSize, '\0');
    unsigned char c5[5], c8[8];
    size_t index = 0, tail = 0;
    while (index < dataSize) {
        memset(c5, 0, sizeof(c5));
        memset(c8, 0, sizeof(c8));
        size_t cSize = 5 < dataSize - index ? 5 : dataSize - index;
        for (int i = 0; i < cSize; ++i) c5[i] = data[index++];
        c8[0]=c5[0]>>3;
        c8[1]=(c5[0]&7)<<2|(c5[1]>>6);
        c8[2]=(c5[1]>>1)&31;
        c8[3]=((c5[1]&1)<<4)|(c5[2]>>4);
        c8[4]=((c5[2]&15)<<1)|(c5[3]>>7);
        c8[5]=(c5[3]>>2)&31;
        c8[6]=((c5[3]&3)<<3)|(c5[4]>>5);
        c8[7]=c5[4]&31;
        for (size_t i=cSize*8/5+1;i<8;++i) c8[i]=32;
        for (int i=0;i<8;++i) code[tail++]=_32keyStr[c8[i]];
    }
    return code;
}

char *Base32::decode(const char* code, size_t& dataSize) {
    const size_t codeSize = strlen(code);
    size_t maxDataSize = codeSize * 5 / 8;
    char* data = (char*)malloc(maxDataSize);
    memset(data, 0, maxDataSize);
    unsigned char c5[5], c8[8];
    size_t index = 0;
    dataSize = 0;
    while (index < codeSize) {
        memset(c5, 0, sizeof(c5));
        memset(c8, 0, sizeof(c8));
        size_t cSize = 8 < codeSize - index ? 8 : codeSize - index;
        for (int i = 0; i < cSize; ++i) c8[i] = _32keyStr.find(code[index++]);
        for (int i = cSize; i < 8; ++i) c8[i] = 32;
        c5[0] = (c8[0]<<3)|(c8[1]>>2);
        c5[1] = ((c8[1]&3)<<6)|(c8[2]<<1)|(c8[3]>>4);
        c5[2] = ((c8[3]&15)<<4)|(c8[4]>>1);
        c5[3] = ((c8[4]&1)<<7)|(c8[5]<<2)|(c8[6]>>3);
        c5[4] = ((c8[6]&7)<<5)|c8[7];
        int valiedSize = 7;
        while(valiedSize >= 0 && c8[valiedSize]==32) --valiedSize;
        valiedSize = (valiedSize + 1) * 5 / 8;
        for (int i=0;i<valiedSize;++i) data[dataSize++] = c5[i];
    }
    return data;
}

std::string Base32::decode(const std::string &code) {
    const size_t codeSize = code.size();
    if (codeSize * 5 % 8 != 0) return "";
    size_t maxDataSize = codeSize * 5 / 8;
    std::string data(maxDataSize, '\0');
    unsigned char c5[5], c8[8];
    size_t index = 0, dataSize = 0;
    while (index < codeSize) {
        memset(c5, 0, sizeof(c5));
        memset(c8, 0, sizeof(c8));
        size_t cSize = 8 < codeSize - index ? 8 : codeSize - index;
        for (int i = 0; i < cSize; ++i) c8[i] = _32keyStr.find(code[index++]);
        for (int i = cSize; i < 8; ++i) c8[i] = 32;
        c5[0] = (c8[0]<<3)|(c8[1]>>2);
        c5[1] = ((c8[1]&3)<<6)|(c8[2]<<1)|(c8[3]>>4);
        c5[2] = ((c8[3]&15)<<4)|(c8[4]>>1);
        c5[3] = ((c8[4]&1)<<7)|(c8[5]<<2)|(c8[6]>>3);
        c5[4] = ((c8[6]&7)<<5)|c8[7];
        int valiedSize = 7;
        while(valiedSize >= 0 && c8[valiedSize]==32) --valiedSize;
        valiedSize = (valiedSize + 1) * 5 / 8;
        for (int i=0;i<valiedSize;++i) data[dataSize++] = c5[i];
    }
    data.resize(dataSize);
    return data;
}

char *Base64::encode(const char *data, size_t dataSize) {
    // Base64 是每6个bit编码成一个字符,一个char8个bit,那么每次需要拿3个char共24(3*8=24)个bit,然后拆分成4个6bit
    // |xxxxxxxx|xxxxxxxx|xxxxxxxx|
    // |xxxxxx|xxxxxx|xxxxxx|xxxxxx|
    if (dataSize <= 0) return nullptr;
    size_t codeSize = (dataSize / 3 + (dataSize % 3 ? 1 : 0)) * 4 + 1;
    char* code = (char*)malloc(codeSize);
    memset(code, 0, codeSize);
    unsigned char c3[3], c4[4];
    size_t index = 0, tail = 0;
    while (index < dataSize) {
        memset(c3, 0, sizeof(c3));
        memset(c4, 0, sizeof(c4));
        size_t cSize = 3 < dataSize - index ? 3 : dataSize - index;
        for (int i = 0; i < cSize; ++i) c3[i] = data[index++];
        c4[0] = c3[0] >> 2;
        c4[1] = (c3[0] & 3) << 4 | c3[1] >> 4;
        c4[2] = (c3[1] & 15) << 2 | c3[2] >> 6;
        c4[3] = c3[2] & 63;
        for (size_t i=cSize*4/3+1;i<4;++i) c4[i]=64;
        for (int i=0;i<4;++i) code[tail++]=_64keyStr[c4[i]];
    }
    return code;
}

std::string Base64::encode(const std::string &data) {
    // Base64 是每6个bit编码成一个字符,一个char8个bit,那么每次需要拿3个char共24(3*8=24)个bit,然后拆分成4个6bit
    // |xxxxxxxx|xxxxxxxx|xxxxxxxx|
    // |xxxxxx|xxxxxx|xxxxxx|xxxxxx|
    const size_t dataSize = data.size();
    if (dataSize == 0) return "";
    std::string encodeStr;
    size_t codeSize = (data.size() / 3 + (data.size() % 3 ? 1 : 0)) * 4;
    std::string code(codeSize, '\0');
    unsigned char c3[3], c4[4];
    size_t index = 0, tail = 0;
    while (index < dataSize) {
        memset(c3, 0, sizeof(c3));
        memset(c4, 0, sizeof(c4));
        size_t cSize = 3 < dataSize - index ? 3 : dataSize - index;
        for (int i = 0; i < cSize; ++i) c3[i] = data[index++];
        c4[0] = c3[0] >> 2;
        c4[1] = (c3[0] & 3) << 4 | c3[1] >> 4;
        c4[2] = (c3[1] & 15) << 2 | c3[2] >> 6;
        c4[3] = c3[2] & 63;
        for (size_t i=cSize*4/3+1;i<4;++i) c4[i]=64;
        for (int i=0;i<4;++i) code[tail++]=_64keyStr[c4[i]];
    }
    return code;
}

char *Base64::decode(const char *code, size_t& dataSize) {
    const size_t codeSize = strlen(code);
    if (codeSize * 3 % 4 != 0) return nullptr;
    size_t maxDataSize = codeSize * 3 / 4;
    char* data = (char*)malloc(maxDataSize);
    memset(data, 0, maxDataSize);
    unsigned char c3[3], c4[4];
    size_t index = 0;
    dataSize = 0;
    while (index < codeSize) {
        memset(c3, 0, sizeof(c3));
        memset(c4, 0, sizeof(c4));
        size_t cSize = 4 < codeSize - index ? 4 : codeSize - index;
        for (int i = 0; i < cSize; ++i) c4[i] = _64keyStr.find(code[index++]);
        for (int i = cSize; i < 4; ++i) c4[i] = 64;
        c3[0] = (c4[0] << 2) | (c4[1] >> 4);
        c3[1] = ((c4[1] & 15) << 4) | (c4[2] >> 2);
        c3[2] = ((c4[2] & 3) << 6) | c4[3];
        int valiedSize = 3;
        while(valiedSize >= 0 && c4[valiedSize]==64) --valiedSize;
        valiedSize = (valiedSize + 1) * 6 / 8;
        for (int i=0;i<valiedSize;++i) data[dataSize++] = c3[i];
    }
    return data;
}

std::string Base64::decode(const std::string &code) {
    const size_t codeSize = code.size();
    if (codeSize * 3 % 4 != 0) return "";
    size_t maxDataSize = codeSize * 3 / 4;
    std::string data(maxDataSize, '\0');
    unsigned char c3[3], c4[4];
    size_t index = 0, dataSize = 0;
    while (index < codeSize) {
        memset(c3, 0, sizeof(c3));
        memset(c4, 0, sizeof(c4));
        size_t cSize = 4 < codeSize - index ? 4 : codeSize - index;
        for (int i = 0; i < cSize; ++i) c4[i] = _64keyStr.find(code[index++]);
        for (int i = cSize; i < 4; ++i) c4[i] = 64;
        c3[0] = (c4[0] << 2) | (c4[1] >> 4);
        c3[1] = ((c4[1] & 15) << 4) | (c4[2] >> 2);
        c3[2] = ((c4[2] & 3) << 6) | c4[3];
        int valiedSize = 3;
        while(valiedSize >= 0 && c4[valiedSize]==64) --valiedSize;
        valiedSize = (valiedSize + 1) * 6 / 8;
        for (int i=0;i<valiedSize;++i) data[dataSize++] = c3[i];
    }
    data.resize(dataSize);
    return data;
}

#endif //BASE3264_H

ClipBoard.h

#ifndef CLIPBOARD_H
#define CLIPBOARD_H

#include <windows.h>
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string.h>

using namespace std;

class ClipBoard {
public:
  static bool setText(const std::string& str);
  static bool setText(const char* str);
  static bool getText(std::string& str);
  static bool getText(char*& str);
};

bool ClipBoard::setText(const std::string& str) {
  size_t strSize = str.size();
  HWND hWnd = NULL;
  OpenClipboard( hWnd );//打开剪切板
  EmptyClipboard();//清空剪切板
  HANDLE hHandle = GlobalAlloc(GMEM_FIXED, strSize+1);//分配内存
  char* pData = (char*) GlobalLock(hHandle);//锁定内存,返回申请内存的首地址
  strcpy(pData, str.c_str());
  SetClipboardData(CF_TEXT, hHandle);//设置剪切板数据
  GlobalUnlock(hHandle);//解除锁定
  CloseClipboard();//关闭剪切板
  return true;
}

bool ClipBoard::getText(std::string& str) {
  HWND hWnd = NULL;
  OpenClipboard(hWnd);
  if (!IsClipboardFormatAvailable(CF_TEXT)) {
    CloseClipboard();
    return false;
  }
  HANDLE h = GetClipboardData(CF_TEXT);//获取剪切板数据
  char* p = (char*)GlobalLock(h);
  // unsigned long long dataSize = GlobalSize(h);
  str = std::string(p);
  GlobalUnlock(h);
  CloseClipboard();
  return true;
}

bool ClipBoard::setText(const char* str) {
  size_t strSize = strlen(str);
  HWND hWnd = NULL;
  OpenClipboard( hWnd );//打开剪切板
  EmptyClipboard();//清空剪切板
  HANDLE hHandle = GlobalAlloc(GMEM_FIXED, strSize+1);//分配内存
  char* pData = (char*) GlobalLock(hHandle);//锁定内存,返回申请内存的首地址
  strcpy(pData, str);
  SetClipboardData(CF_TEXT, hHandle);//设置剪切板数据
  GlobalUnlock(hHandle);//解除锁定
  CloseClipboard();//关闭剪切板
  return true;
}

bool ClipBoard::getText(char*& str) {
  HWND hWnd = NULL;
  OpenClipboard(hWnd);
  if (!IsClipboardFormatAvailable(CF_TEXT)) {
    CloseClipboard();
    return false;
  }
  HANDLE h = GetClipboardData(CF_TEXT);//获取剪切板数据
  char* p = (char*)GlobalLock(h);
  unsigned long long dataSize = GlobalSize(h);
  if (str != nullptr) free(str);
  str = (char*)malloc(dataSize+1);
  memset(str, 0, dataSize+1);
  strcpy(str, p);
  GlobalUnlock(h);
  CloseClipboard();
  return true;
}
#endif //CLIPBOARD_H

EncodeFileDecodeClipBoard.h

#include "Base3264.h"
#include "ClipBoard.h"

#include <stdio.h>
#include <filesystem>
#include <fstream>

unsigned long long getFileSize(std::filesystem::path path) {
  if (std::filesystem::status(path).type() != std::filesystem::file_type::regular) return -1;
  return std::filesystem::file_size(path);
}

bool encodeFileToClipBoard(const std::string& filePathStr) {
  std::filesystem::path filePath(filePathStr);
  if (!std::filesystem::exists(filePath) || !std::filesystem::is_regular_file(filePath)) {
    return false;
  }
  filePath = std::filesystem::absolute(filePath);
  size_t fileSize = getFileSize(filePath);
  if (fileSize > 20 * 1024 * 1024) {
    printf("file size too big! %d Mb\n", fileSize/1024/1024);
    return false;
  }
  if (fileSize <= 0) {
    printf("file not data!\n");
    return false;
  }
  std::ifstream ifs;
  ifs.open(filePath.string(), std::ios_base::in|std::ios::binary);
  if (!ifs.is_open()) {
    printf("can't open file %s\n", filePath.c_str());
    return false;
  }
  char* data = (char*)malloc(fileSize);
  ifs.read(data, fileSize);
  ifs.close();
  // encode file
  char* encodeData = Base64::encode(data, fileSize);
  free(data);
  ClipBoard::setText(encodeData);
  free(encodeData);
  return true;
}

bool decodeClipBoardToFile(const std::string& filePathStr) {
  char* data = nullptr;
  if (!ClipBoard::getText(data)) {
    return false; 
  }
  size_t dataSize = 0;
  char* decodeData = Base64::decode(data, dataSize);
  free(data);
  std::ofstream ofs;
  ofs.open(filePathStr, std::ios_base::out|std::ios::binary);
  if (!ofs.is_open()) {
    free(decodeData);
    return false;
  }
  ofs.write(decodeData, dataSize);
  free(decodeData);
  ofs.close();
  return true;
}

main.cpp

#include "EncodeFileDecodeClipBoard.h"

#include <stdio.h>
#include <filesystem>

int main (int argc, char *argv[]) {
  if (argc != 3) {
    printf("encode.exe -i <inputFilePath>\n");
    printf("encode.exe -o <outputFilePath>\n");
    return 0;
  }
  std::string op(argv[1]);
  std::string filePathStr(argv[2]);
  std::filesystem::path filePath(filePathStr);
  filePath = std::filesystem::absolute(filePath);
  filePathStr = filePath.string();
  printf("%s\n", filePathStr.c_str());

  // copy to clipBoard
  if (op == "-i") {
    if (!std::filesystem::exists(filePath) || !std::filesystem::is_regular_file(filePath)) {
      printf("please input vailed filePath!\n");
      return 0;
    }
    encodeFileToClipBoard(filePathStr);
  } else if (op == "-o") {
    decodeClipBoardToFile(filePathStr);
  } else printf("wrong op: %s\n", op.c_str());
  return 0;
}
文章目录