首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 互联网 >

io-nio-socket稳扎稳打(一)流基础

2012-12-20 
io-nio-socket步步为营(一)流基础前沿:半路出家,自学io-nio-socket这块有些时日了,反反复复好多次,收获了

io-nio-socket步步为营(一)流基础

前沿:半路出家,自学io-nio-socket这块有些时日了,反反复复好多次,收获了很多,也记住了很多,但是好像不成系统,这次想彻底整好,不在简单的记住用法,更要用心理解背后的原理。道可道非常道,实践,写入自己的思考。start...

?

一、流基础____________________________________________________________

?

1、流关闭顺序

结论:只需要关闭外层流即可。

思考:因为外层流使用的是Decorator模式,最终还是底层流underlying stream。

    public static String testStreamColseSequence( String name )throws Exception {        FileInputStream fis = new FileInputStream( name );        // InputStreamReader(fis");默认字符集为UTF-8        Reader reader = new InputStreamReader( fis );        BufferedReader br = new BufferedReader( reader );        String header = br.readLine();        br.close();        //设置断点,观察varibales,fis,reader.lock,br.lock.lock均已关闭        // 调用fis, 报Exception in thread "main" java.io.IOException: Stream Closed        System.out.println( "fis.read()=" + fis.read() );        return header;    }

?

2、io与nio比较

结论:单纯复制byte流方面,io甚至比nio快些,因为从1.4开始io用nio重新实现了,按块读取,但是

nio多个线程复制一个连接的优势,io-socket是无法获得的。

思考:需要操作系统级别的I/O,unix网络编程实践。有待提升

?

import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;/** * 测试数据:2个完全一样的的视频,101M的mp4 * iioCopy=327,nioCopy=422,因为从1.4开始io用nio重写了 ,从FileChannel fc1 = in.getChannel();即可看出端倪 * 面向流 的 I/O系统一次一个字节地处 理数据。NIO按块处理数据比按(流式的)字节处理数据要快得多,但缺少I/O的简单优雅 * @author timeriver.wang * @date 2012-12-07 9:37:22 AM */public class IOpkNIOCopy {    private static int LEN_8K = 8192;    public static void main( String[] args )        throws Exception {        ioCopy( "e:/work/1/1.MP4", "e:/work/2/1.MP4" );        nioCopy( "e:/work/1/2.MP4", "e:/work/2/2.MP4" );    }    public static void ioCopy( String name1, String name2 )        throws Exception {        long start = System.currentTimeMillis();        FileInputStream fis = new FileInputStream( name1 );        FileOutputStream fos = new FileOutputStream( name2 );        byte[] buf = new byte[LEN_8K];        while ( true ) {            int n = fis.read( buf );            if ( n == -1 ) {                break;            }            fos.write( buf, 0, n );            // 这行代码会使复制的视频变花屏。            // fos.write(99);        }        fis.close();        fos.close();        long end = System.currentTimeMillis();        long time = end - start;        System.out.println( "iioCopy=" + time );    }    public static void nioCopy( String name1, String name2 )        throws Exception {        long start = System.currentTimeMillis();        FileInputStream in = new FileInputStream( name1 );        FileOutputStream out = new FileOutputStream( name2 );        // Since:1.4,java从1.4开始提升性能        // Returns the unique FileChannel object associated with this file input stream.        FileChannel fc1 = in.getChannel();        FileChannel fc2 = out.getChannel();        ByteBuffer bb = ByteBuffer.allocate( LEN_8K );        while ( true ) {            bb.clear();            int n = fc1.read( bb );            if ( n == -1 ) {                break;            }            bb.flip();            fc2.write( bb );        }        fc1.close();        fc2.close();        long end = System.currentTimeMillis();        long time = end - start;        System.out.println( "nioCopy=" + time );    }}
?

3、最基础的InputStream,OutputStream才是最终要的,源代码显示都是,单字节的read(),归根结缔。只是read是抽象的,但是read(byte[])不是,代码技巧。reader也是。

?

RandomAccessFile implements DataOutput, DataInput, Closeable

ByteArrayInputStream extends InputStream

?

?

public abstract class InputStream implements Closeable {    private static final int MAX_SKIP_BUFFER_SIZE = 2048;//    各种read方法,各种上层input流最终都依赖这个read,体味编程之美。    public abstract int read() throws IOException;    public int read(byte b[]) throws IOException {        return read(b, 0, b.length);    }    public int read(byte b[], int off, int len) throws IOException {        int c = read();    }    public long skip(long n) throws IOException {        nr = read(skipBuffer, 0, (int)Math.min(size, remaining));    }    public int available() throws IOException {        return 0;    }    public void close() throws IOException {}//    synchronized.    public synchronized void mark(int readlimit) {}    public synchronized void reset() throws IOException {        throw new IOException("mark/reset not supported");    }    public boolean markSupported() {return false;}}

?FileInputStream extends InputStream

?

public class FileInputStream extends InputStream{    public native int read() throws IOException;    //不再调用read()了,按块读,不再按byte读取了?    private native int readBytes(byte b[], int off, int len) throws IOException;    public int read(byte b[], int off, int len) throws IOException {        return readBytes(b, off, len);    }    //也重写父类的skip为natvie方法了,不再调用read()了,    public native long skip(long n) throws IOException;    //since 1.4    public FileChannel getChannel() {        synchronized (this) {FileChannelImpl.open...}    }}

?SocketInputStream extends FileInputStream

?

private native int socketRead0(FileDescriptor fd,byte b[], int off, int len,int timeout)
?

4、read()返回[0-255]的int,把有符号的byte数值,转换成了无符号的int数值。可以用来判断是否EOF流结束了与否

,验证代码如下

?

/** * @author timeriver.wang * @date 2012-12-10 10:45:17 AM */public class Test {    public static void main( String[] args ) throws Exception{        String filePath = "d:/12.txt";        writeFile(filePath);        readFile( filePath );    }    public static void writeFile(String filePath) throws IOException{        ByteBuffer bb = ByteBuffer.allocate( 20 );        bb.putChar( 'a' );        bb.putInt( -255 );        bb.putShort((short) -255 );        bb.putChar( 'b' );        bb.putChar( 'c' );        FileOutputStream fos = new FileOutputStream(filePath);        fos.write( bb.array());    }        public static void readFile(String filePath) throws IOException{        FileInputStream fis = new FileInputStream(filePath);        ByteBuffer readbuff = ByteBuffer.allocate( 20 );        //写入的byte -1,read读取的是255,即无符号的byte数值。        int i = fis.read();        while(i != -1){            readbuff.put( (byte)i);            System.out.println(i);            i = fis.read();        }        System.out.println(readbuff);    }}

热点排行