Thanks for reading.
I'm taking a class where I need to read in PGM files character by character.
We're given code in C but I'd much rather use Java, so I tried rewriting it.
I'm hitting a snag though: using BufferedReader's read() method is returning
different values then what it should.
For example, where the c version...
> int ci2;
> FILE *fp2;
>
> fp2=fopen("inputimage","rb");
>
> ci2 = getc(fp2);
>
> printf("%d", ci2);
returns "150" for some point in the file. The Java version...
> int ci2;
>
> BufferedReader ci2 = new BufferedReader(new FileReader("inputimage"));
>
> ci2 = in2.read(t2);
>
> System.out.print(ci2);
returns "8211".
If I convert the input from both the C and Java versions back to chars and output
to files, the C versions matches the original image exactly (which it should), but
the Java version is screwy.
I assume it has to do with Java VM converting the character encodings of the input,
but I have no clue as to how to get the correct input.
Here a simple example code that just reads in the pgm (without the header info) and
outputs it to another file character by character...
import java.io.*;
public class copy {
public static void main (String[] args) throws IOException {
int i,j, input;
BufferedReader fin = new BufferedReader(new FileReader(args[0]));
BufferedWriter fout = new BufferedWriter(new FileWriter(args[1]));
// .pgm header info for a 256x256 image
fout.write("P5\n256 256\n255\n");
for (i=0; i<256; i++) {
for (j=0;j<256;j++) {
input = fin.read();
fout.write(input);
}
}
fin.close();
fout.close();
}
}
Thanks for any help anyone can provide.
- Drew G.
Oliver Wong - 17 Jan 2007 19:57 GMT
> I'm taking a class where I need to read in PGM files character by
> character.
PGM... isn't that an image file format? If so, you should be reading the
values as bytes, not as characters.
- Oliver
Tom Hawtin - 17 Jan 2007 21:12 GMT
> PGM... isn't that an image file format? If so, you should be reading the
> values as bytes, not as characters.
Like xbm, it's an image file format, but is text-based. Looks like C.
Complete hack. Great for image processing in Perl.
Tom Hawtin
A. Bolmarcich - 17 Jan 2007 20:04 GMT
> Thanks for reading.
>
> I'm taking a class where I need to read in PGM files character by character.
> We're given code in C but I'd much rather use Java, so I tried rewriting it.
> I'm hitting a snag though: using BufferedReader's read() method is returning
> different values then what it should.
A BufferedReader is designed to read a character input stream, but you
are trying to read a byte input stream. Use a BufferedInputStream
instead.
> For example, where the c version...
>
>> int ci2;
>> FILE *fp2;
>>
>> fp2=fopen("inputimage","rb");
[snip]
The "b" in the mode parameter indicates that the file is to be read
as a binary (rather than text) file. Without the "b" in the mode you
might have problems reading the file.
Although it is possible to use a BufferedReader as long as the
underlying Reader is using an encoding that converts each byte of
the input stream to a char with the same value, such as "ISO8859_1",
is would be better to avoid the byte to char conversion since you
are want byte, not char, values.
Tom Hawtin - 17 Jan 2007 20:12 GMT
>> printf("%d", ci2);
>
> returns "150" for some point in the file. The Java version...
>> System.out.print(ci2);
>
> returns "8211".
8211 is an en-dash. Presumably this is what 150 represents on your
machines configured default character encoding. Are you sure it's a PGM
file?
> I assume it has to do with Java VM converting the character encodings of the input,
> but I have no clue as to how to get the correct input.
Yup. FileWriter and FileReader are useless classes. The default
character encoding is almost never what you want for any non-trivial
program. And if it is what you want, you really should state so explicitly.
Instead use FileInputStream and InputStreamReader (and FileOutputStream
and OutputStreamWriter), with an explicit character set.
Alternatively, treat it as a binary file and drop the Readers and
Writers (but mind that byte is signed while InputStream.read() returns a
non-negative byte representation).
Tom Hawtin
someone@somedomain.com.invalid - 17 Jan 2007 20:24 GMT
>A BufferedReader is designed to read a character input stream, but you
>are trying to read a byte input stream. Use a BufferedInputStream
>instead.
Worked like a charm! Thank you very much for your help! I also needed
to change to BufferedOutputStream for the output, so
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(args[0]));
BufferedOutputStream fout = new BufferedOutputStream(new FileOutputStream(args[1]));
is what worked for me. Thanks again!
- Drew G