c言語でファイルをbase64変換する
c言語でドラッグ&ドロップでbase64のエンコードとデコードしたかったので作りました。
コードは無駄に長くなっています。
前に作ったことはあるのですが、あのときは全てメモリ上で扱っていたためサイズが大きいと扱えなかったため、今回はファイルに3バイトずつ書き込むことで改善しています。
あとシフト演算子の優先順位の考えを理解していなく、結構詰まりました。
もうシフト演算子を使うときは括弧でくくりまくります。
ファイル名やディレクトリの操作を自分で行っているため全角文字が含まれている場合に対応していません。
githubにあげればいいのですが、githubよりこっちの方が見返しやすいので。
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
//0:directory, 1:file
void getFileName(char *filepath,char *getname,int flag)
{
//get size and '\' count
int size=0,slash=0;
for(int i=0;;i++){
if(filepath[i]==0)break;
size++;
if(filepath[i]=='\\')slash++;
}
//1:file
if(flag==1){
//get file name (reverse)
char temp[200]={};
int j=0;
for(int i=size-1;i>0;i--){
if(filepath[i]=='\\')break;
temp[j]=filepath[i];
j++;
}
//put file name
for(int i=0;;i++){
if(j<0 || temp[j-1]=='\"'){
getname[i]=0;
break;
}
getname[i]=temp[j-1];
j--;
}
}else{
//0:directory
int slash2=0;
for(int i=0;;i++){
if(filepath[i]=='\\')slash2++;
if(slash2==slash){
getname[i]=0;
break;
}
getname[i]=filepath[i];
}
}
}
int b64table(int b64)
{
int ascii=-1;
//0~9 48~57 -> 52~61
if (b64 >= 48 && b64 <= 57)ascii = b64 + 4;
//A~Z 65~90 -> 0~25
if (b64 >= 65 && b64 <= 90)ascii = b64 - 65;
//a~z 97~122 -> 26~51
if (b64 >= 97 && b64 <= 122)ascii = b64 - 71;
//'+' 43 -> 62
if (b64 == 43)ascii = b64 + 19;
//'/' 47 -> 63
if (b64 == 47)ascii = b64 + 16;
//'=' 61 -> 0
if (b64 == 61)ascii = 0;
//error
if (b64 == -1)printf("ascii=%d\n",b64);
return ascii;
}
//4 characters(4*6=24 bits)
void b64decode(char *fname)
{
FILE *fp,*fp2;
fp=fopen(fname,"rb");
char fname2[200],fname3[200];
getFileName(fname,fname2,0);
getFileName(fname,fname3,1);
strcat(fname2,"\\b64de_");
strcat(fname2,fname3);
fp2=fopen(fname2,"wb");
int de1,de2,de3;
while(1){
int a=fgetc(fp);
if(a==-1)break;
int b=fgetc(fp);
int c=fgetc(fp);
int d=fgetc(fp);
de1=(b64table(a)<<2)+(b64table(b)>>4);
de2=((b64table(b)&0b1111)<<4)+(b64table(c)>>2);
de3=((b64table(c)&0b11)<<6)+b64table(d);
fputc(de1,fp2);
fputc(de2,fp2);
fputc(de3,fp2);
}
fclose(fp);
fclose(fp2);
}
//3 characters(3*8=24 bits)
void b64encode(char *fname)
{
char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
FILE *fp,*fp2;
fp=fopen(fname,"rb");
char fname2[200],fname3[200];
getFileName(fname,fname2,0);
getFileName(fname,fname3,1);
strcat(fname2,"\\b64en_");
strcat(fname2,fname3);
fp2=fopen(fname2,"wb");
int en1,en2,en3,en4;
while(1){
int a=fgetc(fp);
if(a==-1)break;
int b=fgetc(fp);
if(b==-1){
en1=base64[a>>2];
en2=base64[(a&0b11)<<4];
fputc(en1,fp2);
fputc(en2,fp2);
fputc('=',fp2);
fputc('=',fp2);
break;
}
int c=fgetc(fp);
if(c==-1){
en1=base64[a>>2];
en2=base64[((a&0b11)<<4)+(b>>4)];
en3=base64[(b&0b1111)<<2];
fputc(en1,fp2);
fputc(en2,fp2);
fputc(en3,fp2);
fputc('=',fp2);
break;
}
en1=base64[a>>2];
en2=base64[((a&0b11)<<4)+(b>>4)];
en3=base64[((b&0b1111)<<2)+(c>>6)];
en4=base64[c&0b111111];
fputc(en1,fp2);
fputc(en2,fp2);
fputc(en3,fp2);
fputc(en4,fp2);
}
fclose(fp);
fclose(fp2);
}
int main(int argc, char *argv[])
{
//D&D default:decode
if(argc==2){
b64decode(argv[1]);
//b64encode(argv[1]);
return 0;
}
puts("D&D default:decode");
puts("decode:0");
puts("encode:1");
puts("format: filepath num");
puts("example: C:\\test.txt 1");
char fname[200];
int f=0;
scanf("%s %d",fname,&f);
if(f==1)b64encode(fname);
else b64decode(fname);
return 0;
}
コメント
0 件のコメント :
コメントを投稿