Java之IO(四)DataInputStream和DataOutputStream
转载请注明源出处:http://www.cnblogs.com/lighten/p/6986155.html
1.前言
DataInputStream和DataOutputStream分别继承了FilterInputStream和FilterOutputStream,这块内容在第二节介绍BufferedInputStream和BufferedOutputStream的时候介绍过了,这里不再介绍。Java中针对于IO有许多现有的封装类可以使用,但是每个封装类都有各自的特点,使用场景不一样。本章介绍的这对IO还实现了其它的接口,DataInput和DataOutput。之前所讲到的流都是字节流,但是实际上对我们而言,字节流是没有什么太大的意义,单个字节人是无法知道含义的,所以通常需要对字节进行解析,获取真正有价值的意义。而这对流就完成了一个对基本数据类型(boolean,byte,unsignedByte,short,unsignedShort,char,int,long,float,double)的写入和读取和一些常用的读一行,读取UTF格式等方法,不需要我们自己重复写。当然Java的IO体系针对字符流有专门的Reader和Writer进行操作字符流。这在之后的章节进行介绍。
2.DataInputStream

DataInputStream需要接受一个输入源流。



这些基础的InputStream的方法都是使用输入源的基本方法。

这些方法其实也十分的简单,都是针对每个类型的特点,将其读取出来,当然写入流的时候也要这样才行。
// 读取一个整形,根据是否为0返回boolean值
public final boolean readBoolean() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (ch != 0);
} // 读取一个整形,转成byte类型(实际上存的就是byte类型)
public final byte readByte() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
} // 读取一个整形,直接返回就是无符号的byte类型值了
public final int readUnsignedByte() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return ch;
} // 读取两个字节,short是占两个字节,把第一读出来的左移8位到高8位。最后强转成short
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));
} // 和short的方式一样,不进行强转就是无符合short
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);
} // char也是两个字节,方法和short一样,最后强转成char
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));
} // int是4个字节,第一个左移24位到最高8位,之后的依次就是最后的结果
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));
} // long是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));
} // float是调用readInt再通过Float的方法来转成float
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
} // double与float类似,不过是8位所以用readLong()
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
最后的readline()方法已经被废弃了。不过可以看看源代码,比较有意思:
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);
}
用了一个无限循环,读取到换行符才进行break,因为换行符根据操作系统不同,有两种'\r\n'和'\n'。所以'\r'的时候还判断了一下后面的字符是不是\n。不是的话使用了一个PushbackInputStream,这个很有意思,一般流读取了是无法反悔的(不能再次读取),但是专门有了个反悔的输入流。这个其实也简单,和BufferedInputStream原理类似,就是里面有个数组,不同的是BufferedInputStream是为了存从流中取得的字节,PushbackInputStream是放入反悔的字节,pos计数还是从缓存大小倒数的,这也是个不同点。最后是将流读取成UTF格式的字符串。但是只限于DataOutputStream输出的,其解析有固定的格式,前一个Int是字符串长度。
3.DataOutputStream

DataOutputStream也需要一个输出源,里面有一个计数字段written,计算写入了多少字节的数据,是int类型。如果长度超多了int类型的最大值,就会使用Integer.MAX_VALUE来标记。

超过了就会变成负数,就是变成了Integer.MAX_VALUE。接下来就是与DataInputStream解析方法对应的写入方法了。
public final void writeBoolean(boolean v) throws IOException {
out.write(v ? 1 : 0);
incCount(1);
}
public final void writeByte(int v) throws IOException {
out.write(v);
incCount(1);
}
public final void writeShort(int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
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.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
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));
}
还有一些方法比如writeBytes(String)和writeUTF方法就不介绍了。
4.例子与结语
@Test
public void test() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
DataOutputStream dos = new DataOutputStream(baos);
dos.writeByte(1);
dos.writeInt(234);
dos.writeShort(56);
dos.writeLong(789L);
dos.writeDouble(11.11);
dos.writeFloat(22.22f);
dos.writeChar('a');
dos.writeBoolean(false);
dos.writeUTF("你好!");
dos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readByte());
System.out.println(dis.readInt());
System.out.println(dis.readShort());
System.out.println(dis.readLong());
System.out.println(dis.readDouble());
System.out.println(dis.readFloat());
System.out.println(dis.readChar());
System.out.println(dis.readBoolean());
System.out.println(dis.readUTF());
dis.close();
}

上述就是一个简单的例子了。这里还需要说明的是:这对流是线程不安全的,如果你要在多线程下使用,需要自己保证线程安全。
Java之IO(四)DataInputStream和DataOutputStream的更多相关文章
- java代码----------实现创建DataInputStream和DataOutputStream进行读写
总结: 主要是 捕获异常 package com.a.b; import java.io.*; public class testData { public static void main(Stri ...
- Java之IO(零)总结
转载请注明原出处:http://www.cnblogs.com/lighten/p/7274378.html 1.前言 本章是对之前所讲述的整个Java的IO包的一个总结,抽出个人认为比较重要的知识点 ...
- Java IO(十一) DataInputStream 和 DataOutputStream
Java IO(十一) DataInputStream 和 DataOutputStream 一.介绍 DataInputStream 和 DataOutputStream 是数据字节流,分别继承自 ...
- Java基础-IO流对象之数据流(DataOutputStream与DataInputStream)
Java基础-IO流对象之数据流(DataOutputStream与DataInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据流特点 操作基本数据类型 ...
- Java面向对象 IO (四)
Java面向对象 IO (四) 知识概要: (1)打印流 (2)序列流 SequenceInputStream (3)ObjectInputStream与Ob ...
- java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
本章介绍DataOutputStream.我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:http://www.cnblog ...
- java下DataInputStream与DataOutputStream写入数据的同时写入数据类型
package cn.stat.p2.demo; import java.io.DataInputStream; import java.io.DataOutputStream; import jav ...
- Java基础——IO流
今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...
- 从Decorator,Adapter模式看Java的IO库
我想任何一本介绍模式的书在讲到Decorator模式的时候不能不提到它的实际应用--在Java/IO库里面的应用,<<Java与模式>>这本书也不例外,有点不一样的是,这本书在 ...
随机推荐
- 手机PC文件传输
QQ啥的现在直接无法全部退出,很纠结后台运行,时不时的来条消息,明明电脑QQ还开着,越来越流氓了. 服务端代码: <%@ Page Language="C#" %> & ...
- Cadence丢失了csdCommon.dll
http://bbs.elecfans.com/jishu_450237_1_1.html
- webuploader在ie7下的flash模式的使用
webuploader在ie7下不能使用h5模式上传图片,只能使用flash模式. 但是出现了几个问题:(1)必须正确的引入.swf文件,才能使webuploader正常运行 ...
- OpenGL中的旋转是可以叠加的?
OpenGL中的旋转是可以叠加的? 1. opengl中的旋转 如:glrogtate(45.0f, 0, 0, 1),是将当前坐标系顺时针旋转45度,然后绘制, 程序如下: ; float line ...
- Python - 更改pip源至国内镜像
永久使用 [windows] 在用户名目录下创建一个目录 C:\Users\xxx\pip [linux] ~/.pip/pip.conf 新建pip.ini [global] index-url = ...
- Spring Boot 2 实践记录之 Redis 及 Session Redis 配置
先说 Redis 的配置,在一些网上资料中,Spring Boot 的 Redis 除了添加依赖外,还要使用 XML 或 Java 配置文件做些配置,不过经过实践并不需要. 先在 pom 文件中添加 ...
- SQL触发器操作
Deleted表用于存储DELETE和UPDATE语句所影响的行的复本.在执行DELETE或UPDATE语句时,行从触发器表中删除,并传输到deleted表中.Deleted表和触发器表通常没有相同的 ...
- 【Kindeditor编辑器】 文件上传、空间管理
包括图片上传.文件上传.Flash上传.多媒体上传.空间管理(图片空间.文件空间等等) 一.编辑器相关参数 二.简单的封装类 这里只是做了简单的封装,欢迎大家指点改正. public class Ki ...
- C#调用C++库知识点
DllImport方式: CharSet属性:Ansi短字节和Unicode长字节 CallingConvention属性:Cdecl清理和被调用方清理堆栈 EntryPoint属性:定位函数入口.如 ...
- 构建NetCore应用框架之实战篇(七):BitAdminCore框架登录功能源码解读
本篇承接上篇内容,如果你不小心点击进来,建议从第一篇开始完整阅读,文章内容继承性连贯性. 构建NetCore应用框架之实战篇系列 一.简介 1.登录功能完成后,框架的雏形已经形成,有必要进行复习. 2 ...