سؤال

لقد لعبت مع الملف Java API النظام ، ونزل مع الدالة التالية ، وتستخدم لنسخ الملفات الثنائية.المصدر الأصلي جاء من الويب ، ولكن أضفت حاول/catch/أخيرا الشروط للتأكد من ذلك ، ينبغي أن شيئا خاطئا يحدث العازلة تيارات ستكون مغلقة (وبالتالي ، OS ressources تحرير) قبل الإنتهاء وظيفة.

أنا قلصت إلى أسفل وظيفة لإظهار نمط:

public static void copyFile(FileOutputStream oDStream, FileInputStream oSStream) throw etc...
{
   BufferedInputStream oSBuffer = new BufferedInputStream(oSStream, 4096);
   BufferedOutputStream oDBuffer = new BufferedOutputStream(oDStream, 4096);

   try
   { 
      try
      { 
         int c;

         while((c = oSBuffer.read()) != -1)  // could throw a IOException
         {
            oDBuffer.write(c);  // could throw a IOException
         }
      }
      finally
      {
         oDBuffer.close(); // could throw a IOException
      }
   }
   finally
   {
      oSBuffer.close(); // could throw a IOException
   }
}

بقدر ما أفهم أنا لا يمكن وضع اثنين close() في النهاية لأن أول شرط close() قد رمي ، ثم الثانية لن يعدم.

أنا أعرف C# لديها التصرف نمط من شأنها أن التعامل مع هذا الامر مع using الكلمات الرئيسية.

حتى أنني أعرف أفضل C++ الكود قد يكون شيئا مثل (باستخدام جافا مثل API):

void copyFile(FileOutputStream & oDStream, FileInputStream & oSStream)
{
   BufferedInputStream oSBuffer(oSStream, 4096);
   BufferedOutputStream oDBuffer(oDStream, 4096);

   int c;

   while((c = oSBuffer.read()) != -1)  // could throw a IOException
   {
      oDBuffer.write(c);  // could throw a IOException
   }

   // I don't care about resources, as RAII handle them for me
}

أنا في عداد المفقودين شيئا, أو هل أنا حقا يجب أن تنتج قبيحة المتضخمة البرمجية في جافا فقط لمعالجة الاستثناءات في close() طريقة مخزنة تيار ؟

(من فضلك, أنا في مكان ما...)

تحرير:هل هو مني أو عند تحديث هذه الصفحة ، رأيت كل سؤال و كل الإجابات بنسبة نقطة واحدة في بضع دقائق ؟ هو شخص يستمتع كثيرا حين remaning مجهول ؟

تحرير 2: ماكدويل عرضت مثيرة جدا للاهتمام الرابط شعرت أنني يجب أن أذكر هنا:http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html

تحرير 3:بعد ماكدويل رابط هوت بناء على اقتراح جافا 7 نمط مماثل C# باستخدام نمط: http://tech.puredanger.com/java7/#resourceblock .مشكلتي هو موضح صراحة.على ما يبدو ، حتى مع جافا 7 do, المشاكل لا تزال قائمة.

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

المحلول

حاول/أخيرا النمط هو الطريقة الصحيحة للتعامل مع تيارات في معظم الحالات Java 6 و أقل.

وبعضها الدعوة بصمت إغلاق تيارات.كن حذرا أفعل هذا من أجل هذه الأسباب: جافا:كيف لا جعل حالة من الفوضى في التعامل مع تيار


جافا 7 يدخل حاول مع الموارد:

/** transcodes text file from one encoding to another */
public static void transcode(File source, Charset srcEncoding,
                             File target, Charset tgtEncoding)
                                                             throws IOException {
    try (InputStream in = new FileInputStream(source);
         Reader reader = new InputStreamReader(in, srcEncoding);
         OutputStream out = new FileOutputStream(target);
         Writer writer = new OutputStreamWriter(out, tgtEncoding)) {
        char[] buffer = new char[1024];
        int r;
        while ((r = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, r);
        }
    }
}

AutoCloseable أنواع سيتم تلقائيا إغلاق:

public class Foo {
  public static void main(String[] args) {
    class CloseTest implements AutoCloseable {
      public void close() {
        System.out.println("Close");
      }
    }
    try (CloseTest closeable = new CloseTest()) {}
  }
}

نصائح أخرى

هناك قضايا ، ولكن الكود الذي وجد الكذب على شبكة الإنترنت سيئة حقا.

إغلاق المخزن المؤقت تيارات يغلق تيار تحتها.كنت حقا لا تريد أن تفعل ذلك.كل ما تريد القيام به هو تدفق تيار الناتج.أيضا لا فائدة في تحديد الكامنة وراء تيارات الملفات.أداء سيء لأنك نسخ بايت واحد في وقت واحد (في الواقع إذا كنت تستخدم جافا.io استخدام يمكن استخدام transferTo/transferFrom وهو أسرع قليلا لا يزال).بينما نحن عن أسماء المتغيرات تمتص.لذلك:

public static void copy(
    InputStream in, OutputStream out
) throw IOException {
    byte[] buff = new byte[8192];
    for (;;) {
        int len = in.read(buff);
        if (len == -1) {
            break;
        }
        out.write(buff, 0, len);
    }
}

إذا كنت تجد نفسك باستخدام المحاولة أخيرا الكثير, ثم يمكنك عامل بها مع "تنفيذ حول" المصطلح.

في رأيي:جافا يجب أن يكون نوعا من إغلاق الموارد في نهاية نطاق.أقترح إضافة private كما الأحادية postfix مشغل ليغلق في نهاية أرفق كتلة.

نعم, هكذا جافا يعمل.هناك مراقبة انعكاس - المستخدم الكائن أن تعرف كيفية تنظيف الكائن بدلا من الكائن نفسه تنظيف بعد نفسها.للأسف هذا يؤدي إلى الكثير من رمز تنظيف المنتشرة في جميع أنحاء الخاص بك جافا البرمجية.

C# لديها "باستخدام" الكلمة تلقائيا الاتصال التصرف عندما كائن يخرج من نطاق.جافا لا يوجد لديه شيء من هذا القبيل.

للأسف هذا النوع من التعليمات البرمجية يميل إلى الحصول على منتفخة قليلا في جاوة.

بالمناسبة, إذا كان أحد يدعو إلى oSBuffer.قراءة أو oDBuffer.كتابة يطرح استثناء ، ثم ربما كنت تريد أن تدع هذا الاستثناء تتخلل المكالمة الهرمي.

وجود حراسة الدعوة إلى close() داخل أخيرا-شرط سوف يسبب الأصلي باستثناء محل واحد التي تنتجها close()-دعوة.وبعبارة أخرى, الفشل close()-الأسلوب قد يخفي استثناء الأصلي المنتجة عن طريق قراءة() أو كتابة().لذا أعتقد أنك تريد أن تجاهل استثناءات من قبل close() إذا وفقط إذا أساليب أخرى لا رمي.

وعادة ما حل هذه صريحة إغلاق المكالمة داخل الداخلية محاولة:

  try {
    while (...) {
      read...
      write...
    }
    oSBuffer.close(); // exception NOT ignored here
    oDBuffer.close(); // exception NOT ignored here
  } finally {
    silentClose(oSBuffer); // exception ignored here
    silentClose(oDBuffer); // exception ignored here
  }
  static void silentClose(Closeable c)  {
    try {
      c.close();
    } catch (IOException ie) {
      // Ignored; caller must have this intention
    }
  }

وأخيرا الأداء رمز ربما ينبغي العمل مع المخازن المؤقتة (متعددة وحدات البايت في القراءة/الكتابة).لا يمكن أن تعود تلك الأرقام ، ولكن أقل المكالمات يجب أن تكون أكثر كفاءة من إضافة مخزنة تيارات على القمة.

الشائعة IO المهام مثل نسخ ملف رمز مثل هو مبين أعلاه هو إعادة اختراع العجلة.للأسف جدك لا توفر أي أعلى مستوى المرافق ، ولكن أباتشي العموم io لا.

على سبيل المثال ، FileUtils يحتوي على العديد من المرافق أساليب العمل مع الملفات و الدلائل (بما في ذلك النسخ).من ناحية أخرى, إذا كنت حقا بحاجة إلى استخدام IO الدعم في جدك ، IOUtils يحتوي على مجموعة من closeQuietly() الأساليب التي بالقرب من القراء والكتاب, تيارات, الخ.دون رمي استثناءات.

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