五.Java IO、NIO、文件、通讯

Java 的 I/O 大概可以分成四组:
基于字节操作的 I/O :InputStream 和 OutputStream
基于字符操作的 I/O :Writer 和 Reader
基于磁盘操作的 I/O :File
基于网络操作的 I/O :Socket


输入流只能读不能写.
输出流只能写不能读.
!java.io.RandomAccessFile类是可读可写的。


5.1 IO

InputStream/OutputStream的工作原理:
InputStream/OutputStream( 字节流 ) :一次传送一个字节。
IO中以byte[]作为缓冲,从源(可以是文件,内存中的数据等等)中读取数据到byte[]中,写入数据的时候,将byte[]写入到目标。
InputStream类中的read(byte b[], int off, int len)方法(部分):
	int i = 1;
  for (; i < len ; i++) {
      c = read();
      if (c == -1) {
          break;
      }
      b[off + i] = (byte)c;
  }


每次从源中读取一个字节,存储到byte[] b中。最多读取len个字节。缓冲区读满或者到达源末尾后,将缓冲区的数据写入目标。
read()是一个native方法,正常返回0-255,到达源数据的末尾返回-1
InputStream/OutputStream是抽象类,使用的是其子类,子类会重新定义相关方法。为了性能这些子类中的底层实现都是native方法。


Writer/Reader实现原理相似,不同的是将流数据以一个字符的长度为单位处理,并进行编码转换。


5.2 NIO



NIO特性之一:为所有的原始类型提供(Buffer)缓存支持
拷贝文件测试IO和NIO的读写速度:
	//IO方式
	public  void copyFileByIO(File file, File newFile)
	{
		try
		{
			FileInputStream fis = new FileInputStream(file);
			FileOutputStream fos = new FileOutputStream(newFile, true);
			byte[] bytes = new byte[1024];
			while (fis.read(bytes) != -1)
			{
				fos.write(bytes);
			}
			if(fis!=null)
				fis.close();
			if(fos!=null)
				fos.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	//NIO方式
	public static void copyFileByNIO(File file, File newFile)
	{
		try
		{
			FileChannel fcin = new FileInputStream(file).getChannel();
			FileChannel fcout = new FileOutputStream(newFile, true).getChannel();
			ByteBuffer bb = ByteBuffer.allocate(1024);
			while (fcin.read(bb) != -1)
			{
				bb.flip();
				fcout.write(bb);
				bb.clear();
			}
			if(fcin!=null)
				fcin.close();
			if(fcout!=null)
				fcout.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}




文件大小:3.2G
>> IO 读写耗时:114320 速度:30.45 M/s
>> NIO 读写耗时:86009 速度:40.47 M/s


NIO中使用Buffer来作为读写中转,Buffer是一个连续的内存块。
IO以流的方式处理数据,NIO以块的方式处理数据。
NIO中通过channel操作Buffer缓冲区,所以NIO速度比IO要快很多。


5.3 文件

文件处理是Java IO系统中的一个子系统。
比如要读取文件,只需要new一个FileInputStream,即可以流的方式读取文件。
 public FileInputStream(String name)
 public FileInputStream(File file)
这两种方式都可以从文件创建一个输入流。
和其它的一样read()方法都是native的,FileInputStream命名是以InputStream结尾说明他是一个输入流,那么它的工作原理就和其它流一样。
FileInputStream中有一个getChannel(),可以得到一个FileChannel对象。这是NIO中的特性,通过channel读/写数据,提高了性能。


File类:


public String getName() {
      int index = path.lastIndexOf(separatorChar);
      if (index < prefixLength) return path.substring(prefixLength);
      return path.substring(index + 1);
  }
得到文件名,其实是获得完整路径中的最后一个/(separatorChar根据系统匹配/或者\),然后截取到文件名。
同样的getParent()也是通过截取字符串来获得父目录。
File类包含了许多对文件的操作:
 public boolean isFile() //判断是不是一个文件
 public boolean isHidden() //判断是不是隐藏
 public long length() //文件长度
 public boolean exists() //文件或目录是否存在
 public boolean createNewFile() //创建文件
 public boolean delete() //删除文件
 ...
但是,File类并不只是指文件,可以将其表示为目录。
File file=new File( "D:/");
同样的File类中也包含了对目录的操作:
 public boolean isDirectory() //判断是不是一个文件夹
 public String[] list() //得到文件夹下的文件和目录的名字
 public File[] listFiles() //得到文件夹下的文件
 public boolean mkdir() //创建目录
 public boolean renameTo //重命名
 ...


示例:
File file=new File("c:/");
String[] files = file.list();
for(String s:files)
{
System.out.println(s);
}
输出:
$RECYCLE.BIN
alipay
bcd.dna.LOG1
bcd.dna.LOG2
Boot
bootmgr
BOOTSECT.BAK
cygwin
Documents and Settings
maxldr.mbr
Program Files
Program Files (x86)
ProgramData
Recovery
RECYCLER
System Volume Information
TCKYU
Users
Windows


可以看到list()将所有文件和文件夹都列了出来,包括隐藏文件和文件夹,顺序和实际文件夹中的显示顺序一致。




5.4 通讯



NIO特性之二:异步 I/O 支持
在通讯中就是: 提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 


阻塞式网络IO:
	ServerSocket server=new ServerSocket(9999); 
  Socket socket=server.accept();//使用accept()阻塞等待请求
  BufferedReader is=new BufferedReader(new InputStreamReader(client.getInputStream()));  
  PrintWriter os=new PrintWriter(client.getOutputStream());  
  BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));  
  while(true)
  {  
  	String str=is.readLine();
  }
  //...


accept()如果没有连接会一直阻塞
readLine()如果没有读取到数据,也会一直阻塞。
这样的方式,每个和客户端的连接都要用一个单独的线程来处理,每个线程拥有自己的栈空间并且占用一些 CPU 时间,当没有请求的时候就会阻塞。
假如每个客户端一天之和服务器通讯一次,那么这些线程全部都必须存在一天。这样就会浪费系统资源。


非阻塞式网络IO:
由一个专门的线程来处理所有的 IO 事件,并负责分发,采用事件驱动机制,事件到的时候才触发。


5.5 关于TCP、UDP、HTTP

TCP/IP是个协议组,可分为三个层次:
网络层:IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。
传输层:TCP协议、UDP协议。
应用层:FTP、HTTP、TELNET、SMTP、DNS等协议


!socket只是一种连接模式,不是协议。


TCP是基于连接的协议,必须建立好了连接,才能通讯。
适合传输大量数据,可靠的连接。
UDP不需要建立连接,直接把数据发送过去。因为不需要连接,所以效率高,但是可靠性没有TCP高。
适合速度快的,数据少的。


!ping命令的实现就是基于UDP。


http是一个协议,但是底层还是基于tcp的,
HTTP协议是建立在请求/响应模型上的。客户建立给服务器发送一条请求,服务器收到请求,给客户端返回一个响应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值