2010-05-27 13 views
2

写了一个基本的文件处理程序一个Java家庭作业,而当我接到任务后,我有一些注意事项有关未能赶上了几个例子:Java文件处理,我做错了什么?

  • 从文件缓冲区可能已空。
  • 文件未找到
  • 文件流没有关闭

这里是用来打开文件的代码块:

/** 
* Create a Filestream, Buffer, and a String to store the Buffer. 
*/ 
FileInputStream fin = null; 
BufferedReader buffRead = null; 
String loadedString = null; 

/** Try to open the file from user input */ 
try 
{ 
    fin = new FileInputStream(programPath + fileToParse); 
    buffRead = new BufferedReader(new InputStreamReader(fin)); 
    loadedString = buffRead.readLine(); 
    fin.close(); 
} 
/** Catch the error if we can't open the file */ 
catch(IOException e) 
{ 
    System.err.println("CRITICAL: Unable to open text file!"); 
    System.err.println("Exiting!"); 
    System.exit(-1); 
} 

了一句话,我从他身上了是fin.close();需要在finally块,我根本没有。但我认为我创建try/catch的方式可以防止文件无法打开的问题。

让我清楚几件事情:这不是为了当前的任务(不是试图让某人做我自己的工作),我已经创建了我的项目,并对它进行了评分。我自己并没有完全理解我的教授的推理。最后,我没有太多的Java经验,所以我有点困惑为什么我的catch不够好。

+2

虽然在一个长时间运行的程序中关闭系统资源是非常重要的(当然这是很好的做法),如果你打算在yo中调用'System.exit',是否关闭文件是一个有争议的问题你的catch块。 – jasonmp85 2010-05-27 18:57:03

+0

@ jasonmp85这就是我的想法,但是它看起来好像他希望我们把它标记为好像它会一直在运行。这对我来说很有意义。 – Urda 2010-05-27 19:36:45

回答

7
  • 缓冲区从文件可能已空。

该文件可能为空。也就是说,在打开文件时达到文件结束。 loadedString = buffRead.readLine()然后会返回null。

也许你应该添加类似if (loadedString == null) loadedString = "";

  • 文件有固定的这个没有被发现

由于FileInputStream(String)构造函数可能抛出的文件中解释一个FileNotFoundException。你做你的IOException子句捕捉这个(因为FileNotFoundExceptionIOException),所以它的精细,但你也许可以这样做:

} catch (FileNotFoundException fnfe) { 
    System.err.println("File not fonud!"); 
} catch (IOException ioex { 
    System.err.println("Some other error"); 
} 
  • 文件流没有关闭

你确实打电话给fin.close(),它在正常情况下关闭文件流。也许他意味着它不是总是关闭。 readLine可能会抛出IOException,在这种情况下跳过close()。这就是原因在finally条款有它(这确保它被称为无论在try - 阻塞会发生什么。(*)


(*)作为@mmyers正确地指出,把close()finally块中实际上是不够的,因为你在catch -block中调用System.exit(-1)如果这真的是所需的行为,你可以在catch-clause中设置一个错误标志,如果这个标志是

+0

如果由于catch块中的System.exit()而导致异常,finally子句将不会被执行。 – 2010-05-27 19:00:55

+0

好点!我没有想到这一点!我会更新答案。 – aioobe 2010-05-27 19:02:51

+0

从技术上讲,FileInputStream *的finalize方法会在终止时关闭流:-) – aioobe 2010-05-27 19:08:46

1

buffRead.readLine()抛出异常,您的FileInputStream会永远关闭,还是会跳过该行? finally块的用途是,即使在特殊情况下,finally块中的代码也会执行。

3

但是如果您的程序在try块的第二行或第三行上抛出异常,该怎么办?

buffRead = new BufferedReader(new InputStreamReader(fin)); 
loadedString = buffRead.readLine(); 

到此为止,文件句柄已打开并分配给fin。您可以捕获异常,但文件句柄将保持打开状态。

你要的fin.close()声明移到finally块:

} finally { 
    try { 
     if (fin != null) { 
      fin.close(); 
     } 
    } catch (IOException e2) { 
    } 
} 
+1

我想你应该在试图关闭它之前添加一个'if(fin!= null)'(如果该文件不存在)。 – Kru 2010-05-27 19:01:29

+0

谢谢@Chris,已修复。 – mob 2010-05-27 19:10:02

+0

,或者再次使用apache commons(本例中为io),只写一行:'IOUtils。closeQuietly(fin);',这正是你正在做的很少(本地)代码http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html#closeQuietly% 28java.io.InputStream%29 – 2010-05-27 19:39:48

0

除打开文件外,还有很多其他错误可能发生

最后,您最终可能会定义一个定义或不定义的fin,您必须防止出现空指针错误,并且不要忘记关闭文件会引发新的异常。

我的建议是捕捉到了这个在一个单独的程序,让的IOExceptions飞出来的:

private String readFile() throws IOException { 
    String s; 
    try { 
    fin = new FileInputStream(programPath + fileToParse); 
    buffRead = new BufferedReader(new InputStreamReader(fin)); 
    s = buffRead.readLine(); 
    fin.close(); 
    } finally { 
    if (fin != null { 
     fin.close() 
    } 
    } 
    return s 
} 

,然后在你需要它:

try { 
    loadedString = readFile(); 
} catch (IOException e) { 
    // handle issue gracefully 
} 
+0

无论是否引发异常,都会执行finally代码块。因此,在正常情况下,你有一个冗余的'fin.close()'。 'try'块中的那个可以被删除。 – 2010-05-27 19:14:49

+0

gee,这个页面上几乎每个问题都有一个apache commons解决方案。使用FileUtils.readFileToString(文件),它更短,你可以重新调用它。 http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html#readFileToString(java.io.File) – 2010-05-27 19:42:43