JAVA常用类(IO篇)-DataOutputStream详解

2023-11-11

文方便阅读和理解,本文翻译自源码,适合具有一定数据结构/算法基础且有志专研源码的朋友阅读,初学者请无视。错漏之处,多谢指正!

package java.io;
/**
 * DataOutputStream 可以实现java对象到流的便捷写入. 一个应用可以随后把流读出来 
 */
public
class DataOutputStream extends FilterOutputStream implements DataOutput {
    /**
     * 目前已经写入的byte数目
     * 如果counter值溢出了,它将被赋值为Integer.MAX_VALUE
     */
    protected int written;

    /**
     * bytearr 需要被writeUTF初始化
     */
    private byte[] bytearr = null;

    /**
     *创建一个新的data output stream用来向底层特定的output stream写数据,
     *计数器counter被设置为0
     *
     * @param   out   底层output strean,被保存起来以便后面用到
     * @see     java.io.FilterOutputStream#out
     */
    public DataOutputStream(OutputStream out) {
        super(out);
    }

    /**
     * 让written增加value,如果超过Integer.MAX_VALUE,written为  *Integer.MAX_VALUE
     */
    private void incCount(int value) {
        int temp = written + value;
        if (temp < 0) {
            temp = Integer.MAX_VALUE;
        }
        written = temp;
    }

    /**
     * 对特定的byte进行写 (参数b表示8个比特位表示的int数字) 到output stream中. 如果异常被抛出, 计数器written的值加1
     * <p>
     * 实现OutputStram的write方法
     *
     * @param      b   需要被写入的byte
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     */
    public synchronized void write(int b) throws IOException {
        out.write(b);
        incCount(1);
    }

    /**
     * 从特定的byte数组中写入len个byte到output stream中,写入byte数组的起始位置为offset。如果异常抛出written的值将会增加到len
     *
     * @param      b     被写的byte数组
     * @param      off   起始位置.
     * @param      len   写入的byte个数.
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     */
    public synchronized void write(byte b[], int off, int len)
        throws IOException
    {
        out.write(b, off, len);
        incCount(len);
    }

    /**
     * 将数据刷入output stream,强制将缓存中的任何数据写入到output stream
     * 
     * DataOutputStream 的flush方法中或调用其内含的output stream的flush方法
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     * @see        java.io.OutputStream#flush()
     */
    public void flush() throws IOException {
        out.flush();
    }

    /**
     * 向内含的output stream写一个bool(相当于1的数据),如果v为true将写入1,false将写入0。如果没有任何异常抛出计数器written的值将会加1
     *
     * @param      v   被写入的bool值
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeBoolean(boolean v) throws IOException {
        out.write(v ? 1 : 0);
        incCount(1);
    }

    /**
     * 向内含的output stream写一个一个byte。如果没有任何异常抛出计数器written的值将会加1
     *
     * @param      v   被写入的值
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeByte(int v) throws IOException {
        out.write(v);
        incCount(1);
    }

    /**
     * 向内含的output stream写一个2个byte(1个short)。如果没有任何异常抛出计数器written的值将会加2
     *
     * @param      v   被写入的short值
     * @exception 如果发生I/O错误抛出I/O异常.
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeShort(int v) throws IOException {
        out.write((v >>> 8) & 0xFF);
        out.write((v >>> 0) & 0xFF);
        incCount(2);
    }

    /**
     * 写入一个char(2个byte), 先写入高位. 如果没有任何异常抛出计数器written的值将会加2.
     * 向
     * @param      v   被写入的char值
     * @exception  如果发生I/O错误抛出I/O异常.
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeChar(int v) throws IOException {
        out.write((v >>> 8) & 0xFF);
        out.write((v >>> 0) & 0xFF);
        incCount(2);
    }

    /**
     * 写入一个int(4个byte), 先写入高位. 如果没有任何异常抛出计数器written的值将会加4.
     * @param      v   被写入的int
     * @exception  如果发生I/O错误抛出I/O异常.
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeInt(int v) throws IOException {
        out.write((v >>> 24) & 0xFF);
        out.write((v >>> 16) & 0xFF);
        out.write((v >>>  8) & 0xFF);
        out.write((v >>>  0) & 0xFF);
        incCount(4);
    }

    private byte writeBuffer[] = new byte[8];

    /**
     * 写入一个long(8个byte), 先写入高位. 如果没有任何异常抛出计数器written的值将会加8.
     *
     * @param      v   a <code>long</code> to be written.
     * @exception  IOException  if an I/O error occurs.
     * @see        java.io.FilterOutputStream#out
     */
    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);
    }

    /**
     * 通过Float的floatToIntBits方法将float参数转换为int,然后将这个int值写入到内含的output stream(占据4个byte的空间),如果没有任何异常抛出计数器written的值将会加4.
     * @param      v   被写入的float
     * @exception  如果发生I/O错误抛出I/O异常
     * @see        java.io.FilterOutputStream#out
     * @see        java.lang.Float#floatToIntBits(float)
     */
    public final void writeFloat(float v) throws IOException {
        writeInt(Float.floatToIntBits(v));
    }

    /**
     * 通过Double的doubleToLongBits方法将float参数转换为double,然后将这个double值写入到内含的output stream(占据8个byte的空间),如果没有任何异常抛出计数器written的值将会加8.
     * @param      v   被写入的double值
     * @exception  如果发生I/O错误抛出I/O异常.
     * @see        java.io.FilterOutputStream#out
     * @see        java.lang.Double#doubleToLongBits(double)
     */
    public final void writeDouble(double v) throws IOException {
        writeLong(Double.doubleToLongBits(v));
    }

    /**
     * 将字符串作为一个bytes序列写入到内含的output stream中。字符串中的字符被按顺序写入,通过丢弃它高位的8个bit。如果没有任何异常抛出计数器written的值将会增加字符串s的字符数组的长度
     * 
     * @param      s   
     * @exception  如果发生I/O错误抛出I/O异常.
     * @see        java.io.FilterOutputStream#out
     */
    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);
    }

    /**
     * Writes a string to the underlying output stream as a sequence of
     * characters
     * 将字符串作为一个字符数组序列写入到内含的output stream对象中. 每一个字符像是调用了writeChar方法一样写入内含的output stream中.如果没有任何异常抛出计数器written的值将会增加字符串s的字符数组的长度
     *
     * @param      s   被写入的字符串
     * @exception  IOException 如果发生I/O错误抛出I/O异常.
     * @see        java.io.DataOutputStream#writeChar(int)
     * @see        java.io.FilterOutputStream#out
     */
    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);
    }

    /**
     * 
  将一个字符串以一种独立于机器的方法UTF-8编码,写入DataOutput对象中首先,2byte的数据会像调用writeShort方法一样写入到目标对象中,表示要追加的byte个数。这个值是真实被写出的byte的个数,而不是string字符串的字符个数,在这个长度之后,字符串中的每一个字符都是一个output,并按顺序排列,使用改良的UTF-8编码方法为每一个字符编码。如果没有任何异常抛出,计数器written将会增加output stream的byte总数的值,这个比特数将是原字符串字节数的最低二倍,最多三倍。
     *
     * @param      str   a string to be written.
     * @exception  IOException  if an I/O error occurs.
     */
    public final void writeUTF(String str) throws IOException {
        writeUTF(str, this);
    }

    /**
     * 将一个字符串以一种独立于机器的方法UTF-8编码,写入DataOutput对象中首先,2byte的数据会像调用writeShort方法一样写入到目标对象中,表示要追加的byte个数。这个值是真实被写出的byte的个数,而不是string字符串的字符个数,在这个长度之后,字符串中的每一个字符都是一个output,并按顺序排列,使用改良的UTF-8编码方法为每一个字符编码。如果没有任何异常抛出,计数器written将会增加output stream的byte总数的值,这个比特数将是原字符串字节数的最低二倍,最多三倍。
     * @param      str   被写入的字符串
     * @param      out   目标写入对象
     * @return     写出的byte数
     * @exception  IOException  如果为发生I/O错误
     */
    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;
    }

    /**
     * 返回计数器written的当前值,即当前被写入到output stream中的字符数.
     * 如果计数器的值溢出,它将会被赋值为Integer.MAX_VALUE.
     *
     * @return  written字段的值
     * @see     java.io.DataOutputStream#written
     */
    public final int size() {
        return written;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA常用类(IO篇)-DataOutputStream详解 的相关文章

  • 使用 POST 将数据从 Android 发送到 AppEngine Datastore

    抱歉 如果这是一个简单的问题 但我只是不知道我应该做什么 而且我认为我有点超出了我的深度 我想将数据从 Android 应用程序发送到在 Google App Engine 上运行的应用程序 数据必须从那里写入数据存储区 我的数据主要采用对
  • CopyOnWriteArraySet.add 和 remove 的重写等于

    我有像下面这样的课程 class A Override public boolean equals Object other return true Class B extends A Class C extends A Override
  • 如何安装 C++ 的 VOCE?

    我正在尝试安装 VOCE api 它是为 C 和 Java 构建的语音识别 API 这是我第二次使用外部 C 库 也是第一次使用 Java C api 语音链接 http voce sourceforge net http voce sou
  • Java 的 System.arraycopy() 对于小数组有效吗?

    是Java的System arraycopy 对于小数组来说是高效的 或者它是本机方法这一事实是否使其可能比简单的循环和函数调用效率低得多 本机方法是否会因跨越某种 Java 系统桥梁而产生额外的性能开销 稍微扩展一下 Sid 所写的内容
  • 为什么 DragHandler exportAsDrag 禁用我的 MouseMotionListener?

    我想实现一个简单的 JComponent 拖放 并带有 O Reilly Swing Hacks 的预览 我的问题是 如果 TransferHandler 启动 Drag MouseMotionListener 停止执行 mouseDrag
  • Spring Rest POST Json RequestBody 不支持内容类型

    当我尝试使用 post 方法发布新对象时 RequestBody 无法识别 contentType Spring 已经配置完毕 POST 可以与其他对象一起使用 但不能与这个特定对象一起使用 org springframework web
  • 如何限制用户键入时 JTextPane 中的字符数 (Java)

    我需要不允许在输入 X 后输入任何字符 我需要在输入 X 个字符后发出蜂鸣声 我知道如何在用户按 Enter 键后执行此操作 但我需要在用户按 Enter 键之前执行此操作 我从 Oracle 站点找到的方法是将 DocumentSizeF
  • 寻找 WebElements,最佳实践

    在我们当前的自动化 使用 Selenium WebDriver Java 中 我们使用 FindBy very广泛地 例如 FindBy css a name bcrumb protected List
  • 使用 Java 检索 Window 进程的 CPU 使用率

    我正在寻找一个 Java 解决方案来查找 Windows 中正在运行的进程的 CPU 使用情况 查了一下网上 关于Java解决方案的信息似乎很少 请记住 我并不是要查找 JVM 的 CPU 使用情况 而是要查找当时在 Windows 中运行
  • 如何在JUnit测试中将MockWebServer端口设置为WebClient?

    我在用着spring boot with WebClient 它被自动装配为一个 bean 问题 写一个junit集成测试 我必须使用okhttpMockWebServer 该模拟始终在随机端口上启动 例如localhost 14321 N
  • Tomcat JDBC 池中没有足够的空闲连接

    给定以下 Tomcat JDBC 连接设置
  • Ubuntu 的打包 - Web 应用程序

    Web 应用程序没有与 C 或类似文件不同的 make 文件 但是 它需要放置在特定的目录中 例如 var www 我是 Linux 打包新手 所以我的问题是 如何将我的应用程序打包到 deb 中 以便在安装时将其放入 etc myprog
  • jsf 中的类型未找到属性

    我正在尝试调用 jsf 中使用 primefaces 的属性 但我有错误 500 在托管bean PersonelBean 类型上找不到 我正在使用 hibernate jsf 和 spring PersonelBean java Mana
  • 在 HttpClient4 中使用 PoolingHttpClientConnectionManager 的正确方法出现问题 java.lang.IllegalStateException: 连接池关闭

    我正在 Java 中利用 HTTPclient4 发送 HTTP 请求并处理 HTTP 响应 我想使用连接池来提高性能 但我无法找到合适的方法来做到这一点 我正在 Java 中利用 HTTPclient4 发送 HTTP 请求并处理 HTT
  • 在Java程序中计算zip文件的md5哈希值

    我有一个 zip 文件 在我的 Java 代码中我想计算 zip 文件的 md5 哈希值 有没有我可以用于此目的的 java 库 一些例子将非常感激 谢谢 几周前我通过这篇文章做到了这一点 http www javalobby org ja
  • 如何处理文件名中的空格

    我正在尝试迭代本地目录中的文件 foreach string name in Directory GetFileSystemEntries path FileAttrtibutes att File GetAttributes name 文
  • JBoss 5 截断 base64 cookie 字符串的尾部 =

    从 JBoss 4 升级到 JBoss 5 后 我注意到最烦人的回归 它截断 base64 cookie 值的尾部等号 我花了很长时间才明白问题不是我的代码而是 JBoss 的 我用 google 搜索了一下 发现这是一个已知的问题issu
  • Admob - 没有广告可显示

    你好 我尝试制作一些在 Android 手机上显示广告的示例程序 并尝试在 v2 2 的模拟器上测试它 代码中的一切似乎都很好 但调试器中的 AdListener 表示 响应消息为零或空 onFailedToReceiveAd 没有广告可显
  • 如何手动添加Android Studio依赖

    我多次尝试向我的项目添加依赖项 但每次都会出现错误 我想添加它们的依赖项是 de hdodenhof circleimageview 1 3 0 and com github bumptech glide glide 3 6 1 所以我想下
  • 生成签名和加密的 JWT

    我正在尝试使用生成签名和加密的 JWT 令牌雨云智威汤逊 http connect2id com products nimbus jose jwt private void generateToken throws JOSEExceptio

随机推荐

  • 分库分表的概念

    目录 一 分库分表有什么用 二 分库分表的方式 三 分库分表的缺点 四 什么时候需要分库分表 五 常见的分库分表组件 总结 在前面写了一篇关于MySQL主从集群的文章 而主从的作用 在我们开发角度更大的作用是作为读写分离的支持 也是学习Sh
  • Debian系统下network和NetworkManager冲突及关闭NetworkManager

    在Debian Linux下 network服务管理对于网卡的配置 NetworkManager是由管理系统网络链接的服务和允许用户管理网络连接的客户端服务组成 network和NetworkManager服务会出现冲突 一般如果想另外使用
  • [前端系列第7弹]Vue:一个渐进式的 JavaScript 框架

    Vue 是一个用于构建用户界面的 JavaScript 框架 它具有以下特点 渐进式 Vue 可以根据不同的使用场景 灵活地选择使用库或者框架的方式 从而实现渐进式的开发 响应式 Vue 通过数据绑定和虚拟 DOM 技术 实现了高效的响应式
  • ajax数字的正则表达式,validateform正则表达式 datatype验证数字

    第8章 用户模式下的线程同步 4 lowbar 条件变量 Condition Variable 8 6 条件变量 Condition Variables 可利用临界区或SRWLock锁来实现 8 6 1 条件变量的使用 1 条件变量机制就是
  • BigDecimal转化为String

    Oracle Java字段类型转换 从数据库取出一个字段 在java中为BigDecimal类型 将其转化为String类型的字段时 报转化异常的错误java math BigDecimal cannot be cast to java l
  • Spring面试题整理

    Spring的优缺点是什么 优点 1 方便解耦 简化开发 Spring就是一个大工厂 可以将所有对象的创建和依赖关系的维护 交给Spring管理 2 AOP编程的支持 Spring提供面向切面编程 可以方便的实现对程序进行权限拦截 运行监控
  • WRF系列教程1:WRF如何得到更好的模拟结果?

    编者按 这是新开的一个系列 有时间会逐步将WRF官方培训的ppt挑选个人认为重要的进行翻译 以及结合个人的使用经验进行一些解释 由于个人水平有限 难免会出现偏差和错误 欢迎斧正 本篇内容来源于WRF官网2021年的培训ppt Applica
  • 如何用frp做内网穿透

    使用场景 需要将内网的一些应用端口开放出来 以便可以通过外网访问或者第三方调试使用 采用工具 frp 0 28 0 linux amd64 tar gz 工具下载地址 https github com fatedier frp releas
  • element 实现表格滚动vue-seamless-scroll --save

    npm install vue seamless scroll save main js import scroll from vue seamless scroll Vue use scroll
  • 服务器扩容 --挂载磁盘方式(学习笔记)

    一 查看服务器磁盘 df h fdisk l 可以看到新增加了一块硬盘 dev sdb 大概有4T的容量 二 挂载磁盘 1 进行磁盘分区 fdisk dev sdb sdb为新加磁盘名称 步骤如下 2 查看新建分区 fdisk l 3 对新
  • create connection SQLException, url: jdbc:mysql://localhost:3306/users?characterEncoding=utf-8, erro

    今天写JDBCTemplate的时候出现bug 一开始网上查的时候说可能是驱动版本和数据库版本不太对 但是后来手写连接用DriverManager获取连接是可以获取得到的 然后又用Druid连接池试了一下 也可以获取连接 所以排除这个问题
  • BP脑电数据处理

    BP Brain Products 脑电数据处理 一 BP分析软件导出数据 标签 1 1 BP分析软件加载原始数据 1 2导出Markers 1 3 将原始数据导出成edf格式输出 1 4 MATLAB处理 一 BP分析软件导出数据 标签
  • [机缘参悟-92]:《本质思考》- 本质思考的9种训练方法

    目录 前言 01 假设力 尽可能涵盖所有的可能方案 02 逆向思考力 从未来可能的失败倒推 03 共情力 不断地站在他人的角度看问题 04 信息整理力 辨别每种信息的类型和属性和背后意图 05 图像化能力 掌握更直观的表达方式 06 定规则
  • 电子电路图中VCC、IO、3V3OUT、VDD3V3解释

    1 Vcc 一般表示电源正端 是晶体管集电极或IC集电极供电电压 2 IO 输入 输出端口 3 3V3OUT 3 3V输出端 4 VDD 一般表示电源正端 是场效应管漏极或IC内漏极供电电压 5 3V3 3 3V端 一般是供电电压为3 3V
  • 【Django缓存实现】前端缓存和后端缓存

    目录 一 什么是缓存 二 Web缓存 一 前端缓存 二 后端缓存 三 Django缓存 一 缓存类型 二 设置缓存 1 Memcached 2 Redis 3 数据库缓存 4 文件系统缓存 5 本地内存缓存 6 虚拟缓存 用于开发模式 7
  • Windows 环境配置Github 的SSH key

    今天需要将本机编写的代码提交至github 上 但是push 远程分支提示如下错误信 remote Support for password authentication was removed on August 13 2021 Plea
  • usaco-Cow Pedigrees

    题意 求出n个节点可以构成多少种高为h的二叉树 分析 设左子树节点数x 右子树节点数为n x 1 函数dp表示满足条件的树的个数 则dp n dp x n x 1 对于未知数h dp n dp x dp n x 1 x lt n 2 x i
  • llvm和clang环境配置(续篇)

    关于llvm和clang开发环境的配置之前已经发过一篇 当时是因为llvm官网给的文档省略了很多重要信息 需要额外补充一些信息才能完成环境配置 时隔许久 重新打开llvm官网 发现他们的文档已经更新了 写的非常详细 专门列举了一节用来解释如
  • Java 集合 --- HashMap的底层原理

    Java 集合 HashMap的底层原理 HashMap的下标计算 计算步骤 为什么要 h h gt gt gt 16 为什么数组长度必须是 2 n HashMap的树化 HashMap的扩容 HashMap的put流程 HashMap的线
  • JAVA常用类(IO篇)-DataOutputStream详解

    文方便阅读和理解 本文翻译自源码 适合具有一定数据结构 算法基础且有志专研源码的朋友阅读 初学者请无视 错漏之处 多谢指正 package java io DataOutputStream 可以实现java对象到流的便捷写入 一个应用可以随