سؤال

لدي المثال التالي للقراءة من قارئ مخزنة:

while ((inputLine = input.readLine()) != null) {
   System.out.println("I got a message from a client: " + inputLine);
}

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

لكني لا أفهم كيف يعمل. inputLine = input.readLine() ينتظر حتى يظهر شيء ما في القارئ المخزن المؤقت وعندما يظهر شيء ما ، فإنه يعود true ويتم تنفيذ الكود في الحلقة. لكن عندما null يمكن إرجاعها.

هناك سؤال آخر. تم أخذ الرمز أعلاه من طريقة throws Exception وأنا أستخدم هذا الرمز في طريقة تشغيل الخيط. وعندما أحاول أن أضع throws Exception قبل run يشكو المترجم: لا يلقي طريقة Overridden استثناء. بدون ال throws exception لدي شكوى أخرى من برنامج التحويل البرمجي: استثناء غير مبني. اذا، ماذا استطيع ان افعل؟

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

المحلول

عند إغلاق المقبس على الطرف الآخر ، يجب على القارئ إعادة سلسلة فارغة. هذا هو الشرط الذي تبحث عنه. للتعامل مع الاستثناء ، لف حلقة القراءة في كتلة المحاولة.

 try {
   while ((inputLine = input.readLine()) != null) {
     System.out.println("I got a message from a client: " + inputLine);
   }
 }
 catch (IOException e) {
   System.err.println("Error: " + e);
 }

قد تجد هذا درس تعليمي على القراءة/الكتابة من/إلى مقبس في جافا ، مفيدة.

نصائح أخرى

لسؤالك الأول:

لكني لا أفهم كيف يعمل. InputLine = input.ReadLine () ينتظر حتى يظهر شيء ما في القارئ المخزن المؤقت وعندما يظهر هناك شيء ما ، فإنه يعيد صحيحًا ويتم تنفيذ الكود في الحلقة. ولكن عندما يمكن إعادة فارغ.

BufferedReader.readLine() لا يعود true عند النجاح. يعيد سلسلة تحتوي على الخط الذي تمت قراءته. إذا تم الوصول إلى نهاية الدفق ، فإنه يعود null.

سؤالك الثاني:

تم أخذ الرمز أعلاه من طريقة ترمي استثناء وأستخدم هذا الرمز في طريقة تشغيل مؤشر الترابط. وعندما أحاول وضع رميات استثناء قبل تشغيل المدى يشكو برنامج التحويل البرمجي: لا يلقي طريقة Overridden استثناء. بدون استثناء رميتي ، لدي شكوى أخرى من المترجم: استثناء غير مُبلغ عنه. اذا، ماذا استطيع ان افعل؟

يجب عليك لف الرمز الخاص بك في حاول/تمسك بلوك. إذا كنت لا ترغب في التعامل مع الاستثناء الذي تم صيده ، فما عليك سوى ترك هذا الجزء فارغًا (غير موصى به)

try {
    while ((inputLine = input.readLine()) != null) {
        System.out.println("I got a message from a client: " + inputLine);
    }
} catch (Exception e) {
    //handle exception
}

سيعود قراء القارئ () قيمة السلسلة عندما يكون لديه شيء ما ، وسلسلة فارغة عندما لا يكون هناك أي شيء بعد ، و Null عند إغلاق الاتصال.

أود أن أوصي بتفكيك/تجول حول كتلة الكود الخاص بك مع وظيفة IO والتعامل مع الأخطاء بشكل مناسب.

input يتم توصيل القارئ بالمقبس ، وهو مستمع ، أي يستمر في الاستماع إلى الرسائل الواردة.

حول سؤالك الثاني ، يجب عليك وضع كتلة تجربة/اصطياد داخل الطريقة ، والتقاط الاستثناء والتعامل معه. لا تقم بإعادة التدلل.

لكني لا أفهم كيف يعمل. .... ينتظر حتى يظهر شيء ما في القارئ المخزن المؤقت وعندما يظهر شيء هناك ، فإنه يعود صحيحًا

لا ، فإنه يعيد قيمة التعبير (inputLine = input.ReadLine ()) ، خط الإدخال نفسه. تتم مقارنة سطر الإدخال مع فارغة.

يتم إرجاع NULL عند الوصول إلى "EOF (نهاية الملف)". نظرًا لأن هذا يقرأ من مقبس الشبكة ، يتم إنشاء نهاية الملف عند فصل المقبس (إما بواسطة الخادم أو العميل) ، لكن من المحتمل أن تحصل على استثناء قبل أن ترى EOF بالفعل.

إذا لم يكن هذا للواجب المنزلي ، فقد ترغب في إلقاء نظرة على Apache Commons ioutils.

على افتراض أنك لا تقوم بإنشاء Bufferrederer ، وتوقف فقط عند inputstream:

String results = IOUtils.toString(inputStream);
System.out.println(results);
while ((inputLine = input.readLine()) != null) {

انظر إلى كل جزء من التعبير:

input.readLine()

إرجاع سلسلة ستكون فارغة إذا تم الوصول إلى نهاية الدفق (أو يلقي استثناءً على الخطأ).

inputLine = input.readLine()

يعين هذه السلسلة إلى inputline

((inputLine = input.readLine()) != null)

يتحقق من أن السلسلة التي تم تعيينها ليست فارغة (نهاية الدفق).

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

أما بالنسبة للنتيجة من readLine(), ، سوف يعود null عندما لا يوجد شيء أكثر للقراءة. في حالة المقبس ، يكون ذلك عندما يغلق الجانب الآخر بشكل نظيف المقبس (أي إنهاء مفاجئ أو إغلاق غير نظيف سيؤدي عادة إلى استثناء في الكود الخاص بك لأن نظام التشغيل سيرسل نوعًا مختلفًا من الإخطار المقبس).

لديّ كلمة تحذير واحدة لأنك تلتف مقبسًا في أ java.io.BufferedReader. يجب أن تكون حريصًا جدًا على استخدام هذا في أي نوع من رمز الإنتاج.

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

لاحظ أن هناك أنواعًا أخرى من استثناءات المقبس التي لا تعني أن المقبس قد فقد. على سبيل المثال ، انظر إلى تعريف java.io.InterruptedIOException. يحتوي هذا على متغير عام يوضح عدد البايتات التي تم نقلها بنجاح في أحدث طلب I/O (قراءة أو كتابة). هذا يعني أنه يمكن تنفيذ عملية IO مرة أخرى لاسترداد أو إرسال البايتات المتبقية للحزمة.

إذا كان التصميم الخاص بك في أي استثناء هو إغلاق القارئ على الفور ومقبس ، فسيعمل الطريقة بشكل صحيح.

تتمثل الطريقة المناسبة للقراءة من المقبس في استخدام دفق المقبس مباشرةً ، واستخدام NIO (بايتبوفيرز وما شابه) ، أو استخدام مكتبة شبكة مكتوبة جيدًا مع تجريدات جيدة على هذه الفئات ذات المستوى الأدنى (تتوفر العديد من المصادر المفتوحة).

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