বস্তুগুলিকে সিরিয়ালাইজ করতে আপনি ব্যবহার করতে পারেন এমন সাধারণ প্যাটার্ন রয়েছে। মৌলিক আদিম হ'ল এই দুটি ফাংশন যা আপনি পুনরাবৃত্তিকারীদের কাছ থেকে পড়তে এবং লিখতে পারেন:
template <class OutputCharIterator>
void putByte(char byte, OutputCharIterator &&it)
{
*it = byte;
++it;
}
template <class InputCharIterator>
char getByte(InputCharIterator &&it, InputCharIterator &&end)
{
if (it == end)
{
throw std::runtime_error{"Unexpected end of stream."};
}
char byte = *it;
++it;
return byte;
}
তারপরে সিরিয়ালাইজেশন এবং ডিসরিয়ালাইজেশন ফাংশনগুলি নিদর্শন অনুসরণ করে:
template <class OutputCharIterator>
void serialize(const YourType &obj, OutputCharIterator &&it)
{
}
template <class InputCharIterator>
void deserialize(YourType &obj, InputCharIterator &&it, InputCharIterator &&end)
{
}
ক্লাসগুলির জন্য আপনি ADL ব্যবহার করে ওভারলোডটি সন্ধানের জন্য বন্ধু ফাংশন প্যাটার্নটি ব্যবহার করতে পারেন:
class Foo
{
int internal1, internal2;
template <class OutputCharIterator>
friend void serialize(const Foo &obj, OutputCharIterator &&it)
{
}
};
তারপরে আপনার প্রোগ্রামে আপনি সিরিয়ালীকরণ করতে এবং এই জাতীয় কোনও ফাইলটিতে আপত্তি করতে পারেন:
std::ofstream file("savestate.bin");
serialize(yourObject, std::ostreambuf_iterator<char>(file));
তারপরে পড়ুন:
std::ifstream file("savestate.bin");
deserialize(yourObject, std::istreamBuf_iterator<char>(file), std::istreamBuf_iterator<char>());
আমার পুরানো উত্তর এখানে:
সিরিয়ালাইজেশন মানে আপনার বস্তুকে বাইনারি ডেটাতে পরিণত করা। যদিও ডিসরিয়ালাইজেশন অর্থ ডেটা থেকে কোনও বস্তু পুনরুদ্ধার।
সিরিয়ালাইজ করার সময় আপনি কোনও uint8_t
ভেক্টরে বাইটস চাপছেন। আনসিরিয়ালাইজ করার সময় আপনি কোনও uint8_t
ভেক্টর থেকে বাইট পড়ছেন ।
স্টাফিয়াল সিরিয়ালকরণের সময় আপনি নিখুঁত নিদর্শনগুলি নিয়োগ করতে পারেন।
প্রতিটি সিরিয়ালাইজযোগ্য শ্রেণীর একটি serialize(std::vector<uint8_t> &binaryData)
বা অনুরূপ স্বাক্ষরযুক্ত ফাংশন থাকা উচিত যা সরবরাহিত ভেক্টরটিতে এর বাইনারি উপস্থাপনা লিখবে। তারপরে এই ফাংশনটি এই ভেক্টরটিকে তার সদস্যের ক্রমিক ক্রিয়াকলাপে নামিয়ে দিতে পারে যাতে তারা এতে তাদের স্টাফও লিখতে পারে।
যেহেতু ডেটা উপস্থাপনা বিভিন্ন আর্কিটেকচারে আলাদা হতে পারে। কীভাবে ডেটা উপস্থাপন করবেন তা আপনার একটি স্কিম খুঁজে বের করতে হবে।
বেসিকগুলি থেকে শুরু করা যাক:
পূর্ণসংখ্যার ডেটা ক্রমিক করা হচ্ছে
সামান্য এন্ডিয়ান ক্রমে বাইটগুলি লিখুন। অথবা আকারের বিষয়ে বিবেচনায় থাকলে ভেরেন্টের উপস্থাপনা ব্যবহার করুন।
সামান্য এন্ডিয়ান ক্রমে সিরিয়ালাইজেশন:
data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);
সামান্য এডিয়ান অর্ডার থেকে ডিসরিয়ালেশন:
integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
ভাসমান পয়েন্ট ডেটা সিরিয়ালাইজ করা হচ্ছে
যতদূর আমি জানি আইইইই 754 এর একচেটিয়া রয়েছে। আমি মূলধারার এমন কোনও স্থাপত্য সম্পর্কে জানি না যা ভাসমানদের জন্য অন্য কিছু ব্যবহার করবে। বাইট ক্রম হ'ল একমাত্র জিনিস যা আলাদা হতে পারে। কিছু স্থাপত্যগুলি সামান্য এডিয়ান ব্যবহার করে, অন্যরা বড় অ্যান্ডিয়ান বাইট ক্রম ব্যবহার করে। এর অর্থ আপনি গ্রহণের শেষে বাইটগুলি কীভাবে উচ্চতর করবেন সে সম্পর্কে আপনাকে সতর্ক হওয়া দরকার। আর একটি পার্থক্য হ'ল ডেনরমাল এবং অনন্ত এবং এনএএন মানগুলি পরিচালনা করা। তবে যতক্ষণ আপনি এই মানগুলি এড়িয়ে যান ততক্ষণ আপনার উচিত ঠিক।
ক্রমিকায়ন:
uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...
ডিসরিয়ালাইজেশন এটি পিছনে করছে। আপনার আর্কিটেকচারের বাইট অর্ডারটি মাইন্ড করুন!
সিরিয়ালিং স্ট্রিং
প্রথমে আপনাকে একটি এনকোডিংয়ে সম্মত হওয়া দরকার। ইউটিএফ -8 সাধারণ। তারপরে এটিকে দৈর্ঘ্যের উপসর্গযুক্ত পদ্ধতি হিসাবে সঞ্চয় করুন: প্রথমে আপনি উপরে উল্লিখিত একটি পদ্ধতি ব্যবহার করে স্ট্রিংয়ের দৈর্ঘ্য সংরক্ষণ করুন, তারপরে বাই-বাই-বাই স্ট্রিংটি লিখুন।
সিরিজিকরণ অ্যারে।
তারা একটি স্ট্রিং হিসাবে একই। আপনি প্রথমে অ্যারের আকারের প্রতিনিধিত্ব করে একটি পূর্ণসংখ্যাকে সিরিয়ালাইজ করুন তারপরে এটিতে প্রতিটি বস্তুকে সিরিয়ালাইজ করুন।
পুরো বস্তু সিরিয়ালিং করা হচ্ছে
আমি আগেই বলেছি serialize
যে তাদের একটি পদ্ধতি থাকা উচিত যা কোনও ভেক্টরে সামগ্রী যুক্ত করে। কোনও অবজেক্টকে আনসিরিয়ালাইজ করতে, এটির এমন একজন কনস্ট্রাক্টর থাকা উচিত যা বাইট স্ট্রিম গ্রহণ করে। এটি একটি হতে পারে istream
তবে সহজতম ক্ষেত্রে এটি কেবল একটি রেফারেন্স হতে পারেuint8_t
পয়েন্টার । কনস্ট্রাক্টর স্ট্রিম থেকে এটি যে বাইটগুলি চায় তা পড়ে এবং অবজেক্টে ক্ষেত্রগুলি সেট আপ করে। যদি সিস্টেমটি ভালভাবে ডিজাইন করা হয়েছে এবং ক্ষেত্রগুলিকে অবজেক্ট ফিল্ড অর্ডারে সিরিয়ালাইজ করা হয়েছে তবে আপনি কেবলমাত্র একটি প্রারম্ভিক তালিকায় ফিল্ডটির নির্মাতাদের কাছে স্ট্রিমটি প্রেরণ করতে পারেন এবং সেগুলি সঠিক ক্রমে বিশৃঙ্খলাবদ্ধ করতে পারেন।
সিরিয়ালিং অবজেক্ট গ্রাফ
প্রথমে আপনাকে নিশ্চিত করতে হবে যে এই জিনিসগুলি সত্যই কিছু যা আপনি সিরিয়ালায়িত করতে চান to গন্তব্যে এই বিষয়গুলির উদাহরণ উপস্থিত থাকলে আপনাকে সেগুলি ক্রমিক করার দরকার নেই।
এখন আপনি খুঁজে পেয়েছেন যে আপনাকে পয়েন্টার দ্বারা নির্দেশিত সেই অবজেক্টটি ক্রমিক করা দরকার। পয়েন্টারগুলির সমস্যা যে তারা প্রোগ্রামটিতে কেবল এটি ব্যবহারযোগ্য valid আপনি পয়েন্টারকে সিরিয়ালাইজ করতে পারবেন না, আপনাকে তাদের বস্তুগুলিতে ব্যবহার বন্ধ করা উচিত। পরিবর্তে অবজেক্ট পুল তৈরি করুন। এই অবজেক্ট পুলটি মূলত একটি গতিশীল অ্যারে যা "বাক্সগুলি" ধারণ করে। এই বাক্সগুলির একটি রেফারেন্স গণনা রয়েছে। অ-শূন্য রেফারেন্স গণনা একটি লাইভ অবজেক্টকে নির্দেশ করে, শূন্যটি একটি খালি স্লট নির্দেশ করে। তারপরে আপনি শেয়ার্ড_প্টারের সমান স্মার্ট পয়েন্টার তৈরি করেন যা পয়েন্টারটি বস্তুটিতে সঞ্চয় করে না, তবে সূচীতে অ্যারেতে থাকে। আপনাকে এমন একটি সূচকেও সম্মত করতে হবে যা নাল পয়েন্টারটিকে বোঝায়, যেমন। -1।
মূলত আমরা এখানে যা করেছি পয়েন্টারগুলি অ্যারে সূচকগুলির সাথে প্রতিস্থাপন করা হয়েছে। সিরিয়ালাইজ করার সময় আপনি যথারীতি এই অ্যারে সূচকটি সিরিয়াল করতে পারবেন। গন্তব্য সিস্টেমে কী জিনিসটি স্মৃতিতে থাকবে সে সম্পর্কে আপনাকে চিন্তা করার দরকার নেই। কেবল নিশ্চিত করুন যে তাদেরও একই বস্তু পুল রয়েছে।
সুতরাং আমাদের অবজেক্ট পুলগুলি সিরিয়ালাইজ করা দরকার। তবে কোনটি? আচ্ছা আপনি যখন কোনও অবজেক্টের গ্রাফকে সিরিয়ালাইজ করেন আপনি কেবল কোনও অবজেক্টকে সিরিয়ালাইজ করছেন না, আপনি একটি সম্পূর্ণ সিস্টেমকে সিরিয়ালাইজ করছেন। এর অর্থ সিস্টেমের ক্রমিকায়ন সিস্টেমের অংশ থেকে শুরু হওয়া উচিত নয়। Objects অবজেক্টগুলিকে সিস্টেমের বাকী অংশ নিয়ে চিন্তা করা উচিত নয়, তাদের কেবল অ্যারে সূচকগুলি সিরিয়ালাইজ করা দরকার এবং এটিই। আপনার সিস্টেমে সিরিয়ালাইজেশন রুটিন থাকা উচিত যা সিস্টেমটির সিরিয়ালাইজেশনকে অর্কেস্টেট করে এবং প্রাসঙ্গিক অবজেক্ট পুলগুলির মধ্য দিয়ে চলে এবং সেগুলি সমস্ত ক্রমিক করে তোলে।
প্রাপ্তির শেষে সমস্ত অ্যারের মধ্যে থাকা কোনও বস্তুর পছন্দসই অবজেক্ট গ্রাফটি পুনরায় তৈরি করা হয় এবং এর মধ্যে একটি বস্তুকে ডিসরিয়ালাইজ করা হয়।
ক্রিয়ালাইজিং ফাংশন পয়েন্টার
পয়েন্টার অবজেক্টে রাখবেন না। একটি স্ট্যাটিক অ্যারে থাকে যা এই ফাংশনগুলির পয়েন্টারগুলিকে ধারণ করে এবং অবজেক্টে সূচকটি সংরক্ষণ করে।
যেহেতু উভয় প্রোগ্রামই এই টেবিলটি তাদের শেল্ভগুলিতে সংকলিত করেছে, কেবলমাত্র সূচি ব্যবহার করে কাজ করা উচিত।
পলিমারফিক ধরণের সিরিয়ালিং করা
যেহেতু আমি বলেছি যে সিরিয়ালাইজযোগ্য প্রকারে আপনার পয়েন্টার এড়ানো উচিত এবং এর পরিবর্তে আপনার অ্যারে সূচকগুলি ব্যবহার করা উচিত, পলিমারফিজম কেবল কাজ করতে পারে না কারণ এর জন্য পয়েন্টার প্রয়োজন।
টাইপ ট্যাগ এবং ইউনিয়নগুলির সাথে আপনার এটি চারপাশে কাজ করা উচিত।
সংস্করণ
উপরের সমস্ত উপরে। আপনি সফ্টওয়্যার আন্তঃব্যবস্থার বিভিন্ন সংস্করণ চাইবেন।
এক্ষেত্রে প্রতিটি বিষয়বস্তু সংস্করণ নির্দেশ করতে তাদের সিরিয়ালাইজেশনের শুরুতে একটি সংস্করণ নম্বর লিখতে হবে।
অপরদিকে বস্তুটি লোড করার সময়, নতুন বস্তুগুলি পুরানো উপস্থাপনাগুলি পরিচালনা করতে সক্ষম হতে পারে তবে পুরানোগুলি নতুনকে হ্যান্ডেল করতে পারে না তাই তাদের এ সম্পর্কে একটি ব্যতিক্রম ছড়িয়ে দেওয়া উচিত।
প্রতিবার কিছু পরিবর্তন হওয়ার সাথে সাথে আপনার সংস্করণ নম্বরটি কাটাতে হবে।
সুতরাং এটি মোড়ানোর জন্য, সিরিয়ালাইজেশন জটিল হতে পারে। তবে ভাগ্যক্রমে আপনার প্রোগ্রামের সমস্ত কিছু সিরিয়ালাইজ করার দরকার নেই, বেশিরভাগ ক্ষেত্রে কেবল প্রোটোকল বার্তাগুলিই সিরিয়ালায়িত হয়, যা প্রায়শই পুরানো স্ট্রাইক থাকে। সুতরাং উপরে বর্ণিত জটিল কৌশলগুলি আপনার প্রয়োজন নেই।