io-nio-socket步步为营(一)流基础
2017-10-17 18:10
387 查看
前沿:半路出家,自学io-nio-socket这块有些时日了,反反复复好多次,收获了很多,也记住了很多,但是好像不成系统,这次想彻底整好,不在简单的记住用法,更要用心理解背后的原理。道可道非常道,实践,写入自己的思考。start...
一、流基础____________________________________________________________
1、流关闭顺序
结论:只需要关闭外层流即可。
思考:因为外层流使用的是Decorator模式,最终还是底层流underlying stream。
2、io与nio比较
结论:单纯复制byte流方面,io甚至比nio快些,因为从1.4开始io用nio重新实现了,按块读取,但是
nio多个线程复用一个连接的优势,io-socket是无法获得的。
思考:需要操作系统级别的I/O,unix网络编程实践。有待提升
3、最基础的InputStream,OutputStream才是最重要的,源代码显示最终都是调用单字节的read()。而且read是抽象的,让子类去实现,非常犀利
RandomAccessFile implements DataOutput, DataInput, Closeable
ByteArrayInputStream extends InputStream
FileInputStream extends InputStream,重写了read(),skip(),应该是1.4按块读取提供效率。
SocketInputStream extends FileInputStream
4、read()返回[0-255]的int,把有符号的byte数值,转换成了无符号的int数值。可以用来判断是否EOF流结束了与否
,验证代码如下
5、InputStream小技巧
一、流基础____________________________________________________________
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(); //设置断点,观察varibales: //br.lock.lock.closed-->reader.lock.closed-->fis.closed=false br.close(); // 调用fis.read(), 报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是抽象的,让子类去实现,非常犀利
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,重写了read(),skip(),应该是1.4按块读取提供效率。
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); } }
5、InputStream小技巧
/** * @author wangnaijiang * @version 2012-12-30 1:18:12 PM */ public class StreamUtils { /** * 考虑到网络分包延迟,一直阻塞到填满缓冲区。 */ public static byte[] read1( InputStream is )throws Exception { int bytesRead = 0; byte[] input = new byte[1024]; while ( bytesRead < 1024 ) { bytesRead += is.read( input, bytesRead, 1024 - bytesRead ); } return input; } /** * 考虑到网络分包延迟,一直阻塞到填满缓冲区或读取到-1流结束。 */ public static byte[] read2( InputStream is )throws Exception { int bytesRead = 0; byte[] input = new byte[1024]; while ( bytesRead < 1024 ) { int result = is.read( input, bytesRead, 1024 - bytesRead ); if ( result == -1 ) break; bytesRead += result; } return input; } }
相关文章推荐
- io-nio-socket步步为营(二)传统IO
- io-nio-socket步步为营(三)NIO
- io-nio-socket步步为营(四)异步AIO
- io-nio-socket步步为营(五)netty框架
- io-nio-socket步步为营(六)SSL
- io-nio-socket步步为营(七) IO模型-心得体会
- io-nio-socket步步为营(八)实践练习
- 【Java TCP/IP Socket】Java NIO Socket VS 标准IO Socket
- IO与NIO对于异步Socket的处理
- Node.js, Websocket, socket.io, 基础
- JAVA SOCKET IO VS NIO
- Socket通信之BIO(同步阻塞IO)、PAIO(伪异步阻塞IO)、NIO(异步非阻塞IO)、AIO(异步非阻塞IO)、netty5之IO
- Socket.IO学习之基础入门
- 【Java TCP/IP Socket】Java NIO Socket VS 标准IO Socket
- Socket.IO学习之基础入门
- Java SE 基础复习-IO与序列化(2)-网络操作 HTTP与SOCKET
- java基础之IO与NIO
- Java IO 和 NIO 分别实现简单的Socket
- IO(一):传统IO(基于字符,字节,Socket) 与BIO,NIO,AIO 介绍
- IO基础之Properties类、数据流、RandomAccessFile类、管道流和nio的简单说明