我想用base64编码非常小的文件(小于缓冲区)。是的,我知道,有很多base64源代码可用,但我想使用OpenSSL。
我的工作例子:
BIO *bin = BIO_new_file("smallfile.bin", "r");
BIO *b64 = BIO_new(BIO_f_base64());
BIO *bmem = BIO_new(BIO_s_mem());
BIO_push(b64, bmem);
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
char buff[8192];
int n=BIO_read(bin, buff, sizeof(buff));
BIO_write(b64, buff, n);
BIO_flush(b64);
n = BIO_read(bmem, buff, sizeof(buff));
cout << string(buff,n) << endl;
BIO_free_all(bin);
BIO_free_all(b64);如何使链直接读取/写入BIOs,例如: BIO_f_new_file -> BIO_f_base64 ->缓冲区或BIO_s_mem
有可能吗?
发布于 2022-03-06 01:57:38
似乎不可能将源(BIO_s_file)和接收器(BIO_s_mem)组合在一个BIOs链中。它可能需要一个OpenSSL事件循环,因为它不知道需要多少读取才能使用来自源的所有数据。
然而,使用OpenSSL函数对数据进行Base64编码的一个更简单的方法是使用EVP接口
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
return EXIT_FAILURE;
}
FILE *fin = fopen(argv[1], "r");
if (!fin) {
fprintf(stderr, "Unable to open %s\n", argv[1]);
return EXIT_FAILURE;
}
unsigned char inbuff[8192];
int insize = fread(inbuff, 1, sizeof inbuff, fin);
fclose(fin);
// For every 3 bytes of input provided 4 bytes of output data will be produced.
// (Plus a trailing nul)
int outsize = 4 * (insize/3 + 1) + 1;
unsigned char outbuff[outsize];
outsize = EVP_EncodeBlock(outbuff, inbuff, insize);
if (outsize < 0) {
fputs("Encoding error!\n", stderr);
return EXIT_FAILURE;
}
fwrite(outbuff, 1, outsize, stdout);
putchar('\n');
return 0;
}发布于 2022-03-08 01:13:47
回答你的问题,这是不可能的生物。迟早,要从BIO链中提取/推送数据,将需要BIO_read/ part。简单地说,你所拥有的基本上是关于它是如何做的。
话虽如此,但有一点值得一提:您不必通过BIO_read操作将数据从内存BIO中提取出来。它已经在那里,只是等待采取,使用BIO_get_mem_data。一个例子比我刚才说的更能说明这一点,所以.
// like you did before...
char buff[8192];
int n=BIO_read(bin, buff, sizeof buff);
BIO_write(b64, buff, n);
BIO_flush(b64);
// ...but do this to get the final data
char *ptr = NULL;
long len = BIO_get_mem_data(bmem, &ptr);注:未完成内存bio回显int buff的读取。从那里开始,如果您希望数据作为std::string,那么它非常简单,如:
std::string s(ptr, ptr+len);如果您只想将其转储到std:cout (或任何std::ostream&),则只需使用write流方法,而不需要中间字符串对象:
std::cout.write(ptr, len);Fwiw,这是我经常将二进制数据转换为C++ std::string对象的方式。
https://stackoverflow.com/questions/71366090
复制相似问题