2012-03-08 16 views
6

私は、今日のほとんどのためのオンライン調査しましたが、私はいくつかの提案のためにStackOverflowのために回してるので、答えを見つけることができませんでした。イメージファイルを読み込んでC++でメモリ(std :: string)に格納する方法は?

は基本的に、私は、画像ファイルをアップロードするPUTメソッドを実行するために、カール使用するC++のライブラリを持っています。今このライブラリはデータ用のstd :: stringを取ります。ローカルディスクに画像ファイル(jpg、gif、pngなど)があります。

私は(のように、私はPUTメソッドのために、このライブラリーに渡す以外にもそれで何もしない)ファイルの内容を気にしないでください。どのように画像ファイルを読み込んでstd :: stringに格納することができますか?ファイルの内容にNULL終端文字が含まれている場合はどうなりますか?

私が試したコードの一部を追加しようとしましたが、私はここに新しいだと私は適切なフォーマットでここに私のコードを貼り付けするかどうかはわかりません。どんな助けもありがとう。

+0

のコールバックfrunctionでどのようにこれは、単に4つのスペースですべてをインデントします。または、コードを貼り付けてそれを選択し、次に示すようなボタンを押します: '{}'。また、テキストを小さな文字で囲んでインラインでコードを配置することもできます。私は彼らがバックティックと呼ばれると思う。私がこれまで使用してきたすべてのキーボードでは、キーの左上隅にあるキーです。 –

+0

@ベンジャミン:ドイツ語のキーボードレイアウトでは、右上にあり、バックスペースキーの左側にあります。 :)また、Ctrl + Altキーを押して取得する必要があります。いずれの場合でも、 '\'は意味します。 – Xeo

+5

実際に使用するライブラリはバイナリデータを文字列に入れたいのですか?あなたはそれが望むファイル名ではないと確信していますか? 'char'型はほぼすべてのプラットフォーム上のバイトですが、' std :: string'を使用してバイナリデータを格納するのは間違っています。 –

答えて

4

私は考えることができる最も簡単な方法。バイナリモードでファイルを開き、次にすべてをstringstreamに読み込みます。

std::ifstream fin("foo.png", std::ios::in | std::ios::binary); 
std::ostringstream oss; 
oss << fin.rdbuf(); 
std::string data(oss.str()); 
+0

これは私が正確にしたものです。バイナリデータの一部だけをアップロードしたように見えるので、うまくいきませんでした。 –

2
std::ifstream fin("foo.png", std::ios::binary); 
std::string data; 
data.reserve(1000000); 
std::copy(std::istreambuf_iterator<char>(fin), 
      std::istreambuf_iterator<char>(), 
      std::back_inserter(data)); 

次のようなコードでstd::stringに画像ファイルを読み込むことができます。 reserveメソッドのパラメータをファイルサイズの99%より大きくするように調整します。ゼロバイト(NULLターミネータと呼ばれる)は、ifstreamstringの両方で正しく処理されます。


私は、バイナリファイルの読み込みのいくつかの方法が比較される良いarticleを見つけました。ここでは、その記事から最速の方法です:

std::ifstream fin("foo.png", std::ios::binary); 
fin.seekg(0, std::ios::end); 
std::string data; 
data.resize(fin.tellg()); 
fin.seekg(0, std::ios::beg); 
fin.read(&data[0], data.size()); 

そしてここでは、最短1です:

std::ifstream fin("foo.png", std::ios::binary); 
std::string data((std::istreambuf_iterator<char>(fin)), 
       std::istreambuf_iterator<char>()); 

更新

このような何かがコールバックを供給するために使用することができます機能(私はそれをテストしていない):

std::ifstream fin("foo.png", std::ios::binary); 
fin.seekg(0, std::ios::end); 
... 
curl_easy_setopt(m_ctx, CURLOPT_INFILESIZE, fin.tellg()); 
curl_easy_setopt(m_ctx, CURLOPT_READDATA,  (void *)&fin); 
fin.seekg(0, std::ios::beg); 
... 
static size_t put_callback(void *ptr, size_t size, size_t nmemb, void *data){ 
    std::ifstream* in = static_cast<std::ifstream*>(data); 
    if(in->eof()) return 0; 
    in->read((char *)ptr, size*nmemb); 
    return in->gcount(); 
} 
+0

私は昨日自分のコードで短絡したバージョンを試しましたが、これもうまくいきませんでした。私は今日ここに自分のコードを取得しようとするので、私はこれについてより多くの助けを得ることができます。 –

2

ライブラリがここにコードを貼り付けるには「データ」は、ファイル内容

stringstream data_stream.str(data.c_str()); 
curl_easy_setopt(m_ctx, CURLOPT_UPLOAD,  1L); 
curl_easy_setopt(m_ctx, CURLOPT_PUT,   1L); 
curl_easy_setopt(m_ctx, CURLOPT_INFILESIZE, data.length()); 
curl_easy_setopt(m_ctx, CURLOPT_READFUNCTION, put_callback); 
curl_easy_setopt(m_ctx, CURLOPT_READDATA,  (void *)&data_stream); 
curl_easy_setopt(m_ctx, CURLOPT_WRITEFUNCTION, get_callback); 
curl_easy_setopt(m_ctx, CURLOPT_WRITEDATA,  (void *)&m_request_response); 

をとして渡された文字列であるPUT呼び出しを行うと、ここでcurlopt_readfunction

static size_t put_callback(void *ptr, size_t size, size_t nmemb, void *data){ 

    stringstream *output_stream; 
    int   retval; 

    output_stream = (stringstream *) data; 

    if(output_stream->eof()) return 0; 

    retval = min(size*nmemb,output_stream->str().size()); 
    output_stream->read((char *)ptr, retval); 

    //return the number of bytes processed 
    return retval; 
} 
+0

少なくとも、http://stackoverflow.com/questions/9612121/how-to-read-image-files-and-store-it-in-memorystdstring-in-c/9623954#9623954によれば、文字列は0バイトを格納します。 hm。 –

+0

はい、文字列に0バイトを格納できます。バグはあなたのコードの最初の行にあります: 'data.c_str()'。ここでは、ゼロ終了文字列がcharポインタとして渡されます。したがって、文字列は最初のゼロバイトでトリムされます。不要な 'c_str()'を取り除くか、コールバックでBenjaminのメソッドの 'stringstream'を使うか、単に' ifstream'を開いてコールバックで使うことができます。 –

+0

あなたは正しいです。私はコールバック関数を書き直す必要があると思います。 –

関連する問題