在 BufferedReader 之后使用 DataInputStream

Using DataInputStream after BufferedReader

示例二进制PGM文件如下:

P5
# This is a comment
10 10
255
#image intensity information in bytes that I am unable to copy paste here

喜欢

当我尝试使用以下代码读取文件时:

import java.io.*;

public class Pgm_reader2 {
    public static void main(String[] args) throws IOException {
        try {
            FileInputStream inRaw = new FileInputStream("A.pgm");
            DataInputStream dis = new DataInputStream(inRaw);
            int i = 0;
            while(i < 4){
                System.out.println(dis.readLine());
                i++;
            }
            while(dis.available() != 0){
                System.out.print(dis.readUnsignedByte() + " ");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

它完美运行并给出以下输出:

P5
# This is a comment
10 10
255
0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 0

但它表明 DataInputStream.readLine() 方法已被弃用。所以为了避免使用这种方法我尝试使用BufferedReader.readLine()方法,如下:

import java.io.*;

public class Pgm_reader2 {
    public static void main(String[] args) throws IOException {
        try {
            FileInputStream inRaw = new FileInputStream("A.pgm");
            DataInputStream dis = new DataInputStream(inRaw);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inRaw));
            int i = 0;
            while(i < 4){
                System.out.println(bufferedReader.readLine());
                i++;
            }
            while(dis.available() != 0){
                System.out.print(dis.readUnsignedByte() + " ");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

输出变为:

P5
# This is a comment
10 10
255

似乎第二个 while 循环即

while(dis.available() != 0){
    System.out.print(dis.readUnsignedByte() + " ");
}

不工作。

这可能是什么原因?

我尝试使用更大的图像,即 400x400 图像而不是 10x10 图像,

并尝试使用以下代码从一幅图像中复制字节并将其粘贴到新文件中:

import java.io.*;

public class Pgm_reader2 {
    public static void main(String[] args) throws IOException {
        try {
            FileInputStream inRaw = new FileInputStream("A.pgm");
            FileOutputStream outRaw = new FileOutputStream("B_test.pgm");
            DataInputStream dis = new DataInputStream(inRaw);
            DataOutputStream dos = new DataOutputStream(outRaw);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inRaw));
            String line = null;
            int i = 0;
            while(i < 4){
                line = bufferedReader.readLine();
                dos.writeBytes(line);
                dos.writeBytes("\n");
                i++;
            }
            int intbyte = 0;
            while(dis.available() != 0){
                intbyte = dis.readUnsignedByte();
                dos.writeByte(intbyte);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

输出图像是这样的:

如果我在整个代码中使用 DataInputStream.readLine(),则输出图像与输入图像完全相同。怎么样了?

BufferedReader 是缓冲的,这意味着它将尽可能多地读取(向上缓冲区的大小)以最小化对底层 Reader 或 Stream 的调用次数。因此,它不适合稍后更改流。一般来说,更改底层流的包装器或 reader 是个坏主意,除非你真的知道自己在做什么。

在这种情况下,最简单的解决方案是使用已弃用的方法。您可以编写自己的 readLine() 替代品,但这可能只会带来更多问题而不是帮助。

@deprecated This method does not properly convert bytes to characters.

确实如此,但是对于 ASCII 字符,它可能会满足您的需要。

我找到了为什么在 dataInputStream 之前使用 bufferedReader 时图像会向上和向左移动一点以及为什么底部有黑条的答案。解释:

如果图像大小为 400*400,我们在 header 之后有 160000 个字节要读取。由于 bufferedReader 读取额外内容并保存在其缓冲区中,我们假设它在 header 之后额外读取了 25000 字节。所以当 dataInputStream 开始读取图像强度时,它会从第 25001 个字节开始读取。它将第 2500001 个字节放在第一个位置,因此所有像素强度都向后移动 250000 个位置,即向上 62 行和向左 200 像素。由于最后少了25000字节,所以0从像素(160000-25000+1)写入到160000,因此底部的黑色条带。