سؤال

فيما يبدو boost::asio::async_read لا يحب الأوتار، باعتبارها الحمولة الزائدة الوحيدة لـ boost::asio::buffer يسمح لي بالإنشاء const_buffers، لذلك أنا عالق في قراءة كل شيء في Streambuf.
الآن أريد نسخ محتويات Streambuf إلى سلسلة، ولكن من الواضح أنه يدعم الكتابة إلى char* فقط (sgetn())، وإنشاء istream باستخدام Streambuf واستخدامه getline().

هل هناك أي طريقة أخرى لإنشاء سلسلة بمحتويات Streambufs دون النسخ المفرط؟

هل كانت مفيدة؟

المحلول

وأنا لا أعرف ما إذا كان ذلك ضروريا كما "<م> المفرط النسخ "، ولكن يمكنك استخدام stringstream:

std::ostringstream ss;
ss << someStreamBuf;
std::string s = ss.str();

ومثل، لقراءة كل شيء من ستدين إلى سلسلة، لا

std::ostringstream ss;
ss << std::cin.rdbuf();
std::string s = ss.str();

وبدلا من ذلك، يمكنك أيضا استخدام istreambuf_iterator. سيكون لديك لقياس ما إذا كان هذا أو الطريقة المذكورة أعلاه هي أسرع - أنا لا أعرف

std::string s((istreambuf_iterator<char>(someStreamBuf)), 
               istreambuf_iterator<char>());

لاحظ أن someStreamBuf أعلاه من المفترض أن تمثل streambuf*، حتى تأخذ عنوانه حسب الاقتضاء. أيضا لاحظ الأقواس إضافية حول الوسيطة الأولى في المثال الأخير، بحيث لا تفسر على أنها إعلان وظيفة عودته سلسلة وأخذ مكرر ومؤشر وظيفة أخرى ( "تحليل أكثر المحيرة").

نصائح أخرى

إنه حقًا مدفون في المستندات...

منح boost::asio::streambuf b, ، مع size_t buf_size ...

boost::asio::streambuf::const_buffers_type bufs = b.data();
std::string str(boost::asio::buffers_begin(bufs),
                boost::asio::buffers_begin(bufs) + buf_size);

وهناك احتمال آخر مع boost::asio::streambuf هو استخدام boost::asio::buffer_cast<const char*>() بالتزامن مع boost::asio::streambuf::data() وboost::asio::streambuf::consume() مثل هذا:

const char* header=boost::asio::buffer_cast<const char*>(readbuffer.data());
//Do stuff with header, maybe construct a std::string with std::string(header,header+length)
readbuffer.consume(length);

وهذا لن ينجح مع streambufs طبيعي ويمكن أن تعتبر قذرة، ولكن يبدو أن أسرع طريقة للقيام بذلك.

لboost::asio::streambuf قد تجد حلا من هذا القبيل:

    boost::asio::streambuf buf;
    /*put data into buf*/

    std::istream is(&buf);
    std::string line;
    std::getline(is, line);

وطباعة سلسلة:

    std::cout << line << std::endl;

وأنت قد تجد هنا: HTTP: // شبكة الاتصالات العالمية. boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

ويمكن للمرء أيضا الحصول على الأحرف من asio::streambuf باستخدام std::basic_streambuf::sgetn:

asio::streambuf in;
// ...
char cbuf[in.size()+1]; int rc = in.sgetn (cbuf, sizeof cbuf); cbuf[rc] = 0;
std::string str (cbuf, rc);

والسبب يمكنك فقط إنشاء const_buffer من الأمراض المنقولة جنسيا :: سلسلة لأن الأمراض المنقولة جنسيا :: سلسلة صراحة لا يدعم الكتابة القائمة على مؤشر مباشرة في عقده. هل يمكن أن تفعل شيئا الشر مثل تغيير حجم سلسلة الخاص بك إلى حجم معين، ثم const_cast وconstness من c_str () والتعامل معها مثل شار الخام * عازلة، ولكن هذا غير مطيع جدا وسوف تحصل في ورطة في يوم من الأيام.

وأنا استخدم الأمراض المنقولة جنسيا :: ناقلات للمخازن بلدي لطالما متجه لا تغيير حجم (أو كنت حذرا في التعامل مع تغيير حجم)، يمكنك أن تفعل الكتابة مؤشر مباشرة على ما يرام. إذا كنت بحاجة إلى بعض البيانات باعتبارها الأمراض المنقولة جنسيا :: سلسلة، لا بد لي من نسخ بها، ولكن الطريقة التي أتعامل مع زملائي مخازن قراءة، أي شيء يحتاج إلى أخر ما وراء الاستدعاء قراءة يحتاج ليتم نسخها خارج بغض النظر.

والجواب أبسط سيكون لتحويله في std::string والتلاعب به بعض ما مثل هذا

 std::string buffer_to_string(const boost::asio::streambuf &buffer)
 {
  using boost::asio::buffers_begin;
  auto bufs = buffer.data();
  std::string result(buffers_begin(bufs), buffers_begin(bufs) + buffer.size());
 return result;
}

وإعطاء رمز موجزة جدا للقيام بهذه المهمة.

وأعتقد أنه من أكثر مثل:


streambuf.commit( number_of_bytes_read );

istream istr( &streambuf );
string s;
istr >> s;

وأنا لم ينظر إلى رمز basic_streambuf، ولكن أعتقد أنه يجب أن تكون نسخة واحدة فقط في السلسلة.

واختبرت الإجابة الأولى وحصلت على خطأ المترجم عند ترجمة باستخدام "ز ++ -std = ج ++ 11" ما عملت بالنسبة لي هو:

        #include <string>
        #include <boost/asio.hpp>
        #include <sstream>           
        //other code ...
        boost::asio::streambuf response;
        //more code
        std::ostringstream sline;
        sline << &response; //need '&' or you a compiler error
        std::string line = sline.str(); 

وهذا تجميعها وركض.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top