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