读取隐藏在java异常处理中的变量

时间:2014-07-01 13:49:24

标签: java exception-handling

我正在编写一个函数来获取文本文件,并计算在将行输出到字符串数组时它有多少行。这样做我有几个例外我需要注意。类函数有几个变量,它们应该在整个函数中都有一个范围,但是当我在异常内部的函数中写入一个值时,return语句找不到它。我已经移动了声明,没有任何帮助

返回的值" h5Files" "可能尚未初始化"由于我不知道数组有多长,我无法将其初始化为一定长度。我在代码中执行此操作,我需要一种方法来告诉return语句我现在有一个值

这是代码

public String[] ReadScanlist(String fileIn){

    int i;
    String directory ="c:\\data\\"; // "\" is an illegal character
    System.out.println(directory);
    int linereader = 0;
    String h5Files[];
    File fileToRead = new File(directory + fileIn); 
    System.out.println(fileToRead);


    try {
        FileInputStream fin = new FileInputStream(fileToRead); // open this file

        }
    catch(FileNotFoundException exc) {
        System.out.println("File Not Found");
        }


    try{
        //read bytes until EOF is detected
        do {
            FileReader fr = new FileReader(fileToRead);// Need to convert to reader
            LineNumberReader lineToRead = new LineNumberReader(fr); // Use line number reader class


            //
            while (lineToRead.readLine() != null){
                linereader++;
                }

            linereader = 0;
            lineToRead.setLineNumber(0); //reset line number
            h5Files = new String[linereader];
            while (lineToRead.readLine() != null){
                h5Files[linereader] = lineToRead.readLine(); // deposit string into array
                linereader++;
                }
            return h5Files;
            }
        while(i !=-1); // When i = -1 the end of the file has been reached    
        }
    catch(IOException exc) {
        System.out.println("Error reading file.");
        }

    try{
        FileInputStream fin = new FileInputStream(fileToRead);
        fin.close(); // close the file
        }
    catch(IOException exc) {
        System.out.println("Error Closing File");
        }
    return h5Files;
    }

3 个答案:

答案 0 :(得分:0)

  

由于我不知道数组有多长,我无法初始化它   到一定的长度。

我认为阵列对你来说不是正确的解决方案 - 更不用说它无法完成,但你会重新发明轮子。

我建议您使用LinkedList,例如:

LinkedList<String> h5Files = new LinkedList<>();
h5Files.add(lineToRead.readLine());

或者你可以通过将数组设置为一个arbritary值(例如10)来重新发明轮子,然后在它变满时重新调整它的大小,如下所示:

h5Files = new String[10];
if (linereader = h5Files.size())
{
    String[] temp = h5Files;
   h5Files = new String[2 * linereader];
   for (int i = 0; i < linereader; i++)
  {
     h5Files[i] = temp[i];
  }

}

这些解决方案中的任何一个都允许您在try块之前在安全构造函数中初始化数组(或数组替代),以便在抛出任何异常时可以访问它

答案 1 :(得分:0)

这是你的问题。请用我的评论来查看代码的消化版本。

  String h5Files[]; // here you define the variable. It still is not initialized.
  try{
        ..................
        do {
            h5Files = new String[linereader]; // here you initialize the variable
        } while(i !=-1); // When i = -1 the end of the file has been reached    
        ..................
    catch(IOException exc) {
        // if you are here the variable is still not initialized
        System.out.println("Error reading file.");
    }

    // you continue reading file even if exception was thrown while opening the file 

我认为现在问题更清晰了。您尝试打开文件并计算行数。如果成功,则创建数组。如果不是(即抛出异常时),您捕获异常但仍继续读取该文件。但在这种情况下,您的数组未初始化。

现在该如何解决这个问题?

实际上,如果您第一次无法继续阅读文件。例如,如果文件不存在,则可能发生这种情况。因此,您应该在抛出第一个异常时返回,或者根本不捕获它。实际上,如果在任何阶段抛出异常,则与文件无关。异常不是返回代码。这就是存在例外的原因。

所以,根本不要捕捉异常。将您的方法声明为throws IOException并删除所有try / catch块。

答案 2 :(得分:0)

你的代码非常奇怪。例如,这两个块没有任何意义:

try {
    FileInputStream fin = new FileInputStream(fileToRead); // open this file

    }
catch(FileNotFoundException exc) {
    System.out.println("File Not Found");
    }

try{
    FileInputStream fin = new FileInputStream(fileToRead);
    fin.close(); // close the file
    }
catch(IOException exc) {
    System.out.println("Error Closing File");
    }

我不知道你认为他们做了什么,但除了第一个泄漏记忆外,他们什么都不做。这些评论更令人担忧,他们建议您需要在Java中更多地阅读IO。

删除这些块并整理代码a(移动声明,格式化)可以得到:

public String[] ReadScanlist(String fileIn) {
    String directory = "c:\\data\\";
    String h5Files[];
    File fileToRead = new File(directory + fileIn);
    try {   
        int i = 0;
        do {
            FileReader fr = new FileReader(fileToRead);
            LineNumberReader lineToRead = new LineNumberReader(fr);
            int linereader = 0;
            while (lineToRead.readLine() != null) {
                linereader++;
            }

            linereader = 0;
            lineToRead.setLineNumber(0);
            h5Files = new String[linereader];
            while (lineToRead.readLine() != null) {
                h5Files[linereader] = lineToRead.readLine();                    
                linereader++;
            }
            return h5Files;
        } while (i != -1);
    } catch (IOException exc) {
        System.out.println("Error reading file.");
    }
    return h5Files;
}

我的第一个争论焦点是File相关代码。首先,File从底层操作系统中抽象出来,因此使用/绝对没问题。其次,File有一个File, String构造函数是有原因的,这段代码应为:

File directory = new File("c:/data");
File fileToRead = new File(directory, fileIn);

但它确实应该使用新的Path API(见下文)。

因此,您声明h5Files[]。然后,您继续读取整个文件以计算行数。然后,将h5Files[]分配给正确大小的数组。最后你填充数组。

如果在分配h5Files[]之前任何地方 ,则表示您尚未对其进行初始化,因此无法将其返回。这就是编译器告诉你的。

我不知道此代码中i做了什么,它在顶部分配给0,然后从未重新分配。这是一个无限循环。

所以,你需要重新思考你的逻辑。如果你无法阅读该文件,我建议抛出IOException从不 return null - 这是一种反模式,会导致代码中的所有数千次null次检查。如果您从未return null,则永远不必检查它。

我可以建议以下替代代码:

如果您使用的是Java 7:

public String[] ReadScanlist(String fileIn) throws IOException {
    final Path root = Paths.get("C:/data");
    final List<String> lines = Files.readAllLines(root.resolve(fileIn), StandardCharsets.UTF_8);
    return lines.toArray(new String[lines.size()]);
}

或者,如果你有Java 8:

public String[] ReadScanlist(String fileIn) throws IOException {
    final Path root = Paths.get("C:/data");
    try (final Stream<String> lines = Files.lines(root.resolve(fileIn), StandardCharsets.UTF_8)) {
        return lines.toArray(String[]::new);
    }
}