A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 廖理 中级黑马   /  2012-5-7 21:43  /  1826 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


在用子节流复制文件时,读的时候使用用read()方法一个字节一个字节的读取,读时按一个字节一个字的读出来的,但是方法返回的是是四个字节的int数据,在写的时候也是按照四个字节int型数组写的,这样看来复制后的文件的大小应该是被复制的文件大小的4倍才对啊,那为什么实际中的两个文件的大小是一样的呢?这中间肯定做了些什么处理,是怎么处理的呢?

5 个回复

倒序浏览
本帖最后由 周素强 于 2012-5-8 11:30 编辑

read()方法返回的是下一个数据字节。一个字节的对应的int型范围是0~255。所以当然read方法当读到数据结尾时返回-1代表着数据读完了。而不是你所想的返回就是4,这个返回值是不固定是根据下一个数据字节来返回0~255之间的int型数值。
回复 使用道具 举报
简单理解一下,就是read()返回的是单个字节,byte类型的长度是-128-----127.我们一般接收的时候使用int型接收,方便后边的操作。而如果read()到下一个字节时,这个位置为空时,它就会返回负数,而不一定就是-1。因为它的底层结构都是数组,不管返回0还是正数,为了防止有对应的角标值,我们一般是使用负数来作为返回值。以保证数据的安全性和正确性。
回复 使用道具 举报
一个模拟的模型:public int read(byte b){
  if(字节流中有值){ 把字节流中的字节放在b中;return 一个非-1整数}
  else return -1
}
所以跟你的想法不太一样
回复 使用道具 举报
建议你仔细看毕老师基础视频。
首先要知道硬盘上的数据,无论什么类型,都是以二进制形式存储的。我们知道一个字节有8个二进制数字组成,那么很有可能读到某个字节出现连续8个二进制都是1的情况,那么这个字节读出来之后就是-1。而read()方法的结束标记也是-1。这样就会导致文件还没有读完,读取流就已经认为文件结束了。为了解决这种情况的发生,需要将byte类型的数据提升为int类型,并和255(0xff)进行与运算(&),这样操作的结果就是,返回结果变为int类型,但只有后8位是有效数据,前面的24位全部是0,而且但读到8个二进制都是1的情况,是不会返回-1的,而是返回255。
当然,这是读取的数据貌似是源数据的4倍,而当调用写入流的write()方法时,会自动将int类型数据强转为byte类型,也就是说只保留最后8位的有效数据,这样可以保证文件大小不变。
简言之,就是read()方法做类型提升,write方法做强转动作。
回复 使用道具 举报
楼主的理解有点偏差:
下面是JDK中InputSteam类的read()方法的源代码:
    /**
     * Reads the next byte of data from the input stream. The value byte is
     * returned as an <code>int</code> in the range <code>0</code> to
     * <code>255</code>. If no byte is available because the end of the stream
     * has been reached, the value <code>-1</code> is returned. This method
     * blocks until input data is available, the end of the stream is detected,
     * or an exception is thrown.
     *
     * <p> A subclass must provide an implementation of this method.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             stream is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public abstract int read() throws IOException;
注意红色的部分:读入的字节作为int类型的值(值范围:0-255)返回,也就是说只用了int 的低8位,高24位没用到。

再看OutputStream类的write()方法的源代码:
    /**
     * Writes the specified byte to this output stream. The general
     * contract for <code>write</code> is that one byte is written
     * to the output stream. The byte to be written is the eight
     * low-order bits of the argument <code>b</code>. The 24
     * high-order bits of <code>b</code> are ignored.
     * <p>
     * Subclasses of <code>OutputStream</code> must provide an
     * implementation for this method.
     *
     * @param      b   the <code>byte</code>.
     * @exception  IOException  if an I/O error occurs. In particular,
     *             an <code>IOException</code> may be thrown if the
     *             output stream has been closed.
     */
    public abstract void write(int b) throws IOException;
注意红色部分:参数b的低8位被写入输出流,而高24位被忽略。

源代码虽然不可能完全看懂,但是抓住其中的关键词语,对于理解一些原理问题帮助还是很大的!

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马