سؤال

الجميع،

أحاول التأكد من أن ملفًا مفتوحًا باستخدام BufferedReader مغلق عندما أقوم بمسكات ioException ، لكن يبدو كما لو أن كائن Bufferreader الخاص بي خارج النطاق في كتلة الصيد.

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    try {
        //open the file for reading
        BufferedReader fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        fileIn.close(); 
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}

يشكو NetBeans من أنه "لا يمكن العثور على رمز Filein" في كتلة الصيد ، لكنني أريد التأكد من أنه في حالة إغلاق القارئ. كيف يمكنني فعل ذلك دون قبح إحدى المحاولة الثانية/التقاط البناء حول الأول؟

يتم تقدير أي نصائح أو مؤشرات حول أفضل الممارسات في هذا الموقف ،

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

المحلول

 BufferedReader fileIn = null;
 try {
       fileIn = new BufferedReader(new FileReader(filename));
       //etc.
 } catch(IOException e) {
      fileArrayList.removeall(fileArrayList);
 } finally {
     try {
       if (fileIn != null) fileIn.close();
     } catch (IOException io) {
        //log exception here
     }
 }
 return fileArrayList;

بعض الأشياء حول الكود أعلاه:

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

نصائح أخرى

بمجرد أن تضغط على كتلة الصيد ، لم تعد أي متغيرات معلنة في المحاولة. إعلان bufferedReader filein = null ؛ فوق كتلة المحاولة ، ثم قم بتعيينها في الداخل. في كتلة catch ، افعل if (filein! = null) filein.close () ؛

إنه يشكو من عدم وجود الرمز لأنه ليس كذلك. إنه في كتلة المحاولة. إذا كنت ترغب في الرجوع إلى Filein ، فستحتاج إلى إعلانه خارج المحاولة.

ومع ذلك ، يبدو أنك تريد وضع الإغلاق في كتلة أخيرًا بدلاً من ذلك: يجب عليك إغلاق الملف بغض النظر عن النجاح أو الفشل قبل العودة.

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList); 
    }finally{
        if(fileIn != null) fileIn.close();
    }
    return fileArrayList;
}

تتمثل طريقتي المفضلة في تنفيذ التنظيف بعد استثناء (عندما يمكن أن يلقي التنظيف أيضًا إلقاء استثناء) هي وضع الكود في كتلة المحاولة داخل مجموعة أخرى/أخيرًا ، على النحو التالي:

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList) {
    fileArrayList.removeAll(fileArrayList);

    try {
        //open the file for reading
        BufferedReader fileIn = null;

        try {
            fileIn = new BufferedReader(new FileReader(fileName));
            // add line by line to array list, until end of file is reached
            // when buffered reader returns null (todo). 
            while(true){
                fileArrayList.add(fileIn.readLine());
            }
        } finally {
            if (fileIn != null) {
                fileIn.close();
            }
        }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}

انقل الإعلان من كتلة المحاولة:

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        fileIn.close(); 
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}

ولكن ، ستظل بحاجة إلى توخي الحذر fileIn تم تهيئته بالفعل قبل محاولة إغلاقه:

if (fileIn != null)
    fileIn.close();

أعلن أن BufferedReader خارج كتلة المحاولة وقم بتعيينه على NULL ثم استخدم كتلة أخيرًا لإغلاقها إذا لم يكن فارغًا. كما يتم تمرير FilearRayList بالرجوع إليه ، لذا فإن أي تغييرات تم إجراؤها على الكائن الذي مررت به حتى لا تكون هناك حاجة لإعادته أيضًا.

    public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);
    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);  
    }finally
    {
       try
       {
           if(fillIn != null)
               fileIn.close();
       }
       catch(IOException e){}
    }
    return fileArrayList; //returned empty. Dealt with in calling code.
}

من الأفضل عدم التعامل معها null - المصطلح العام لاكتساب الموارد وإصدارها في جافا :

final Resource resource = acquire();
try { use(resource); }
finally { resource.release(); }

لذا:

public static List<String> readFiletoArrayList(String fileName,
        List<String> fileArrayList, String charsetName) {
    fileArrayList.clear(); // why fileArrayList.removeAll(fileArrayList) ?
    try {
        InputStream file = new FileInputStream(fileName);
        try {
            InputStreamReader reader = new InputStreamReader(file, charsetName);
            BufferedReader buffer = new BufferedReader(reader);
            for (String line = buffer.readLine(); line != null; line = buffer
                    .readLine()) {
                fileArrayList.add(line);
            }
        } finally {
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace(); // you do not want this to hide an
                // exception thrown earlier so swallow it
            }
        }
    } catch (IOException e) {
        fileArrayList.clear(); // returned empty. Dealt with in client
    }
    return fileArrayList;
}

انظر نقاط بلدي هنا

إذا كنت تستخدم قارئك يجب حدد الترميز كما أفعل هنا. إذا كنت تريد قراءة البايتات نسيان القارئ. أيضا إذا كنت تستخدم readLine() يجب أن تنسى أحرف نهاية الخط - إذا كان هذا مصدر قلق ، ففكر في حذف BufferedReader تماما.

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