Java 如何从FileInputStream获取EOFEException

Java 如何从FileInputStream获取EOFEException,java,fileinputstream,Java,Fileinputstream,我正在做一个关于数据压缩的项目(使用哈夫曼算法)。该项目仍在修订中。我遇到了一个非常有趣的问题。我需要从二进制文件中逐字节读取。我得到了这个文件FileInputHelper,它实现了几个方法: import java.io.IOException; public class FileInputHelper implements Closeable { private FileInputStream fileInputStream; private BufferedReader

我正在做一个关于数据压缩的项目(使用哈夫曼算法)。该项目仍在修订中。我遇到了一个非常有趣的问题。我需要从二进制文件中逐字节读取。我得到了这个文件FileInputHelper,它实现了几个方法:

import java.io.IOException;

public class FileInputHelper implements Closeable {
    private FileInputStream fileInputStream;
    private BufferedReader fileBufferedReader;

    public FileInputHelper(File file) throws IOException {
        fileInputStream = new FileInputStream(file);
        fileBufferedReader = new BufferedReader(
               new InputStreamReader(fileInputStream));
    }


    public byte readByte() throws IOException {
        return (byte)fileInputStream.read();
    }

    public char read() throws IOException {
        return (char)fileInputStream.read();
    }

    public String readLine() throws IOException {
        return fileBufferedReader.readLine();
    }

    @Override
    public void close() throws IOException{
        fileInputStream.close();
    }
}
但是当二进制文件结束时,方法应该返回-1。当然,应该如此。但是有一些测试,其中有字节,它们等于-1,但不是最后一个。
正如你所理解的,这是非常关键的。如果在中间我读到-1,我会认为文件已经结束了。但事实并非如此。有没有办法解决这个问题?我能得到EOFEException吗?如果我的代码不好,我想听听你的建议。

这就是为什么
InputStream.read()
在实际读取
byte
时声明返回类型
int
。只有
int
的低位字节用于数据。如果您读取
-1
字节,则它将返回
255
,您必须手动将其向下转换为
byte

ByteArrayInputStream in = new ByteArrayInputStream(new byte[]{1, 0, -1});
int read;
while ((read = in.read()) > -1) {
    System.out.println("As int: " + read + ", as byte: " + (byte) read);
}
将输出:

As int: 1, as byte: 1
As int: 0, as byte: 0
As int: 255, as byte: -1

您可能不想在
public char read()
方法中使用
char
,因为
char
没有签名,无法保存
-1
。返回
int
并遵循通常的惯例更具可读性。

问题是
char
是无符号的,而
byte
是有符号的。基本上,其中是一个特定字符(
0xffff
),当转换为字节时,该字符映射到
-1
。这也是InputStream上的
read()
方法返回整数的原因,即使您得到的是字节或字符

处理此问题的一种方法是在将其转换为字节或字符之前检查
read()
是否返回
-1
。然后,如果
read()。e、 g

int cur = fileInputStream.read();
if(cur == -1) {
    throw new EOFException("End of input reached");
}else {
    return (char) cur;
}
但是,捕获异常并不是用来表示操作已正常完成的一种方式。一种避免这种情况的方法是缓冲字符/字节,并添加
available()
方法,如下所示

public class FileInputHelper implements Closeable {
    private FileInputStream fileInputStream;
    private BufferedReader fileBufferedReader;
    private int next;

    public FileInputHelper(File file) throws IOException {
        fileInputStream = new FileInputStream(file);
        fileBufferedReader = new BufferedReader(
               new InputStreamReader(fileInputStream));
        next = fileInputStream.read();
    }


    public byte readByte() throws IOException {
        int cur = next;
        next = fileInputStream.read();
        if(cur == -1) {
            throw new IOException("End of file reached");
        }
        return (byte) cur;
    }

    public char read() throws IOException {
        int cur = next;
        next = fileInputStream.read();
        if(cur == -1) {
            throw new IOException("End of file reached");
        }
        return (char) cur;
    }

    public String readLine() throws IOException {
        return fileBufferedReader.readLine();
    }

    @Override
    public void close() throws IOException{
        fileInputStream.close();
    }

    // Returns true if there are more chars / bytes to read.
    public boolean available() {
        return next != -1;
    }

}

如果同时使用
read()
/
readByte()
readLine()
方法,则文件的读取方式会出现问题,因此请记住这一点。

提示:
InputStream
返回
int
:它可以返回从-1到255的值(好吧,它也可以返回
short
,但它不返回)。如果一个字节是-1,那么它以前是255。好的。这样得到文件结尾和只得到-1有什么区别呢?
byte
-1被读取为正
int
255。
int
-1是流的结尾。