تحليل المبدأ
أثناء التطوير ، تكون وظيفة "الإرسال المستمر نقطة التوقف" عملية وشائعة للغاية ، كما أنها تبدو أكثر "قياسية". لذلك نحن مهتمون عادة بدراسة كيفية تنفيذ هذه الوظيفة؟
في Java ، يمكنك أيضًا العثور على الكثير من المعلومات حول تنفيذ وظائف مماثلة على الإنترنت. ومع ذلك ، فإن معظمهم يعطي عرضًا تجريبيًا ونشر رمز المصدر. هناك عدد قليل جدًا من التفسيرات التفصيلية لمبدأ تنفيذها.
لذلك عندما تواصلنا معها لأول مرة ، قد نستخدم رموز CRTL + C/V مباشرة ثم نتعرف عليها ، لكن يمكننا أخيرًا الحصول على التأثير. لكن القيام بذلك عندما تكون مبتدئين أمر جيد وسيئ.
الميزة هي أن هناك العديد من رموز المصدر وتفسيرات قليلة ؛ إذا كنا على استعداد للعمل بجد ، فسنبحث عن المعلومات وندرس الأشياء التي لا نفهمها في الكود الذي نشره الآخرون. في النهاية ، من المحتمل أن تحصل على الكثير من المكافآت.
العيوب واضحة أيضًا: كمبتدئ ، عند مواجهة الكثير من التعليمات البرمجية المصدر ، يبدو أن الكثير من الأشياء غير مألوفة ، لذلك من السهل أن تكون شاقة. حتى لو كان لديك فهم تقريبي للاستخدام في النهاية ، فقد لا تفهم بالضرورة مبدأ التنفيذ.
اليوم ، دعنا نبدأ من المنظور الأساسي ومعرفة ما إذا كان ما يسمى "استمرار نقطة الإيقاف" هو في الحقيقة "راقية".
في الواقع ، عندما تتلامس مع "شيء" جديد ، يمكنك تحويله إلى شيء نتعرف عليه للإشارة إلى ومقارنة ونتعلم. عادة ما تكون ضعف النتيجة مع نصف الجهد.
إذا تعرضنا لمفهوم "انتقال الإيقاف المستمر" ، فسيكون من الصعب بالتأكيد شرح واحد أو اثنين أو ثلاثة. ثم ، سنكون بالتأكيد على دراية بـ "لعب الألعاب".
حسنًا ، لنفترض أن لدينا الآن "لعبة RPG واضحة". فكر فيما نفعله عادة عند لعب هذا النوع من الألعاب؟
من الواضح أننا في اليوم الأول قاتلنا معارك دموية وقتلنا الجميع ، على افتراض أننا وصلنا أخيرًا إلى المستوى الرابع. على الرغم من أن المعركة الشرسة كانت على قدم وساق ، عندما نظرت إلى الساعة على الحائط ، كانت بالفعل الساعة 12 صباحًا ، وقد حان الوقت للذهاب إلى الفراش.
كان محرجا للغاية في هذا الوقت. من أجل مواكبة تقدم لعبتنا في المرة القادمة التي نلعب فيها ، ماذا يجب أن نفعل؟
الأمر بسيط للغاية. نحن لا نطفئ اللعبة ، ونذهب إلى الفراش ، ونواصل اللعب في اليوم التالي. هذا جيد ، لكن يبدو أن هناك شيء يجعل الناس يشعرون بعدم الارتياح.
لذلك ، في هذا الوقت ، إذا كانت اللعبة لديها وظيفة تسمى "حفظ" ، فستكون مهمة للغاية. نختار مباشرة الأرشيف ، وأدخل اسم الأرشيف "المستوى الرابع" ، ثم يمكننا إغلاق اللعبة.
عندما نلعب اللعبة في المرة القادمة ، سنجد مباشرة حفظ "المستوى الرابع" ، ثم اقرأ الملف ، ثم يمكننا الاستمرار في لعب اللعبة.
في هذا الوقت ، من السهل فهم ما يسمى "انتقال نقطة الإيقاف المستمر". دعونا نتبع فكرتنا السابقة عن "ممارسة الألعاب":
لنفترض أن هناك ملفًا نحتاج إلى تنزيله الآن. عندما نقوم بتنزيل جزء منه ، يحدث موقف ، مثل: تعطل الكمبيوتر ، يتم خارج الطاقة ، وتقطع الشبكة ، إلخ.
في الواقع ، هذا يشبه عندما كنا نلعب الألعاب من قبل ، كنا بحاجة فجأة للذهاب إلى الفراش والراحة في الساعة 12. حسنًا ، ثم الوضع في هذا الوقت هو:
• إذا تعذر حفظ اللعبة ، فهذا يعني أنه في المرة القادمة التي نلعب فيها ، فإن التقدم في المستويات الأربعة التي مرت هذه المرة فسوف لا يمكننا متابعة اللعبة.
• في المقابل ، إذا كان سلوك "التنزيل" لا يمكن أن يسجل تقدمًا في هذا التنزيل. ثم ، عندما نقوم بتنزيل هذا الملف مرة أخرى ، لا يمكننا البدء إلا.
في هذه المرحلة ، اكتشفنا بالفعل أن مفتاح السلوك الذي ذكرناه أعلاه هو كلمة " متابعة "!
لتحقيق الغرض من "مواصلة" السلوك غير المتصل ، يكون المفتاح هو وجود "وسائط" قادرة على تسجيل وقراءة معلومات العقدة حيث يكون للسلوك "انقطاع".
تحويل إلى عالم البرمجة
في الواقع ، هذا هو المبدأ الأساسي لـ "انتقال نقطة الإيقاف المستمر". بالكلمات العادية ، نحتاج إلى تسجيل معلومات موقع المقاطعة عند مقاطعة سلوك التنزيل ، ثم قراءتها في السلوك التالي.
مع معلومات هذا الموقع ، فكر في ما يجب أن نفعله. نعم ، الأمر بسيط للغاية. عندما يبدأ سلوك التنزيل الجديد ، قم بتنزيل المحتوى مباشرة من هذا الموقع من السجل ، ولم يعد يبدأ من نقطة الصفر.
حسنًا ، لقد تحدثنا عن مبدأ طويل في لغة واضحة وبدأنا نشعر بالملل. لذلك دعونا نلخصها في النهاية ثم نلقي نظرة على كيفية تحويل المبادئ إلى عالم البرمجة.
• عند مقاطعة "تحميل (تنزيل) سلوك" ، نحتاج إلى تسجيل الموقع (الموضع) لهذا التحميل (التنزيل).
• عندما يبدأ سلوك "متابعة" ، نقفز مباشرة إلى المنشور لمواصلة التحميل (التنزيل).
من الواضح أن مفتاح المشكلة يكمن في ما يسمى "الموقف". في "لعبة المستوى المارة" ذكرنا ، "أي مستوى" يمكن استخدامه كوحدة لهذا الموقف.
لذلك عندما نتحول إلى ما يسمى "الإرسال المستمر نقطة التوقف" ، ما الذي يجب أن نستخدمه لقياس "الموضع"؟ من الواضح أن الأمر يعود إلى ثنائي لأن الجوهر هنا ليس أكثر من قراءة الملفات وكتابةها.
ثم بقية العمل بسيط للغاية. أولاً ، سجل الموقف ، الذي يبدو أنه لا يستحق الحديث عنه ، لأنه مجرد استمرار البيانات (الذاكرة ، الملفات ، قاعدة البيانات) ، ولدينا طرق عديدة.
مفتاح آخر هو أنه عندما يبدأ السلوك "المستمر" ، نحتاج إلى بدء عمليات القراءة والكتابة من موضع الموضع الذي سجلناه في المرة الأخيرة ، لذلك نحتاج إلى شيء مشابه لدالة "المؤشر".
بالطبع ، يمكننا أيضًا إيجاد طريقة لتنفيذ مثل هذا "المؤشر" ، ولكن سعيد لأن Java قد وفرت لنا مثل هذا الفصل ، أي عشوائي.
تنعكس وظيفة هذه الفئة بشكل حدسي في اسمها ، ويمكنها الوصول إلى الملفات بشكل عشوائي. دعونا نلقي نظرة على وصف هذه الفئة في وثائق API:
مثيلات دعم هذا الفئة قراءة والكتابة إلى الملفات التي تم الوصول إليها عشوائيا. يتصرف الوصول العشوائي إلى الملفات مثل صفيف بايت كبير مخزّن في نظام الملفات.
إذا تم الوصول إلى ملف بشكل عشوائي في وضع القراءة/الكتابة ، فإن عملية الإخراج متوفرة أيضًا ؛ تبدأ عملية الإخراج بمؤشر الملف وتقدم مؤشر الملف عند كتابة البايت.
تؤدي عملية الإخراج بعد الكتابة إلى الطرف الحالي للمصفوفة الضمنية إلى توسيع الصفيف. يمكن قراءة مؤشر الملف من خلال طريقة getFilePointer وتعيينها من خلال طريقة البحث.
بعد قراءة تعليمات API ، ضحكنا. نعم ، أليس هذا بالضبط ما نريد؟ حسنًا ، لقد شحذنا سكيننا لفترة طويلة ، لماذا لا نقطع الخشب؟
مثال مظاهرة
نظرًا لأنه من أجل "استمرار نقطة الإيقاف" للملفات ، فمن الواضح أننا سنقوم أولاً بإنشاء ملف. ربما تبدو الملفات الصوتية وملفات الصور وما إلى ذلك أكثر صرامة.
لكننا قلنا بالفعل أنه في نظر الإخوة الحاسوبين الكبار ، سيعودون في النهاية إلى "ثنائي". لذلك سنقوم بإنشاء ملف "txt" بسيط هنا ، لأن txt أكثر ملاءمة للفهم.
نقوم بإنشاء ملف يسمى "Test.txt" في الدليل الجذر للقرص D. محتوى الملف بسيط للغاية ، كما هو موضح في الشكل:
هذا صحيح ، ما كتبناه هو 6 رسائل إنجليزية بسيطة. ثم نقرر بزر الماوس الأيمن → الخصائص:
نرى أن الملف الآن 6 بايت في الحجم. هذا هو السبب في أننا نقول أن كل شيء لا ينفصل عن "ثنائي".
نعم ، نحن جميعًا نفهم لأننا دخلنا 6 أحرف إنجليزية ، ومساحة التخزين التي ستشغلها رسالة إنجليزية واحدة هي بايت واحد (أي 8 بت).
حتى الآن ، ما رأيناه ممل ، لأن هذا هراء في الأساس ، والأشخاص الذين لديهم القليل من معرفة الكمبيوتر يعرفون هذه المعرفة. لا تقلق ، دعنا نستمر.
من السهل القراءة وكتابة ملف في Java. لنفترض أن الشرط الحالي هو "كتابة هذا الملف من محرك الأقراص إلى محرك الأقراص E" ، ثم سنقوم برفع لوحة المفاتيح وننجزه!
لكن أليس ما يسمى "تحميل (تنزيل)" لما يسمى بالملف؟ الفرق الوحيد هو أن السلوك يتغير من "فقط بين السكان الأصليين" إلى "بين السكان الأصليين" إلى "بين السكان الأصليين" قراءة ملفات وكتابة.
في هذا الوقت ، سوف نقول ، "توقف عن الحث ، الجميع يعرف هذه الأشياء ، ماذا عن" انتقال نقطة الإيقاف المستمر "؟" في الواقع ، الأمر بسيط للغاية هنا. سنوضح مرة أخرى أن ما يتعين علينا القيام به في نقطة الإيقاف المستمر هو:
إذا كان هناك انقطاع في سلوك القراءة والكتابة السابقة ، فيرجى تسجيل معلومات الموقع لمحتويات الملف التي تمت قراءتها وكتابتها هذه المرة ؛ عندما "يبدأ الاستمرار" ، حرك المؤشر مباشرة هنا وابدأ في مواصلة عملية القراءة والكتابة.
التركيز المتكرر على المبدأ هو في الواقع لأنه طالما أن المبدأ مفهومة ، فإن الباقي يتحرك فقط. هذا تمامًا مثل "تسعة تسعة عودة إلى واحد" دارما في روايات فنون القتال ، وهو أعلى مستوى هو العودة إلى المصدر الأصلي.
طالما أننا نفهم مبدأ أي شيء معقد ، يمكننا تجريده وخفضه إلى أشياء بسيطة. وبالمثل ، فإن سلسلة من الأشياء البسيطة ، من خلال مزيج منطقي ، تشكل أشياء معقدة.
بعد ذلك ، سنعود إلى الفوضى قريبًا ومحاكاة "انتقال مستمر نقطة التوقف" في النموذج الأساسي. هنا لا نكتب رمز الخادم ، ونفعل ذلك من خلال فئة اختبار محلية.
التأثير الذي نريد تحقيقه بسيط للغاية: اكتب ملف "test.txt" على القرص إلى القرص e ، لكننا سنحاكي سلوك "المقاطعة" في منتصف العملية ، ثم نستمر في التحميل مرة أخرى لإكمال العملية بأكملها أخيرًا.
بمعنى آخر ، سننظر في "D Drive" ككمبيوتر هنا ، وننظر مباشرة إلى "محرك الأقراص" كخادم. بعد ذلك ، لن نتعلق ببروتوكول HTTP لمدة نصف سنت (بالطبع ، لا يزال يتعين علينا أن نتعرف عليه في التطوير الفعلي) ، لذلك نحن نهتم فقط بالمبادئ الأساسية لـ "كسر" و "مستمر" لقراءة الملفات وكتابةها.
من أجل تعميق فهمنا من خلال المقارنة ، نكتب أولاً جزءًا طبيعيًا من التعليمات البرمجية ، أي قراءة ونكتب بشكل طبيعي دون انقطاع:
اختبار الفئة العامة {public static void main (string [] args) {// source and target file sourcefile = new file ("d:/" ، "test.txt") ؛ ملف TargetFile = ملف جديد ("E:/" ، "test.txt") ؛ // الإدخال والإخراج تدفق fileInputStream FIS = null ؛ fileOutputStream fos = null ؛ // Data Buffer Byte [] buf = new byte [1] ؛ حاول {fis = جديد fileInputStream (sourceFile) ؛ fos = fileOutputStream جديد (TargetFile) ؛ // قراءة وكتابة البيانات أثناء (fis.read (buf)! = -1) {system.out.println ("كتابة البيانات ...") ؛ fos.write (buf) ؛ }} catch (fileNotfoundException e) {system.out.println ("ملف محدد غير موجود") ؛ } catch (ioException e) {// todo: handled insport} أخيرًا {try {// أغلق دفق الإدخال والإخراج إذا (fis! = null) fis.close () ؛ إذا (fos! = null) fos.close () ؛ } catch (ioException e) {E.PrintStackTrace () ؛ }}}} عند تشغيل هذا الرمز ، سنجد أن نسخة من "test.txt" قد تم نسخها بنجاح في القرص E. هذا الرمز بسيط للغاية ، والشيء الوحيد الذي يمكن قوله هو:
نرى أننا قمنا بتعيين BUF ، أي أن حجم المخزن المؤقت هو 1 ، وهو ما يعني في الواقع أنه في كل مرة نقرأ فيها ، نقرأ بايت من البيانات (أي رسالة إنجليزية واحدة).
الآن ، دعنا نحاكي سلوك القراءة والكتابة المقاطعات. سنقوم بإتقان الكود السابق على النحو التالي:
استيراد java.io.file ؛ استيراد java.io.fileinputStream ؛ استيراد java.io.filenotfoundexception ؛ استيراد java.io.fileOutputStream ؛ استيراد java.io.ioException ؛ استيراد java.io.randomaccessfile public static void main (string [] args) {// source and target file sourcefile = new file ("d:/" ، "test.txt") ؛ ملف TargetFile = ملف جديد ("E:/" ، "test.txt") ؛ // الإدخال والإخراج تدفق fileInputStream FIS = null ؛ fileOutputStream fos = null ؛ // Data Buffer Byte [] buf = new byte [1] ؛ حاول {fis = جديد fileInputStream (sourceFile) ؛ fos = fileOutputStream جديد (TargetFile) ؛ // البيانات قراءة وكتابة بينما (fis.read (buf)! = -1) {fos.write (buf) ؛ // عندما يتم تحميل 3 بايت من محتوى الملف ، يتم تقاطع الشبكة ويتم إلقاء استثناء إذا (targetfile.length () == 3) {position = 3 ؛ رمي FileAccessException () ؛ }}} catch (fileAccessexception e) {keep (sourceFile ، targetfile ، position) ؛ } catch (fileNotfoundException e) {system.out.println ("تحديد الملف غير موجود") ؛ } catch (ioException e) {// todo: handled insport} أخيرًا {try {// أغلق دفق الإدخال والإخراج إذا (fis! = null) fis.close () ؛ إذا (fos! = null) fos.close () ؛ } catch (ioException e) {E.PrintStackTrace () ؛ }}} void static static keep (مصدر الملف ، هدف الملف ، موضع int) {try {thread.sleep (10000) ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } جرب {randomaccessfile readfile = new RandomAccessFile (المصدر ، "RW") ؛ RandomAccessFile WriteFile = new RandomAccessFile (Target ، "RW") ؛ readfile.keek (موقف) ؛ writefile.keek (موقف) ؛ // Data Buffer Byte [] buf = new byte [1] ؛ // البيانات قراءة وكتابة بينما (readFile.Read (buf)! = -1) {writefile.write (buf) ؛ }} catch (fileNotfoundException e) {// todo catch catch e.printstacktrace () ؛ } catch (ioException e) {// todo acto catch block e.printstacktrace () ؛ }}} class fileAccessException يمتد الاستثناء {}لتلخيص ، ما العمل الذي قمنا به في هذا التغيير:
• أولاً ، نحدد موضعًا متغيرًا لتسجيل الموقع الذي تم فيه الانتهاء من القراءة والكتابة عند حدوث مقاطعة. (هذا من أجل الراحة. في الواقع ، ينبغي القول أنه ينبغي تخزين هذه القيمة في ملف أو قاعدة بيانات للثبات)
• ثم في حلقة قراءة الملفات والكتابة ، نقوم بمحاكاة حدوث سلوك المقاطعة. هنا ، عندما يكون طول الملف لـ TargetFile 3 بايت ، فإنه يحاكي رمي استثناء قمنا بتخصيصه. (يمكننا أن نتخيل أنه في التنزيل الفعلي ، تم تحميل محتوى "X" بايت (تم تنزيله) وتقطع الشبكة في هذا الوقت ، لذلك سنقوم بتسجيل "X" في الاستثناء الذي ألقاه الشبكة).
• الباقي كما قلنا من قبل ، بعد بدء سلوك "الاستمرار" ، نلتف ملفنا من خلال فئة RandomAccessFile ، ثم حدد المؤشر إلى الموقع الذي حدثت فيه المقاطعة السابقة للقراءة والكتابة من خلال SEEP.
(لتنزيل الملف الفعلي وتحميله ، بالطبع ، نحتاج إلى تحميل قيمة المقاطعة المحفوظة للخادم. عادةً ما تكون هذه الطريقة httpconnection.setRequestProperty ("Range" ، "Bytes = X") ؛) ؛)
في الكود الخاص بنا ، قم بتمكين السلوك "المستمر" ، أي طريقة الاحتفاظ بها: نبدأ في السماح لخيط الخيط لمدة 10 ثوان ، وهو بالضبط السماح لنا بتشغيل البرنامج ونرى التأثير.
الآن بعد أن ندير البرنامج ، سيبدأ الملف "عملية التحميل من D Disk إلى E Disk". أولاً ، ننقر على القرص E ونجد أن هناك بالفعل ملف test.txt إضافي. افتحه وابحث عن المحتوى على النحو التالي:
هذا صحيح ، في هذا الوقت وجدنا أن المحتوى يحتوي فقط على "ABC". هذا ضمن توقعاتنا ، لأن محاكاة البرنامج الخاصة بنا تقاطع عند تحميل الملف بواسطة 3 بايت.
حسنًا ، دعنا ننتظر بهدوء لمدة 10 ثوانٍ لتمريرها ، ثم انقر على الملف لمعرفة ما إذا كان يمكن أن ينجح:
من خلال لقطات الشاشة ، وجدنا أن المحتوى أصبح بالفعل "ABC" ، وبالتالي تم الانتهاء من الاستمرار.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.