转载

java网络---流

网络操作很大一部分功能就是输入和输出数据。

简单归纳就是上传和下载文件。文件也是数据的一种载体。

java对数据的操作归并为流。

所以对于数据流的操作定义2个基本类。

java.io.OutputStream

java.io.InputStream

一:OutputStream & InputStream

输出流。也就是写入数据,在这里有个易被忽视的方法:flush。

     public void flush() throws IOException {     } 

这个方法的作用,我们每次写一个字符到文件或者其他地方是十分冗余的,如果可以,那就有一个缓存,当我数据达到一定量的时候,

才开始写入的操作。

所以调用:

  public void write(byte b[], int off, int len) throws IOException  

不一定会立刻把数据写入到文件中,这个时候如果close,这部分数据就会丢失掉。

而flush的作用就是,在缓存区,不管数据是否达到一个临界值,强制把数据写入到文件中!

输入流,与输出流相对的。

也有很多方法。最重要的当然是read。

读取单个字符的方式,显然不是很好的一个方式。

     @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {         return IoBridge.read(fd, buffer, byteOffset, byteCount);     } 

以上就是android里面java/io/FileInputStream.java 读取多个字符的方法。

由于网络会比较忙,所以通常传输1024字节的内容,可能只收到512个,剩余部分还在传输过程中。

二:缓冲流

BufferedInputStream和BufferedOutputStream

他们会对inputStream & OutputStream做缓存,然后提高传输的性能。

对于网络传输来说,一次传递1个字节,但是它要包40个字节的头,所以1K的数据会变成41K,

而如果打包在一次,则只要1K多点的数据就可以,性能显然会差很多。

 @Override     public synchronized int read() throws IOException {         // Use local refs since buf and in may be invalidated by an         // unsynchronized close()         byte[] localBuf = buf;         InputStream localIn = in;         if (localBuf == null || localIn == null) {             throw streamClosed();         }          /* Are there buffered bytes available? */         if (pos >= count && fillbuf(localIn, localBuf) == -1) {             return -1; /* no, fill buffer */         }         // localBuf may have been invalidated by fillbuf         if (localBuf != buf) {             localBuf = buf;             if (localBuf == null) {                 throw streamClosed();             }         }          /* Did filling the buffer fail with -1 (EOF)? */         if (count - pos > 0) {             return localBuf[pos++] & 0xFF;         }         return -1;     } 

关键就是fillbuf这个操作,所以read方法每次读取的都是一段字节,而不是依次读取的。

 private int fillbuf(InputStream localIn, byte[] localBuf)             throws IOException {         if (markpos == -1 || (pos - markpos >= marklimit)) {             /* Mark position not set or exceeded readlimit */             int result = localIn.read(localBuf);             if (result > 0) {                 markpos = -1;                 pos = 0;                 count = result == -1 ? 0 : result;             }             return result;         }         if (markpos == 0 && marklimit > localBuf.length) {             /* Increase buffer size to accommodate the readlimit */             int newLength = localBuf.length * 2;             if (newLength > marklimit) {                 newLength = marklimit;             }             byte[] newbuf = new byte[newLength];             System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length);             // Reassign buf, which will invalidate any local references             // FIXME: what if buf was null?             localBuf = buf = newbuf;         } else if (markpos > 0) {             System.arraycopy(localBuf, markpos, localBuf, 0, localBuf.length                     - markpos);         }         /* Set the new position and mark position */         pos -= markpos;         count = markpos = 0;         int bytesread = localIn.read(localBuf, pos, localBuf.length - pos);         count = bytesread <= 0 ? pos : pos + bytesread;         return bytesread;     } 

可以看到fillbuf里面会调用

  int bytesread = localIn.read(localBuf, pos, localBuf.length - pos); 

所以buffer 会把stream放入到一个byte[]的数组里面。

三:压缩流:

 DeflaterOutputStream InflaterInputStream GZIPOutputStream GZIPInputStream ZipOutputStream ZipInputStream 

这六个就是java提供的压缩流,他们的读写就是使用read & write方法。

输出流压缩数据,输入流解压数据。

四:摘要流

DigestInputStream,DigestOutputStream

摘要流的目的,主要是可以验证数据的完整性。

虽然程序员可以更高效的写出独立的验证算法,但是统一使用以后,可以简化这部分的操作。

五:阅读器和书写器

 Reader -> BufferedReader     -> LineNumberReader         -> InputStreamReader  -> FileReader  Writer -> BufferedWriter        -> OutputStreamWriter -> FileWriter 

网络传输中有各种不同的字符编码,所以就会需要有一个读写和处理的工具来操作流。

FileReader & FileWrite是处理文件的,具体的细节就不写了!

正文到此结束
Loading...