纵骑横飞  章仕烜

 
首先我们来看一下 DataOutputStream
 
/**
 * A data output stream lets an application write primitive Java data
 * types to an output stream in a portable way. An application can
 * then use a data input stream to read the data back in.
 *
 * @author  unascribed
 * @version 1.44, 11/17/05
 * @see     java.io.DataInputStream
 * @since   JDK1.0
 */
public
class DataOutputStream extends FilterOutputStream implements DataOutput {
    /**
     * The number of bytes written to the data output stream so far.
     * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
     */
    protected int written;
 
    /**
     * bytearr is initialized on demand by writeUTF
     */
    private byte[] bytearr = null;
 
    public DataOutputStream(OutputStream out) {
    super(out);
    }
 
    /**
     * Increases the written counter by the specified value
     * until it reaches Integer.MAX_VALUE.
     *如果说缓冲区溢出就
*/
    private void incCount(int value) {
        int temp = written + value;
        if (temp < 0) {
            temp = Integer.MAX_VALUE;
        }
        written = temp;
    }
 
/**
     * 这两个方法 和OutputStream一样的效果
     */
    public synchronized void write(int b) throws IOException {
    out.write(b);
        incCount(1);
    }
    public synchronized void write(byte b[], int off, int len)
    throws IOException {
    out.write(b, off, len);
    incCount(len);
    }
 
    /**
     * 刷新 和OutputStream一样的效果
     */
    public void flush() throws IOException {
    out.flush();
    }
 
    /**
     * 这是 标志数据流的特性的部分
     */
    public final void writeBoolean(boolean v) throws IOException {
    out.write(v ? 1 : 0); //true写的是1 底层保存的是01
    incCount(1);
    }
 
    /**
     * 对于整型,除去long类型肯定传的是long类型的,其他传入的都是int类型的
     */
    public final void writeByte(int v) throws IOException {
    out.write(v);
        incCount(1);
    }
/**
* 0xFF 十六进制 15*16+15=255 补码 0000 0000 1111 1111
* v>>>8也就是 除以2^8
* 如果你真传一个short值 那么
* 第一个数 往后挪动8位 肯定是 0000 0000 0000 0000 所以结果是写进去个空格
* 第二个数 原封不动 &255 拿到的还是原来的数 所以写进去的是对应的字符
* 所以说 这两句话就是 让写入的东西占两个位置 一个空格 一个对应的字符
*/
    public final void writeShort(int v) throws IOException {
       out out
        incCount(2);
    }
 
    public final void writeChar(int v) throws IOException {
        out.write((v >>> 8) & 0xFF);
        out.write((v >>> 0) & 0xFF);
        incCount(2);
    }
 
    public final void writeInt(int v) throws IOException {
        out.incCount(4);
    }
 
    private byte writeBuffer[] = new byte[8];
 
    /**
     *这边 代码的解读 让我茅塞顿开
* 让我搞明白了 write某种类型 绝对不是简单的把那个数字扔进输出流
* 实际上是 某种类型有几位 就拆成几位 分别用ascii方式扔进输出流
     */
    public final void writeLong(long v) throws IOException {
        writeBuffer[0] = (byte)(v >>> 56);
        writeBuffer[1] = (byte)(v >>> 48);
        writeBuffer[2] = (byte)(v >>> 40);
        writeBuffer[3] = (byte)(v >>> 32);
        writeBuffer[4] = (byte)(v >>> 24);
        writeBuffer[5] = (byte)(v >>> 16);
        writeBuffer[6] = (byte)(v >>>  8);
        writeBuffer[7] = (byte)(v >>>  0);
        out.write(writeBuffer, 0, 8);
    incCount(8);
    }
 
    /**
     *
     *
     */
    public final void writeFloat(float v) throws IOException {
    writeInt(Float.floatToIntBits(v));
    }
    public final void writeDouble(double v) throws IOException {
    writeLong(Double.doubleToLongBits(v));
    }
 
    public final void writeBytes(String s) throws IOException {
    int len = s.length();
    for (int i = 0 ; i < len ; i++) {
        out.write((byte)s.charAt(i));
    }
    incCount(len);
    }
 
    /**
     *
     */
    public final void writeChars(String s) throws IOException {
        int len = s.length();
        for (int i = 0 ; i < len ; i++) {
            int v = s.charAt(i);
            out.write((v >>> 8) & 0xFF);
            out.write((v >>> 0) & 0xFF);
        }
        incCount(len * 2);
    }
 
    /**
     * 心得: 如果说以后要写两个 工具方法 先写功能更完善的工具方法,然后就可以调用它完成
     *若干简单的工具方法
*/
    public final void writeUTF(String str) throws IOException {
        writeUTF(str, this);
    }
 
 
    static int writeUTF(String str, DataOutput out) throws IOException {
        int strlen = str.length();
    int utflen = 0;
    int c, count = 0;
 
        /* use charAt instead of copying String to char array */
    for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
       utflen++;
        } else if (c > 0x07FF) {
       utflen += 3;
        } else {
       utflen += 2;
        }
    }
 
    if (utflen > 65535)
        throw new UTFDataFormatException(
                "encoded string too long: " + utflen + " bytes");
 
        byte[] bytearr = null;
        if (out instanceof DataOutputStream) {
            DataOutputStream dos = (DataOutputStream)out;
            if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
                dos.bytearr = new byte[(utflen*2) + 2];
            bytearr = dos.bytearr;
        } else {
            bytearr = new byte[utflen+2];
        }
    
    bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
    bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF); 
       
        int i=0;
        for (i=0; i<strlen; i++) {
           c = str.charAt(i);
           if (!((c >= 0x0001) && (c <= 0x007F))) break;
           bytearr[count++] = (byte) c;
        }
   
    for (;i < strlen; i++){
            c = str.charAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
       bytearr[count++] = (byte) c;
              
        } else if (c > 0x07FF) {
       bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
       bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
        } else {
       bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
        }
    }
        out.write(bytearr, 0, utflen+2);
        return utflen + 2;
    }
 
 
    public final int size() {
    return written;
    }
}
 
 
 
 
1.在上面的 write某种类型或者说write的过程中是把多种类型都统一拆分成多个byte,如果这么存,数据会不会流失?
如果说存到一个文本文件里边会不会丢失? -----会 文本文件是ASCII码存 超出范围就用同一个�字符代替 这样这个byte就不知道是多少了
 
所以要 配合 内存流使用 :相当于 把这些字节扔进 byte[]里边 ,这样就会保证这个数据无偏差。
 
2.那么假如说我要混存 int short byte boolean char float double 怎么办?
 
那就要记住 存放的顺序 不然就 张冠李戴了。
 
 
 
 
2.再来看一下 这个 DataInputStream.class
public
class DataInputStream extends FilterInputStream implements DataInput {
 
 
    public DataInputStream(InputStream in) {
    super(in);
    }
 
    /**
     * working arrays initialized on demand by readUTF
     */
    private byte new byte[80];
    private char chararr[] = new char[80];
 
    public final int read(byte b[]) throws IOException {
    return in.read(b, 0, b.length);
    }
    public final int read(byte b[], int off, int len) throws IOException {
    return in.read(b, off, len);
    }
 
    public final void readFully(byte b[]) throws IOException {
    readFully(b, 0, b.length);
    }
 
    public final void readFully(byte b[], int off, int len) throws IOException {
    if (len < 0)
        throw new IndexOutOfBoundsException();
    int n = 0;
    while (n < len) {
        int count = in.read(b, off + n, len - n);
        if (count < 0)
       throw new EOFException();
        n += count;
    }
    }
 
  
    public final int skipBytes(int n) throws IOException {
    int total = 0;
    int cur = 0;
 
    while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
        total += cur;
    }
 
    return total;
    }
 
    /**
     * 这下边的read某种类型的方法就是制定把读进去多少个byte然后转成
     *
* 由此可见 DataIOStream的好处 : 制定读取协议
* 我可以 指定 读多少个byte 作为int 读多少个byte作为short
     */
    public final boolean readBoolean() throws IOException {
    int ch = in.read();
    if (ch < 0)
        throw new EOFException();
    return (ch != 0);
    }
    public final byte readByte() throws IOException {
    int ch = in.read();
    if (ch < 0)
        throw new EOFException();
    return (byte)(ch);
    }
 
    public final int readUnsignedByte() throws IOException {
    int ch = in.read();
    if (ch < 0)
        throw new EOFException();
    return ch;
    }
 
    public final short readShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (short)((ch1 << 8) + (ch2 << 0));
    }
 
    public final int readUnsignedShort() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (ch1 << 8) + (ch2 << 0);
    }
 
  
    public final char readChar() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        if ((ch1 | ch2) < 0)
            throw new EOFException();
        return (char)((ch1 << 8) + (ch2 << 0));
    }
 
    public final int readInt() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        int ch3 = in.read();
        int ch4 = in.read();
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }
 
    private byte readBuffer[] = new byte[8];
 
   
    public final long readLong() throws IOException {
        readFully(readBuffer, 0, 8);
        return (((long)readBuffer[0] << 56) +
                ((long)(readBuffer[1] & 255) << 48) +
       ((long)(readBuffer[2] & 255) << 40) +
                ((long)(readBuffer[3] & 255) << 32) +
                ((long)(readBuffer[4] & 255) << 24) +
                ((readBuffer[5] & 255) << 16) +
                ((readBuffer[6] & 255) <<  8) +
                ((readBuffer[7] & 255) <<  0));
    }
 
    /**
     *
     */
    public final float readFloat() throws IOException {
    return Float.intBitsToFloat(readInt());
    }
 
    /**
     *
     */
    public final double readDouble() throws IOException {
    return Double.longBitsToDouble(readLong());
    }
 
    private char lineBuffer[];
 
    /**
     *
     */
    @Deprecated
    public final String readLine() throws IOException {
    char buf[] = lineBuffer;
 
    if (buf == null) {
        buf = lineBuffer = new char[128];
    }
 
    int room = buf.length;
    int offset = 0;
    int c;
 
loop:  while (true) {
        switch (c = in.read()) {
          case -1:
          case '\n':
       break loop;
 
          case '\r':
       int c2 = in.read();
       if ((c2 != '\n') && (c2 != -1)) {
           if (!(in instanceof PushbackInputStream)) {
           this.in = new PushbackInputStream(in);
           }
           ((PushbackInputStream)in).unread(c2);
       }
       break loop;
 
          default:
       if (--room < 0) {
           buf = new char[offset + 128];
           room = buf.length - offset - 1;
           System.arraycopy(lineBuffer, 0, buf, 0, offset);
           lineBuffer = buf;
       }
       buf[offset++] = (char) c;
       break;
        }
    }
    if ((c == -1) && (offset == 0)) {
        return null;
    }
    return String.copyValueOf(buf, 0, offset);
    }
 
    public final String readUTF() throws IOException {
        return readUTF(this);
    }
 
    public final static String readUTF(DataInput in) throws IOException {
        int utflen = in.readUnsignedShort();
        byte[] bytearr = null;
        char[] chararr = null;
        if (in instanceof DataInputStream) {
            DataInputStream dis = (DataInputStream)in;
            if (dis.length < utflen){
                dis.new byte[utflen*2];
                dis.chararr = new char[utflen*2];
            }
            chararr = dis.chararr;
            bytearr = dis.        } else {
            bytearr = new byte[utflen];
            chararr = new char[utflen];
        }
 
        int c, char2, char3;
        int count = 0;
        int chararr_count=0;
 
        in.readFully(bytearr, 0, utflen);
 
        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;     
            if (c > 127) break;
            count++;
            chararr[chararr_count++]=(char)c;
        }
 
        while (count < utflen) {
            c = (int) bytearr[count] & 0xff;
            switch (c >> 4) {
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    /* 0xxxxxxx*/
                    count++;
                    chararr[chararr_count++]=(char)c;
                    break;
                case 12: case 13:
                    /* 110x xxxx   10xx xxxx*/
                    count += 2;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                            "malformed input: partial character at end");
                    char2 = (int) bytearr[count-1];
                    if ((char2 & 0xC0) != 0x80)
                        throw new UTFDataFormatException(
                            "malformed input around byte " + count);
                    chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
                                                    (char2 & 0x3F)); 
                    break;
                case 14:
                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
                    count += 3;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                            "malformed input: partial character at end");
                    char2 = (int) bytearr[count-2];
                    char3 = (int) bytearr[count-1];
                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
                        throw new UTFDataFormatException(
                            "malformed input around byte " + (count-1));
                    chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
                                                    ((char2 & 0x3F) << 6)  |
                                                    ((char3 & 0x3F) << 0));
                    break;
                default:
                    /* 10xx xxxx,  1111 xxxx */
                    throw new UTFDataFormatException(
                        "malformed input around byte " + count);
            }
        }
        // The number of chars produced may be less than utflen
        return new String(chararr, 0, chararr_count);
    }
}
 
 
作业:
1.把 一个数 用write某种类型的方法写进一个文本文件 再读取出来看看是什么效果
 
 
2.制定一套协议 完成信息 的传输
 
 
 
 

[源码]DataIOStream 数据流 处理基本数据类型的流的更多相关文章

  1. 死磕以太坊源码分析之EVM动态数据类型

    死磕以太坊源码分析之EVM动态数据类型 配合以下代码进行阅读:https://github.com/blockchainGuide/ 写文不易,给个小关注,有什么问题可以指出,便于大家交流学习. So ...

  2. 跟着大彬读源码 - Redis 5 - 对象和数据类型(上)

    相信很多人应该都知道 Redis 有五种数据类型:字符串.列表.哈希.集合和有序集合.但这五种数据类型是什么含义?Redis 的数据又是怎样存储的?今天我们一起来认识下 Redis 这五种数据结构的含 ...

  3. 跟着大彬读源码 - Redis 6 - 对象和数据类型(下)

    继续撸我们的对象和数据类型. 上节我们一起认识了字符串和列表,接下来还有哈希.集合和有序集合. 1 哈希对象 哈希对象的可选编码分别是:ziplist 和 hashtable. 1.1 ziplist ...

  4. Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍

    最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...

  5. 5.Sentinel源码分析—Sentinel如何实现自适应限流?

    Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. Sentinel源码分析-Sentinel是如何进行流量统计的? 3. Senti ...

  6. scrapy 源码解析 (五):启动流程源码分析(五) Scraper刮取器

    Scraper刮取器 对ExecutionEngine执行引擎篇出现的Scraper进行展开.Scraper的主要作用是对spider中间件进行管理,通过中间件完成请求.响应.数据分析等工作. Scr ...

  7. scrapy 源码解析 (四):启动流程源码分析(四) Scheduler调度器

    Scheduler调度器 对ExecutionEngine执行引擎篇出现的Scheduler进行展开.Scheduler用于控制Request对象的存储和获取,并提供了过滤重复Request的功能. ...

  8. scrapy 源码解析 (三):启动流程源码分析(三) ExecutionEngine执行引擎

    ExecutionEngine执行引擎 上一篇分析了CrawlerProcess和Crawler对象的建立过程,在最终调用CrawlerProcess.start()之前,会首先建立Execution ...

  9. scrapy 源码解析 (二):启动流程源码分析(二) CrawlerProcess主进程

    CrawlerProcess主进程 它控制了twisted的reactor,也就是整个事件循环.它负责配置reactor并启动事件循环,最后在所有爬取结束后停止reactor.另外还控制了一些信号操作 ...

随机推荐

  1. PAT (Advanced Level) Practise:1002. A+B for Polynomials

    [题目链接] This time, you are supposed to find A+B where A and B are two polynomials. Input Each input f ...

  2. css中的背景、边框、补丁相关属性

    css中的背景.边框.补丁相关属性 关于背景涉及到背景颜色与背景图片 背景颜色background-color即可设定: 背景图片background-image即可设定: 但是背景图片还涉及到其他的 ...

  3. linux下oracle启动问题

    需要注意的 1.由root用户切换到su oracle 不能启动sqlplus 由root用户切换到su -oracle 可以启动sqlplus 由oracle用户直接登陆也可以启动sqlplus命令 ...

  4. Unity全视角跟随鼠标右键转换视角实现——研究笔记

    using UnityEngine; using System.Collections; public class CameraMove : MonoBehaviour { public Transf ...

  5. 1.13 linux笔记

    free -m 看内存脚本 rpm -ivh 显示过程 rpm -U --upgraderpm -F --freshenrpm -e --eraserpm -e koren find / -name ...

  6. .Net WebApi 实现OAuth2.0认证

    现在多数公众平台提供的api都使用OAuth2.0认证模式,最近在搞Android方面的开发,身份认证和权限控制的各方面比较来说,使用OAuth认证的还是比较靠谱,OAuth2.0的协议可以参考htt ...

  7. Window.Open详解

    文章来源:http://www.cnblogs.com/stswordman/archive/2006/06/02/415853.html 一.window.open()支持环境:JavaScript ...

  8. there are no usable controls in this group

    今天遇到一个怪事, MFC的toolbox是灰的, 不能使用, 后来上网一查找到解决方案: 右键Toolbox, 点击"Choose Items", 重新启动VS2013, 这样t ...

  9. js 中isArray

    es5中新加的方法Array.isArray是否是数值,低版本浏览器中可以这样修复 if (!Array.isArray) { Array.isArray = function(arg) { retu ...

  10. 6个强大的AngularJS扩展应用

    本文链接:http://www.codeceo.com/article/6-angularjs-extension.html本文作者:码农网 – 小峰 AngularJS现在非常热门,是Google推 ...