如何从 FileInputStream 获取 EOFException
How to get EOFException from FileInputStream
我正在做一个关于数据压缩的项目(使用哈夫曼算法)。该项目仍在修订中。我已经 运行 遇到了一个非常有趣的问题。我需要从二进制文件中逐字节读取。我有这个文件 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();
}
}
但是当二进制文件结束时,方法应该return -1。当然,应该如此。但是有一些测试,其中有字节等于-1,但不是最后一个。
如您所知,这非常关键。如果在中间我读到 -1,我会认为文件结束了。但事实并非如此。有什么办法可以解决这个问题吗?我可以获得 EOFException 吗?如果我的代码不好,我想听听你的建议。
这就是为什么 InputStream.read()
在实际读取 byte
时声明 return 类型 int
。只有 int
的低字节用于数据。如果您读取 -1
字节,那么它将 return 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
是有符号的。基本上,当转换为字节时,映射到 -1
的特定字符 (0xffff
) 在哪里。这也是为什么 InputStream 上的 read()
方法 return 是一个整数,即使您得到的是字节或字符。
处理此问题的一种方法是在将其转换为字节或字符之前检查是否 read()
returned -1
。然后,如果 read()
执行 return -1
,您可以抛出 EOFException,并捕获它。例如,
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()
方法,那么文件的读取方式会出现问题,因此请记住这一点。
我正在做一个关于数据压缩的项目(使用哈夫曼算法)。该项目仍在修订中。我已经 运行 遇到了一个非常有趣的问题。我需要从二进制文件中逐字节读取。我有这个文件 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();
}
}
但是当二进制文件结束时,方法应该return -1。当然,应该如此。但是有一些测试,其中有字节等于-1,但不是最后一个。 如您所知,这非常关键。如果在中间我读到 -1,我会认为文件结束了。但事实并非如此。有什么办法可以解决这个问题吗?我可以获得 EOFException 吗?如果我的代码不好,我想听听你的建议。
这就是为什么 InputStream.read()
在实际读取 byte
时声明 return 类型 int
。只有 int
的低字节用于数据。如果您读取 -1
字节,那么它将 return 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
是有符号的。基本上,当转换为字节时,映射到 -1
的特定字符 (0xffff
) 在哪里。这也是为什么 InputStream 上的 read()
方法 return 是一个整数,即使您得到的是字节或字符。
处理此问题的一种方法是在将其转换为字节或字符之前检查是否 read()
returned -1
。然后,如果 read()
执行 return -1
,您可以抛出 EOFException,并捕获它。例如,
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()
方法,那么文件的读取方式会出现问题,因此请记住这一点。