بيانات مخصصة iostream
-
20-09-2019 - |
سؤال
لدي بنية بيانات محددة على أنها
struct myDataStruct
{
int32_t header;
int16_t data[8];
}
وأريد أن آخذ دفق حرف وتحويله إلى تيار MyData. ما فئة الدفق التي يجب أن أقدمها؟ أرغب في إنشاء فئة دفق مخصصة حتى أتمكن من فعل أشياء مثل
myDataStruct myData;
myDataStruct myDataArray[10];
myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
المحلول
بدلاً من myDataStream.get(myData)
, ما تفعله هو الحمل الزائد operator>>
لنوع البيانات الخاص بك:
std::istream& operator>>(std::istream& is, myDataStruct& obj)
{
// read from is into obj
return is;
}
إذا كنت ترغب في القراءة في صفيف ، فما عليك سوى كتابة حلقة:
for( std::size_t idx=0; idx<10; ++idx )
{
myDataStruct tmp;
if( is >> tmp )
myDataArray[idx] = tmp;
else
throw "input stream broken!";
}
باستخدام قالب الوظيفة ، يجب أن تتمكن أيضًا من زيادة تحميل المشغل للصفائف على الجانب الأيمن (لكن هذا لم أجربه أبدًا):
template< std::size_t N >
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N])
{
// use loop as above, using N instead of the 10
}
لكن لا يمكنني أن أقرر ما إذا كان هذا رائعًا أو بائسًا.
نصائح أخرى
إذا كنت تعمل مع مدخلات غير مفيدة ، فيجب عليك القراءة مباشرةً في شكل ثنائي. عادةً ما يمكنك استخدام بعض التوجيهات الخاصة بالمترجم لإنشاء هياكل بيانات بدون حشوة ثم فقط قراءة/الكتابة من ملف.
// Gcc
#pragma pack(1) // option 1: pragmas
struct frame {
std::uint32_t header;
std::uint16_t data[8];
} __attribute((packed)); // option 2: packed attribute
#pragma pack(0)
bool operator==( data const & lhs, data const & rhs )
{
bool result = lhs.header == rhs.header;
for ( int i = 0; i < 8; ++i )
{
result &= lhs.data[i] == rhs.data[i];
}
return result;
}
int main()
{
frame data = { 10, 1, 2, 3, 4, 5, 6, 7, 8 };
std::ofstream out( "data.bin", ofstream::binary );
out.write( reinterpret_cast<char*>(&data), sizeof(data) );
out.close();
std::ifstream in( "data.bin", ifstream::binary );
frame readed;
in.read( reinterpret_cast<char*>(&readed), sizeof(readed) );
in.close();
std::cout << (readed == data) << std::endl; // 1
}
قد يكون توجيه التحويل البرمجي لتعطيل الحشو لـ VS مختلفًا (أعتقد أن توجيهات Pragma تعمل على حد سواء في GCC و VS ، لكنني دائمًا ما استخدمت السمة).