InputStream.read()返回int ,且范围为0到255间int值 ,从输入流读取下一个数据字节,它是以字节为单位来读的,即每次只读取一个字节内容 ,读取后面三前面补三个字节的0,这样读取出来的结果就永远为正,且为0到255间的数。如果因已到达流末尾而没有可用的字节,则返回值-1 。用于进制文件的读取。
OutputStream.write(int b)将指定的字节写入此输出流。write 的规定是:向输出流写入一个字节。要写入的字节是参数b的八个低位。b 的24个高位将被忽略。此方法能向文件中写入负数编码,即可写入二进制流的文件,如声音、图片等文件。
我们再来看看Reader与Writer字符流相应方法: Reader.readReader.read:读取单个字符。在有可用字符、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。范围在 0 到 65535 之间 (0x00-0xffff),实质上读取出来的就是一个char型,即为Unicode编码了。如果已到达流的末尾,则返回 -1
Writer. write(int c)Writer. write(int c):写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。
从上面可以看出是两类字符流,一种是字节流,另一种是字符流,如果我们读取/写入的是一个二进制文件,则使用字节流InputStream.read/OutputStream.write;如果我们读取/写入的是一个字符文件,则使用字符流Reader.read/Writer.write会很方便,当然字符流也可以使用字节流来操作,只是在某些情况下不是很方便。
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import junit.framework.TestCase; public class TestBinaryStreamReadWrite extends TestCase { /* * 写二进制文件(如声音文件)时,只能使用字节流写。outputStream.write方法 只写入最低八位, * 前三字节会丢弃掉,只存储最后一字节 */ public void testCreateByteFile() { try { FileOutputStream fo = new FileOutputStream("e:/tmp/tmp"); byte b = -1; //向文件写两个-1,没有编码为-1的字符,所以创建出的文件为纯二进制文件 fo.write(b); fo.write(b); fo.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * InputStream.read方式是读取一个字节内容后,以int型返回,在这之间有一个转换的过程:当读 * 取一个字节内容后,会在这八位二进制前再补24位二进制的0,所以最后返回的字节编码为正数,永不 * 会为负数,且范围为0-255间的整数。这样如果使用read方法读取二进制文件时,读出的编码是整数, * 原本可能为负编码,最终显示成了正编码。为了确保得到正确的原本二进制编码,在读取后只能强制转 * 换成byte型,或使用read(byte b)方式来读取。 */ public void testReadEncodeError() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); //read方ifc读取的一个字节内容,返回0到255范围内的int字节值,如果因已到达流 //末尾而没有可用的字节,则返回值-1 int readInt = fi.read(); //如果已到达文件末尾,则返回-1。虽然的文件中的每个字节的内容都是-1,但读出来的不是-1, //所以第二个字节也能输出,而不会出现只能读取第一个字节,第二个字节读不出的问题 while (readInt != -1) { //输入两个255,但输入的编码是错误的,应该为-1才对 System.out.println(readInt); //读下一字节 readInt = fi.read(); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 使用InputStream.read读取出的编码如果经过强转换byte型后,我们就不能再使用 readByte * != -1 来判断文件流是否结束了,因为如果为二进制文件,读出的编码就有 为负的,总之,如果读取 * 的是二进制文件,就不能直接使用真实编码与-1比较,只能使用available或通InputStream.read * (byte[] b)方法返回的所读字节数来判断 */ public void testAvailable() { try { File file = new File("e:/tmp/tmp"); FileInputStream fi = new FileInputStream(file); System.out.println("available实质上与file的length相同:" +file.length()); //当使用read方法读取出的编码后经强转byte后,不能使用 (byte) fi.read() != -1 来 //判断是文件流是否结束,这里我们只能使用available来判断是否达文件尾 while (fi.available() > 0) { System.out.println("available=" + fi.available()); //使用read()方法读取字节内容的编码后,只能强转byte型才能得到真实的编码 System.out.println((byte) fi.read()); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 读取二进制文件(如图片)而非字符文件时,除了使用read()读取强转byte型,使用 InputStream. * read(byte[] b)是最好的方式,此时使用读取返回的字节数来判断是否读完 */ public void testReadByByteArr() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); byte[] byteArr = new byte[1024]; //读取的字节数 int readCount = fi.read(byteArr); //如果已到达文件末尾,则返回-1 while (readCount != -1) { for (int i = 0; i < readCount; i++) { System.out.println(byteArr[i]); } readCount = fi.read(byteArr); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 使用InputStream.read读取二进制文件强转换byte型获取真实编码后,不能使用readByte != * -1 来判断是否到文件尾 */ public void testGetBytecodeByConvernt() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); //读取的一个字节内容,强制转byte型,得到真实的编码 byte readByte = (byte) fi.read(); //这里我们不能使用如下方式来判断是否读流结束,因为编码内容本身就是-1,所以不会输出任何内容 while (readByte != -1) { System.out.println((byte) readByte); readByte = (byte) fi.read(); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
|