简体   繁体   English

在Java中使用try-catch时的变量范围问题

[英]Issues in scope of variables while using try-catch in Java

I have a class PDF which implements an interface fileReader . 我有一个PDF类,它实现了一个接口fileReader

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class PDF implements fileReader {
    @Override
    public byte[] readFile(File pdfDoc) {
        if (!pdfDoc.exists()) {
            System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
            return null;
        }
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        try {
            fin.read(fileContent);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileContent;
    }
}

import java.io.File;
public interface fileReader {
    <T> T readFile(File fileObject);
}

I notice that there are scope issues for variables fin . 我注意到变量fin存在范围问题。

Another implementation I made was: 我做的另一个实现是:

public byte[] readFile1(File pdfDoc) {
        if (!pdfDoc.exists()) {
            System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
            return null;
        }
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
            byte fileContent[] = new byte[(int) pdfDoc.length()];
            try {
                fin.read(fileContent);
            } catch (IOException e) {
                System.out.println("");
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        return fileContent;
    }

But now I could not access fileContent . 但现在我无法访问fileContent

How can I combine the try-catches so that I don't have scope problems? 如何组合try-catches以便我没有范围问题? Can there be a better design approach to this problem? 有没有更好的设计方法来解决这个问题? I have to make functions for reading three different types of file. 我必须创建用于读取三种不同类型文件的函数。

Since Java 7 you can combine the try-catch as follows: 从Java 7开始,您可以将try-catch组合如下:

    FileInputStream fin = null;
    try {
        fin = new FileInputStream(pdfDoc);
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        fin.read(fileContent);
    } catch (IOException | FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    }

Which, in my opinion, makes the code cleaner and variable scopes more obvious. 在我看来,这使代码更清晰,变量范围更明显。

You can nest the try catch statements: 您可以嵌套try catch语句:

    try {
       FileInputStream fin = new FileInputStream(pdfDoc);
       byte fileContent[] = new byte[(int) pdfDoc.length()];
       try {
          fin.read(fileContent);
          return fileContent;
       } catch (IOException e) {
         e.printStackTrace();
       } finally {
         fin.close();
       }

    } catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    }
    return null;

Note that I added a close() in a finally clause to clean up. 请注意,我在finally子句中添加了一个close()来清理。 And also returning null is probably not what you want in case of error, but that's application specific. 并且返回null可能不是你想要的错误,但那是特定于应用程序的。

You can have one try with multiple catch blocks. 您可以try使用多个catch块。

try {
    //do stuff
}
catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
}
catch (IOException e) {
        e.printStackTrace();
}

You can modify this part: 您可以修改此部分:

        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        try {
            fin.read(fileContent);
        } catch (IOException e) {
            e.printStackTrace();
        }

By 通过

{
......
       FileInputStream fin = null;
       byte fileContent[]=null;
        try {
            fin = new FileInputStream(pdfDoc);
            fileContent = new byte[(int) pdfDoc.length()];
            fin.read(fileContent);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }
        return fileContent
    }

I would write like this: 我会写这样的:

public byte[] readFile(File pdfDoc) {
    if (!pdfDoc.exists()) {
        System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
        return null;
    }
    FileInputStream fin = null;
    byte fileContent[] = new byte[(int) pdfDoc.length()];

    try {
        fin = new FileInputStream(pdfDoc);
        fin.read(fileContent);
    } catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (null != fin) {
            fin.close();
        }
    }   
    return fileContent;
}

Since Java 7, there is a nice utility methods for reading the entire content of a file: 从Java 7开始,有一个很好的实用方法来读取文件的整个内容:

return Files.readAllBytes(pdfFile.toPath());

This method will open and close the FileInputStream for you, so you don't need to do this yourself. 此方法将为您打开和关闭FileInputStream,因此您无需自己执行此操作。 It throws an IOException if something goes wrong. 如果出现问题,它会抛出IOException。 Usually, it's best to let this exception propagate to the caller, but if you really want to return null in that case, you can accomplish this as follows: 通常,最好让此异常传播给调用者,但如果您确实想在这种情况下返回null,则可以按如下方式完成此操作:

try {
    return Files.readAllBytes(pdfFile.toPath());
} catch (IOException e) {
    e.printStackTrace();
    return null;
}

This also has the nice advantage that the value returned in that case is explicit - or did you really mean to return an array filled with 0 values if the file could no longer be found, as your current code does? 这也有一个很好的优点,就是在这种情况下返回的值是显式的 - 或者你是否真的想要返回一个填充了0值的数组,如果找不到文件,就像你当前的代码那样?

Note that since NoSuchFileException is a subclass of IOException, the catch block will handle both. 请注意,由于NoSuchFileException是IOException的子类,因此catch块将处理这两者。 If you want to handle it differently you can write a separate catch block for the NoSuchFileException: 如果要以不同方式处理它,可以为NoSuchFileException编写一个单独的catch块:

try {
    return Files.readAllBytes(pdfFile.toPath());
} catch (NoSuchFileException e) {
    System.err.println("Oh no, the file has disappeared.");
    e.printStackTrace();
    return null;
} catch (IOException e) {
    System.err.println("The file exists, but could not be read.");
    e.printStackTrace();
    return null;
}

Finally, I should probably mention that your file reading code is incorrect, as InputStream.read() does not necessarily read the entire file at once. 最后,我可能会提到您的文件读取代码不正确,因为InputStream.read()不一定会读取整个文件。 That's why it returns the number of bytes read so you can invoke it again for the rest of the file. 这就是为什么它返回读取的字节数,以便您可以再次为文件的其余部分调用它。 But as I said, since Java 7 you don't need to use such low level APIs (unless the file is too big to fit into memory, of course). 但正如我所说,自Java 7以来,您不需要使用这样的低级API(当然,除非文件太大而无法容纳到内存中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM