java i/o 通俗解释

1 篇文章 0 订阅

1,概述

描述Java的I/O机制,我们可以通过一个生活中的例子来形容。

拿读文件举例,我们在程序中,需要读外部文件,这就像是从河里抽水,我们需要一个抽水机,然后把抽水机丢到河流里,所以第一步,建立抽水机和河流的链接:

FileInputStream fis = new FileInputStream ("e:/yellow_river.txt");

架好设备后,就可以打开水龙头获得水啦,但获得的水需要存放,所以第二步,我们还需要先有一个盛水的容器:

byte [] bottle = new byte[10];

有了抽水机,有了盛水的容器,我们只需要将容器放到水龙头下,打开抽水机的水龙头,就可以得到水啦:

fis.read(bottle);

通过这三步,我们就从河里抽出了十个单位的水,并且放到了我们准备的瓶子里。之后瓶子里的水,也就是数据,就任由我们处置啦。


Java为我们提供了两种类型的抽水机,一种是XXXInputStream,它抽水的单位是字节,当然盛水的容器自然就是字节数组byte[]。

还有一种抽水机XXXReader,它抽水的单位是字符,盛水容器就是字符数组char[]。

经过这两种分类后,我们还根据抽水的源头不同再次分了类。如同抽水机根据不同的水源环境,做了特殊的处理。就像抽水机还可分为河用,湖用,海用。

XXX就表示数据的来源。如同FileInputStream,就是专门从文件中读取数据的;ByteArrayInputStream,就是专门从字符数组也就是内存中读数据的。


假设现在用户不满足只是从各种地方,按各种大小的杯子得到水。用户想,直接打开水龙头,就是热水,就是热咖啡!

显然抽水机已经力不从心了,如果把加热,煮咖啡的功能都加到抽水机中,抽水机会显得太庞杂,坏了也不好查找问题。

所以我们就在抽水机的水龙头下,接了一根加热管:

FileInputStream fis = new FileInputStream("e:/yellow_river.txt");

ObjectInputStream ois= new ObjectInputStream(fis);

这样,只需要调用加热管的水龙头,就可以获得热水啦:

ois.readDouble();

当然我们这根管子是的功能不是加热,而是加工,将数据加工成对象,这样我们就可以直接从文件中获取对象啦。


所以,总的来说,在Java中读文件,就像抽水,首先,需要根据读取单位,根据读取源,选择合适的抽水机。如果需要,还可以在抽水机后添加管子,增强功能。

试着按照排水的例子,描述写文件的机制。


2,基本使用:

既然已经了解了Java的I/O系统,我们现在要熟悉它的基本使用。

1>按字节读文件 FileInputStream & FileOutputStream 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. FileInputStream fis = new FileInputStream("e:/in.txt");   
  2. while (fis.available() > 0) {   
  3.     byte[] b = new byte[10];   
  4.     int nResult = fis.read(b);   
  5.         if (nResult == -1break;   
  6.         System.out.println(new String(b));   
  7. }   
  8. fis.close();   
FileOutputStream(String strFilename)与FileOutputStream(String name, boolean append) 的区别:

当文件已经存在时,第一个会将原来的文件内容覆盖,第二个则可以选择覆盖或写到原来内容的后面。


2>按字符读文件 FileReader & FileWriter 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. FileReader rdFile = new FileReader("e:/in.txt");   
  2. while (rdFile.ready()) {   
  3.     char[] chIn = new char[10];   
  4.         int nResult = rdFile.read(chIn);   
  5.         if (nResult == -1break;   
  6.         System.out.println(chIn);   
  7. }   
  8. rdFile.close();  

3>带缓存的读写  BufferedReader & BufferedWriter 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. FileReader rdFile = new FileReader("e:/in.txt");   
  2. BufferedReader brdFile = new BufferedReader(rdFile);   
  3. FileWriter wrFile = new FileWriter("e:/out.txt");   
  4. BufferedWriter bwrFile = new BufferedWriter(wrFile);   
  5. String strLine;   
  6. while ((strLine = brdFile.readLine()) != null) {   
  7.     bwrFile.write(strLine);   
  8.     bwrFile.newLine();   
  9. }   
  10. brdFile.close();   
  11. bwrFile.close();   

4>文件操作

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. String fileName="D:"+File.separator+"hello.txt";  
  2. File f=new File(fileName);  
  3. //创建一个新文件  
  4. f.createNewFile();   
  5.   
  6. //创建一个文件夹  
  7. f.mkdir();  
  8.   
  9. //删除一个文件  
  10. if(f.exists()){   
  11.     f.delete();    
  12. }else{    
  13.     System.out.println("文件不存在");    
  14. }  
  15.   
  16. //列出指定目录的全部文件名  
  17. String[] str=f.list();    
  18. for (int i = 0; i < str.length; i++) {   
  19.     System.out.println(str[i]);   
  20. }    
  21.   
  22. //列出指定目录的全部文件路径  
  23. File[] files=f.listFiles();   
  24. for (int i = 0; i < files.length; i++) {    
  25.     System.out.println(files[i]);    
  26. }    
  27.   
  28. //判断一个指定的路径是否为目录  
  29. if(f.isDirectory()){   
  30.     System.out.println("YES");   
  31. }else{    
  32.     System.out.println("NO");    
  33. }  
  34.   
  35. //搜索指定目录的全部内容  
  36. print(f);  
  37. public static void print(File f){   
  38.     if(f!=null){    
  39.         if(f.isDirectory()){   
  40.             File[] fileArray=f.listFiles();   
  41.             if(fileArray!=null){    
  42.                 for (int i = 0; i < fileArray.length; i++) {    
  43.                     print(fileArray[i]); //递归调用   
  44.                 }   
  45.             }    
  46.         }    
  47.     }else{    
  48.         System.out.println(f);    
  49.     }    
  50. }   


5>从控制台获取输入

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Scanner cin=new Scanner(System.in);  
  2. System.out.println("请输入你的名字:");  
  3. String name=cin.nextLine();  
  4. System.out.println("你输入你的年龄");  
  5. int age=cin.nextInt();  
  6. System.out.println("你的名字是:"+name+" "+"你的年龄是:"+age);}  

3,深入理解

既然我们已经了解了Java I/O 系统,并学会了一些简单的I/O操作,接下来请打开Java Doc,让我们看看Sun公司是怎样通过面向对象的思想,设计I/O系统的。


总的来说,InputStream和OutputStream是按字节读写数据的抽象类,Reader和Writer是按字符读写数据的抽象类。

而继承它们的都是针对特定数据源的“抽水机”或“排水机”,提供了read和write的基本实现。构造器一般都需要提供数据源。

其中有一个子类叫FilterXXX,这就是“管子”的抽象类,它的继承类,覆盖了read和write方法,提供了更强大方便的方法。它的构造器一般都需要提供“抽水机”和“排水机”。

这种设计模式是“装饰器”。详细可参考Java IO中的设计模式

各个抽水机和排水管的简介


4,Java NIO(New IO)

是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。

Java NIO 由以下几个核心部分组成: 
Channels
Buffers
Selectors

基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。
Channel:
FileChannel:从文件中读写数据。
DatagramChannel:能通过UDP读写网络中的数据。
SocketChannel:能通过TCP读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

Buffer:capacity,position(0~capacity-1),limit(capacity,position)
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
Buffer的分配:ByteBuffer buf = ByteBuffer.allocate(48);
向Buffer中写数据:
1>从Channel写:int bytesRead = inChannel.read(buf); 
2>通过put方法写:buf.put(127);
写模式切换到读模式:flip()
从Buffer中读取数据:
1>读取数据到Channel:int bytesWritten = inChannel.write(buf); 
2>使用get()方法:byte aByte = buf.get();
清空:clear(),compact()
标记:mark(),reset()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值