- 浏览: 304529 次
- 性别:
- 来自: 山西
博客专栏
-
天天编程
浏览量:21984
最新评论
-
变脸小伙:
运用到了场景中,希望接力
StringBuffer源码理解 -
fangsj:
IE9 安全设置 把这个禁用掉了
spring mvc 文件上传+本地预览+一次提交 -
xu-ch:
今天面试,遇到这题,求出了相似度,面试官问我算法原理是什么,悲 ...
计算字符串相似度算法——Levenshtein -
flywangfei:
你是创新工场的么?
计算字符串相似度算法——Levenshtein -
scwuwei:
六点起床比较好
《4点起床-最养生和高效的时间管理》读书笔记
1.FilterInputStream简介
列出主要的内容。
public class FilterInputStream extends InputStream { //对象引用 protected volatile InputStream in; protected FilterInputStream(InputStream in) { this.in = in; } public int read() throws IOException { return in.read(); } //这个地方的read没用用对象引用in,感觉这个地方用的特别好。 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); } }
FilterInputStream是标准的装饰模式,动态的增加对象的功能 。
2.DataInputStream
public class DataInputStream extends FilterInputStream implements DataInput {}
继承的接口是DataInput,API文档上说是从二进制流中读取字节,具体内容就不看了,直接看DataInputStream
2.1 构造函数
public DataInputStream(InputStream in) { //在上面的FilterInputStream中给变量赋值 super(in); }
2.2 read方法
这个类中没有写read()方法,直接调用传入构造函数InputStream对象的read方法,如:FileInputStream的话就是读文件的方法。
下面的两个read带参方法
//这两个方法没什么内容 public final int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); } public final int read(byte b[]) throws IOException { return in.read(b, 0, b.length); }
2.3 readFully方法
从输入流中读取一些字节,并将它们存储在缓冲区数组 b
中。
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; //首先read返回的是读了几个字节,这个方法在这里没什么意义,直接读入byte数组b。 //如果b读不满的话就会继续一个循环,然后报错。也就是说传入的b必须读满 while (n < len) { int count = in.read(b, off + n, len - n); if (count < 0) throw new EOFException(); n += count; } }
2.4 skipBytes
public final int skipBytes(int n) throws IOException { int total = 0; int cur = 0; //in.skip这个方法返回的是跳过了多少字节,返回的是long类型,这里可以随便转是因为n-total是int型,所以。。 //好奇的是为什么不直接返回,还要多一个这样的while循环?想不通。有可能是担心in所对应的对象被覆写,呵呵。 while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) { total += cur; } return total; }
2.5 各种read类型
直接看
//读一个boolean public final boolean readBoolean() throws IOException { int ch = in.read(); if (ch < 0) throw new EOFException(); //这一步可以看出boolean的真实情况,在多数情况下返回的结果是true return (ch != 0); } //读一个字节,即8位 public final byte readByte() throws IOException { int ch = in.read(); if (ch < 0) throw new EOFException(); return (byte)(ch); } //读一个short类型(16位) public final short readShort() throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); //进行以为拼装,证实一个字节是八位。后面的一个怎么需要移位0呢,多此一举?还是什么原因? return (short)((ch1 << 8) + (ch2 << 0)); } //读一个字符,也需要拼装(16位) 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类型,很明显是32位 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]; //读long类型,64位,8字节 public final long readLong() throws IOException { //看来这里是为什么读不满就报错的原因。 readFully(readBuffer, 0, 8); //转成long类型相加 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,和int一样,4字节,32位 public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } //和long一样的double public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); }
2.6 readLine 和readUTF
readLine是一个被抛弃的方法,不看了
readUTF是一个自身对应的方法,和writeUTF需要一起看,在下面一起看
3.DataOutputStream
继承关系
public class DataOutputStream extends FilterOutputStream implements DataOutput { }
FilterOutputStream也是一个标准的装饰模式, 动态的增加对象的功能 。
3.1 各种write方法
//写一个布尔,当然1是真,0是假 public final void writeBoolean(boolean v) throws IOException { out.write(v ? 1 : 0); incCount(1); } //写一个byte,这个也是占一个字节 public final void writeByte(int v) throws IOException { out.write(v); incCount(1); } //写short,两个字节,移位后强取后八位。 public final void writeShort(int v) throws IOException { out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); incCount(2); } //再看两个write 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); } //这个强转byte和强取后八位是一样的效果。 private byte writeBuffer[] = new byte[8]; 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 int size() { return written; }
有空再看看移位的相关知识。
3.2 UTF相关
static int writeUTF(String str, DataOutput out) throws IOException { int strlen = str.length(); int utflen = 0; int c, count = 0; //计算字节数,看来String的每一个字符都是两个字节,16位,也就是4x4 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; } } //一次只能写入么多。65537是最大值, 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) { //移位都是移6位,每次都要求在对应范围内。 // 大于1110 0000 小于 1110 1111 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); // 大于1000 0000 小于 10111111 ,差不多就是这个规则。 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F)); bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); } else { //这个大于 11000000 小于 11011111 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); } } //将包含两个头信息的字符都写入。 out.write(bytearr, 0, utflen+2); return utflen + 2; }
read的就比写难多了
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.bytearr.length < utflen){ dis.bytearr = new byte[utflen*2]; dis.chararr = new char[utflen*2]; } chararr = dis.chararr; bytearr = dis.bytearr; } else { bytearr = new byte[utflen]; chararr = new char[utflen]; } int c, char2, char3; int count = 0; int chararr_count=0; //在已读两个字节后读utflen长度的字节。读满 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: count++; chararr[chararr_count++]=(char)c; break; case 12: case 13: 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: 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); }
4.结束。
这两个类感觉写的比较好懂,思路清晰,没有native方法。并理解了装饰模式。
发表评论
-
fastcgi中的多线程使用
2012-04-06 22:38 137960.背景 在项目中加入了 ... -
crc循环校验原理和实现
2012-03-29 23:33 194271.CRC简介 CRC(cyclical redundanc ... -
TreeMap源码理解
2012-01-31 10:44 01.首先看构造方法 public TreeMap() { ... -
HashMap源码理解
2012-01-30 21:33 1894看看HashMap对应的源码。 1.类、接口关系 ... -
StringUtils源码理解(下)
2012-01-16 15:46 2260本文介绍StringUtils的剩下的两个方法 1. ... -
StringUtils源码理解(中)有点意思的方法
2012-01-12 00:17 3700这次不按照前面的介绍了,方法都大同小异,下面就介绍几个有意思一 ... -
StringUtils源码理解(上)
2012-01-11 23:08 4813StringUtils 源码,使用的是commons-lang ... -
Properties源码理解
2012-07-05 12:23 3961Properties用来读配置文件 ... -
字符流(一)Reader和Writer源码理解
2011-11-27 20:32 15191.Reader 1.1 继承关系 public ... -
字符流(二)BufferedReader和BufferedWriter源码理解
2011-11-27 20:33 48541.BufferedReader 1.1 继承关系 ... -
InputStream,OutputStream源码理解
2011-11-09 22:50 34201.理解字节流和字符流 按流的形式分: 字节流和字符流。 ... -
File源码理解
2011-11-07 23:55 44051.构造函数 最基本的构 ... -
Thread源码理解
2011-10-23 14:36 43611.首先看一下Runnable接口 ... -
泛型简单回顾
2011-09-06 23:36 1342泛型的简介 1.java引入泛型的好处是安全简单。 2. ... -
LinkedList源码理解
2011-08-31 00:26 1455LinkedList源码 0.首先这个类中的两个变量 ... -
Vector源码理解
2011-08-29 23:44 1550Vector类 1.系统的变量 //记录元素的数组 pr ... -
ArrayList源码理解
2011-08-15 21:02 1767构造方法: ... -
Arrays源码理解
2011-08-15 20:34 13791.equals public static boo ... -
StringBuffer源码理解
2011-06-22 19:39 5725StringBuffer 存储和操作字符串 它所继承实现的类 ...
相关推荐
5. DataInputStream和DataOutputStream:用于读写基本数据类型。 6. ObjectInputStream和ObjectOutputStream:用于序列化和反序列化对象。 四、I/O流的使用场景 1. 文件操作:读取和写入文件内容。 2. 网络通信:...
本例演示了如何自定义缓存区,并使用不具有缓冲功能的DataInputStream 和DataOutputStream 类来读写大块的数据文件。效果如图所示,当按下“Start”按钮后,程序从源文件“d:\image.jpg”读取指定大小(缓冲区的大小...
4. **事件监听**:为了实时响应用户操作和蓝牙事件,需要设置各种监听器,例如OnClickListener用于处理按钮点击,BroadcastReceiver监听蓝牙状态变化,以及DataInputStream和DataOutputStream的read()和write()方法...
【Java版飞鸽传书文件传输源码】是一款基于Java编程语言实现的局域网文件传输工具,其设计目标是提供高效、稳定的文件共享服务。Java作为一种跨平台的语言,...同时,分析和理解这段源码也是一个实践和学习的好机会。
这个项目对于学习Java网络编程和理解基础的聊天应用架构有着很好的参考价值。 首先,我们要了解Java网络编程的基础概念。在Java中,`java.net`包提供了用于网络通信的类和接口,如Socket和ServerSocket。Socket是...
5. **输入/输出系统**:涵盖File类,以及I/O流的使用,如FileInputStream、FileOutputStream、DataInputStream、DataOutputStream等,用于处理文件操作和数据传输。 6. **文件和目录操作**:源码会展示如何创建、...
- DataInputStream和DataOutputStream:提供了读写基本类型数据的能力,如int、float等。 2. **字符流**:Reader和Writer是处理字符流的基类,常用的子类有: - FileReader和FileWriter:专门用于文件的字符读写...
2. **Android源码**:源代码是软件开发的基础,它揭示了程序的内部工作原理,对于学习和理解Android应用开发至关重要。 3. **安卓源码**:与“Android源码”同义,指代用Java或Kotlin等语言编写的Android应用原始...
3. **输入/输出流**:Java的InputStream和OutputStream接口及其子类用于读取和写入数据,如使用DataInputStream和DataOutputStream处理字符编码和数据格式化。 4. **并发控制**:由于多线程环境下的资源共享,可能...
例如,使用DataInputStream和DataOutputStream可以方便地处理基本数据类型,或者使用BufferedReader和PrintWriter处理字符串。 - 必须确保发送方和接收方对数据格式有一致的理解,例如是否采用换行符分隔消息,或者...
文件复制是一个常见的I/O操作,可以使用FileInputStream和FileOutputStream结合DataInputStream和DataOutputStream实现,或者使用NIO(New IO)框架的Channels和Buffers进行高效地复制。 异常处理在文件I/O中非常...
7. **过滤流**:FilterInputStream、FilterOutputStream、FilterReader和FilterWriter是装饰器模式的应用,用于增强或修改原有流的功能,如DataInputStream和DataOutputStream增加了读写基本数据类型的能力。...
3. **DataInputStream与DataOutputStream**:这两个类扩展了InputStream和OutputStream,提供了读写基本数据类型(如int、float)和字符串的便捷方法,简化了数据序列化的过程。 4. **对象序列化与反序列化**:在...
Java读取和写入二进制大文件的方法,应该说是一个基于二进制的大文件块,演示了如何自定义缓存区,并使用不具有缓冲功能的DataInputStream 和DataOutputStream 类来读写二进制的大文件块数据,运行效果请参见如下...
8. 数据流:DataInputStream和DataOutputStream支持基本类型的数据读写,如int、double等。 9. 序列化:Java提供Serializable接口,实现该接口的类可以被序列化,保存其状态。 在这个"Java_se_io-master"资源包中...
Java IO流是Java编程语言中一个非常重要的概念,它提供了数据传输的能力,使得程序能够读取和写入数据到各种输入/输出...通过学习提供的资源,包括例题、源码和PPT,你可以全面掌握Java IO流的使用,提升你的编程能力。
而DataInputStream和DataOutputStream则用于在网络上传输字节数据。在文件传输中,会使用这些流对象进行文件内容的读取和写入。 4. **Socket编程**:Socket是网络上的两个进程间通信的端点,Java中的Socket类和...
在安卓(Android)平台上开发游戏时,数据保存和读取是一个重要的环节,特别是在涉及游戏进度、用户设置或者高分记录...通过学习和理解这些代码,开发者可以掌握在Android环境中有效地管理和持久化游戏数据的关键技术。
- 数据传输通常通过InputStream和OutputStream进行,例如使用DataInputStream和DataOutputStream可以方便地读写基本类型的数据。 2. **多线程技术** - 聊天软件需要处理多个并发连接,这就需要用到Java的多线程...
4. **DataInputStream与DataOutputStream**:这两类流提供了一种更方便的方式来读写基本类型和字符串。在游戏保存中,它们可以用来直接写入和读取数值,而无需手动转换为字节。 5. **文件路径与权限**:在Android中...