在BufferedReader之后使用DataInputStream

时间:2016-03-30 22:04:24

标签: java bufferedreader datainputstream pgm

示例二进制PGM文件如下:

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

enter image description 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图像, enter image description here

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

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();
        }
    }
}

输出图像如下:

enter image description here

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

2 个答案:

答案 0 :(得分:2)

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

在这种情况下,最简单的解决方案是使用弃用的方法。您可以为readLine()编写自己的替代品,但这可能会引入更多问题,而不是它有用。

  

@deprecated此方法无法将字节正确转换为字符。

这是事实,但对于ASCII字符,它可能会做你需要的。

答案 1 :(得分:0)

我得到了为什么图像向上和向左移动的原因以及为什么在bufferedReader之前使用dataInputStream时底部有黑条。释:

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