2016-08-26 16 views
0

私は大きなファイルの文字列をC++でデコードしたいと思います。 1827500文字 とファイルは次のとおりです:base64デコードC++行末のバイトの末尾

チェーンのサイズが1370626バイト

私の問題は、デコード機能が動作しないということです。 デコードされたファイルが元のファイルと異なっています。

char *base64_decode(const std::string &input, long *size) 
{ 
    BIO *p_bio_mem = nullptr; 
    BIO *p_bio_b64 = nullptr; 
    char *retrnvalue; 

    p_bio_b64 = BIO_new(BIO_f_base64()); 
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); } 
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length()); 
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); } 
    BIO_push(p_bio_b64, p_bio_mem); 

    // read result from chain 
    // read sequence (reverse to write): buf <<-- p_bio_b64 <<-- p_bio_mem 
    std::vector<char> buf((input.size() * 3/4) + 1); 
    std::string result; 
    for (;;) 
    { 
     auto nread = BIO_read(p_bio_b64, buf.data(), buf.size()); 
     if (nread < 0) { return NULL; //fail} 
     if (nread == 0) { break; } // eof 
     result.append(buf.data(), nread); 
    } 

    BIO_free_all(p_bio_b64); 
    *size = buf.size(); 
    retrnvalue = new char[*size]; 
    memcpy(retrnvalue, buf.data(), *size); 

    return retrnvalue; 
} 

第二:

コードはこちらから:

以下

は私が

まず試した二つの方法があるHow do I base64 encode (decode) in C?

ラインのいくつかの終わりは異なります

Diff with WinMerge

しかし全体ではなくファイル:

Left visualiser of WinMerge diff

あなたはなぜ私に言うことはできますか?そして/または簡単な転送のためにファイルをエンコードする別の方法を教えてください。

私は入力でこれを持っている:drive.google.com/file/d/0B1i4Ez8N86wFblJnaFF6YVNVTWs/view

と私は出力でこれをしたい:drive.google.com/file/d/0B1i4Ez8N86wFdl9OUE5UMFB3R28/view

(申し訳ありませんが2つ以上のリンクを置くことはできません)

PS:「certutil -decode」をバッチでデコードすると問題なく動作します。

解決済み:問題は解決されました。

std::vector<char> buf((input.size() * 3/4) + 1); 
std::string result; 
for (;;) 
{ 
    auto nread = BIO_read(p_bio_b64, buf.data(), buf.size()); 
    if (nread < 0) { return NULL; } //fail 
    if (nread == 0) { break; } // eof 
    result.append(buf.data(), nread); 
} 

BIO_free_all(p_bio_b64); 
*size = buf.size(); 
retrnvalue = new char[*size]; 
memcpy(retrnvalue, buf.data(), *size); 

return retrnvalue; 

あなたはresultと呼ばれる文字列にデータを読み、あなたはそれを使って何を行うことはありません:BASE64-EDのデータを読み取るためにofstreamのライト機能を

+0

関連情報[EVP Encryption | OpenSSL wikiの「C++プログラム」(http://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#C.2B.2B_Programs)を参照してください。スマートポインタを使用してリソースを管理する方法を示します。 [PKCS7_signの結果をchar *またはstd :: stringに取得する方法](http://stackoverflow.com/a/38079093/608639)も参照してください。 OpenSSLデータ型のスマートポインタの束を提供します。 – jww

+0

1827500をメモリに読み込むことは、デスクトップ上でも問題ありませんが、AndroidまたはiOSデバイスが壊れてしまいます。おそらく、暗号化と復号化(おそらくエンコードとデコード)のストリーミングに切り替える必要があります。 – jww

+0

EVP暗号化ありがとうございます。 このプロジェクトは他のデバイス用ではありません、とにかくありがとうございます – OOM

答えて

0

解決済み:問題は解決されました。 ofstream write関数で修正しました

1

あなたのコードを修正しました。かなり台無しにされています。次に、スクラッチバッファの内容を出力バッファにコピーします。また、sizeポインタを削除して、char*の代わりにstd::stringを返すこともできます。あなたの入力は、その行が問題の原因となります、改行が含まれている場合は

別の可能性のある問題は、ライン

BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 

です。

std::string base64_decode(const std::string &input) 
{ 
    BIO *p_bio_mem = nullptr; 
    BIO *p_bio_b64 = nullptr; 

    p_bio_b64 = BIO_new(BIO_f_base64()); 
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); } 
    if (input.find('\n') == std::string::npos) { 
     BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 
    } 

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length()); 
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); } 
    BIO_push(p_bio_b64, p_bio_mem); 

    std::stringstream result; 
    std::vector<char> buf(1024); 
    while (auto nread = BIO_read(p_bio_b64, buf.data(), buf.size())) 
    { 
     if (nread < 0) { throw std::runtime_error("OMGZ"); } //fail 
     result.write(buf.data(), nread); 
    } 

    BIO_free_all(p_bio_b64); 
    return result.str(); 
} 

LIVE DEMO:次のようになりますよう、すべて一緒に

if (input.find('\n') == std::string::npos) { 
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 
} 

:あなたは改行を含んでも含まなくてもよいの入力で動作するようにしたい場合は、条件付きその行を加える必要があります

また、エラーの場合(リンク先の回答のように)にBIOインスタンスをクリーンアップするためにエラー処理を追加することもできますが、それは間違った結果を引き起こすものではありません。

+0

はい私はデバッグモードです。コードを明瞭にごめんね。しかし、問題は同じままです – OOM

+0

あなたの入力データはすべて1行にあり、改行で終わらないのですか?そうでない場合は、 'BIO_set_flags(p_bio_b64、BIO_FLAGS_BASE64_NO_NL);'行を削除してください。 –

+0

ありがとうございます。 私は行をコメントしようとしましたが、行末がすべて欠落しています。 https://s16.postimg.org/lqnny9qlh/befaft.jpg – OOM

関連する問題