【C++】base64でバイナリデータをascii文字列に変換する
タイトルの通り。以下コード
ヘッダーファイル
//mybase64.hpp
#include<string>
//binary -> ascii
std::string base64encode(const std::string &str){
static const char cvt[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string res;
uint8_t phase=0;
uint8_t b;
for(char ch : str){
switch(phase){
case 0:
{
b = ch>>2 & 0b111111;
res+=cvt[b];
b = (ch&0b11)<<4;
} break;
case 1:
{
b += ch>>4 & 0b1111;
res+=cvt[b];
b = (ch&0b1111)<<2;
} break;
case 2:
{
b += ch>>6 & 0b11;
res+=cvt[b];
b = ch&0b111111;
res+=cvt[b];
b = 0;
} break;
}
phase=(phase+1)%3;
}
if(phase>0){
res+=cvt[b];
}
if(res.length()%4>0){
for(int i=res.length()%4; i<4; i++){
res+='=';
}
}
return res;
}
//ascii -> binary
std::string base64decode(const std::string &str){
std::string res;
uint8_t phase=0;
char b;
uint8_t tmp;
for(char ch : str){
uint8_t tmp=0;
if(ch>='A' && ch<='Z'){
tmp=ch-'A';
}else if(ch>='a' && ch<='z'){
tmp=ch-'a'+26;
}else if(ch>='0' && ch<='9'){
tmp=ch-'0'+52;
}else if(ch=='+'){
tmp=62;
}else if(ch=='/'){
tmp=63;
}else if(ch=='='){
if(phase==1) res += b;
break;
}else{
res="";
phase=0;
break;
}
switch(phase){
case 0:
{
b = tmp<<2;
}break;
case 1:
{
b += tmp>>4 & 0b11;
res += b;
b = (tmp&0b1111)<<4;
}break;
case 2:
{
b += tmp>>2 & 0b1111;
res += b;
b = (tmp&0b11)<<6;
}break;
case 3:
{
b += tmp & 0b111111;
res += b;
}break;
}
phase=(phase+1)%4;
}
return res;
}
バイナリデータの入出力もstd::string
でやってるけど、
1byteずつデータ処理できるならvector<char>
とかvector<uint8_t>
とかなんでもいいと思う。
8bitずつ区切られたデータの並びから6bitずつ取り出していくので、ちょっと面倒くさい。
プログラム
文字列
//sample1.cpp
#includ<iostream>
#include<string>
#include"mybase64.hpp"
int main(){
std::string a="Hello, World!";
std::string b=base64encode(s);
std::string c=base64decode(e);
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
return 0;
}
//出力
//Hello, World!
//SGVsbG8sIFdvcmxkIQ==
//Hello, World!
ファイル読み書き
//sample2.cpp
#include<fstream>
#include<string>
#include"mybase64.hpp"
int main(){
std::ifstream ifs;
std::ofstream ofs;
ifs.open("sample.hoge",std::ios::binary);
//std::ios::binaryでバイナリモード指定
if(!ifs.is_open()){
std::cout << "file not exist\n";
exit(1);
}
std::string in;
while(true){
char ch=ifs.get();
//ifs >> ch; だと正しく読み込めなかった
if(ifs.eof()){
break;
}else{
in+=ch;
}
}
ifs.close();
std::string en=base64encode(in);
std::string de=base64decode(en);
ofs.open("sample_base64encode.txt");
ofs << en;
ofs.close();
ofs.open("sample_base64decode.hoge",std::ios::binary);
ofs.write(de.c_str(),de.length());
//ここも ofs << de; では正しく出力できない
ofs.close();
return 0;
}
参考
#C++
投稿日時 : 2022/01/20 19:51