std :: istreamからstd :: stringに直接読み込む
質問
とにかく、一時バッファを作成せずに、既知のバイト数を直接std :: stringに読み込む方法はありますか?
たとえば、現在私はそれを行うことができます
boost::uint16_t len;
is.read((char*)&len, 2);
char *tmpStr = new char[len];
is.read(tmpStr, len);
std::string str(tmpStr, len);
delete[] tmpStr;
解決
std :: string
には、使用できる resize
関数、または同じことを行うコンストラクターがあります:
boost::uint16_t len;
is.read((char*)&len, 2);
std::string str(len, '\0');
is.read(&str[0], len);
これはテストされていません。文字列が連続したストレージを持つことが義務付けられているかどうかはわかりません。
他のヒント
copy_nとinsert_iteratorの組み合わせを使用できます
void test_1816319()
{
static char const* fname = "test_1816319.bin";
std::ofstream ofs(fname, std::ios::binary);
ofs.write("\x2\x0", 2);
ofs.write("ab", 2);
ofs.close();
std::ifstream ifs(fname, std::ios::binary);
std::string s;
size_t n = 0;
ifs.read((char*)&n, 2);
std::istream_iterator<char> isi(ifs), isiend;
std::copy_n(isi, n, std::insert_iterator<std::string>(s, s.begin()));
ifs.close();
_unlink(fname);
std::cout << s << std::endl;
}
コピー、ハッキング、オーバーランの可能性、未定義の動作はありません。
getlineのようなものを使用できます:
#include <iostream>
#include <string>
using namespace std;
int main () {
string str;
getline (cin,str,' ');
}
バッファとしてベクトルを使用します。
boost::uint16_t len;
is.read((char*)&len, 2); // Note if this file was saved from a different architecture
// then endianness of these two bytes may be reversed.
std::vector buffer(len); // uninitialized.
is.read(&buffer[0], len);
std::string str(buffer.begin(),buffer.end());
おそらく、バッファとして文字列を使用することでうまくいくでしょう(GManによって説明されています)。文字列メンバーが連続した場所にあることは標準では保証されていません(したがって、現在の実装を確認し、別のコンパイラ/プラットフォームに移植するときに確認が必要な大きなコメントを入れてください)。
コード長を最適化しているだけですか、それともここにコピーを保存しようとしていますか?一時バッファーの何が問題になっていますか?
文字列の保護を実際に回避しているのは、そのように直接記述しようとすることです。アプリケーションのパフォーマンスに何らかの影響があることがわかったため、std :: stringへのコピーのパフォーマンスが心配な場合は、char *を直接操作します。
編集:もっと見る... コピーせずにchar *からstd :: stringを初期化する
2番目の回答では、達成しようとしているものを達成できない(つまり、コピーするchar *を反復せずにstd :: stringを設定する)ことはできないとかなりフラットに述べられています。
ロードルーチンを見て(おそらくここに投稿しますか?)、割り当てを最小限に抑えます。newとdeleteは確かに無料ではないため、バッファを継続的に再作成する必要がない場合は、少なくとも時間を節約できます。 。私はいつもバッファを0またはnullで配列の最初のインデックスを終端するmemsetすることでそれを消去するのに役立つと思いますが、アルゴリズムに自信があればパフォーマンスの利益のためにそのコードをすぐに削除することができます。
簡単な方法は次のとおりです。
std::istream& data
const size_t dataSize(static_cast<size_t>(data.rdbuf()->in_avail()));
std::string content;
content.reserve( dataSize);
data.read(&content[0], dataSize);