首页 > 代码库 > 疯狂JAVA讲义---第十五章:输入输出(上)流的处理和文件

疯狂JAVA讲义---第十五章:输入输出(上)流的处理和文件

在Java中,把这些不同类型的输入、输出抽象为流(Stream),而其中输入或输出的数据称为数据流(Data Stream),用统一的接口来表示,从而使程序设计简单明了。

首先我要声明下:所谓的输入输出都是相对内存而言的

还要讲几个基本概念:字节流和字符流,字节流8位,主要由InputStream和OutputStream来处理。字符流16位,主要由Reader和Writer来处理。

节点流和处理流,磁盘或网络等读写的数据的流为节点流,对节点流进行封装和处理的流叫处理流。

InputStream和Reader都是抽象类,我用他们对File的实现类做例子,eg(FileInputStream)

 

[java] view plaincopy
  1. public class FileInputStreamTest  
  2. {  
  3.     public static void main(String[] args) throws IOException  
  4.     {  
  5.         //创建字节输入流  
  6.         FileInputStream fis = new FileInputStream("FileInputStreamTest.java");  
  7.         //创建一个长度为1024的“竹筒”  
  8.         byte[] bbuf = new byte[1024];  
  9.         //用于保存实际读取的字节数  
  10.         int hasRead = 0;  
  11.         //使用循环来重复“取水”过程  
  12.         while ((hasRead = fis.read(bbuf)) > 0 )  
  13.         {  
  14.             //取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!  
  15.             System.out.print(new String(bbuf , 0 , hasRead ));  
  16.         }  
  17.         fis.close();  
  18.     }  
  19. }  

eg(FileReader)

 

[java] view plaincopy
  1. public class FileWriterTest  
  2. {  
  3.     public static void main(String[] args) throws IOException  
  4.     {  
  5.         FileWriter fw = null;  
  6.         try  
  7.         {  
  8.             //创建字符输出流  
  9.             fw = new FileWriter("poem.txt");  
  10.             fw.write("锦瑟 - 李商隐/r/n");   
  11.             fw.write("锦瑟无端五十弦,一弦一柱思华年。/r/n");  
  12.             fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。/r/n");  
  13.             fw.write("沧海月明珠有泪,蓝田日暖玉生烟。/r/n");  
  14.             fw.write("此情可待成追忆,只是当时已惘然。/r/n");  
  15.         }  
  16.         catch (IOException ioe)  
  17.         {  
  18.             ioe.printStackTrace();  
  19.         }  
  20.         finally  
  21.         {  
  22.             //使用finally块来关闭文件输出流  
  23.             if (fw != null)  
  24.             {  
  25.                 fw.close();  
  26.             }  
  27.         }  
  28.     }  
  29. }  

以上是输入,下面讲下输出

OutputStream和Writer也是抽象类,我用他们对File的实现类做例子,eg(OutputStream)

 

[java] view plaincopy
  1. public class FileOutputStreamTest  
  2. {  
  3.     public static void main(String[] args) throws IOException  
  4.     {  
  5.         FileInputStream fis = null;  
  6.         FileOutputStream fos = null;  
  7.         try  
  8.         {  
  9.             //创建字节输入流  
  10.             fis = new FileInputStream("FileOutputStreamTest.java");  
  11.             //创建字节输入流  
  12.             fos = new FileOutputStream("newFile.txt");  
  13.             byte[] bbuf = new byte[32];  
  14.             int hasRead = 0;  
  15.             //循环从输入流中取出数据  
  16.             while ((hasRead = fis.read(bbuf)) > 0 )  
  17.             {  
  18.                 //每读取一次,即写入文件输出流,读了多少,就写多少。  
  19.                 fos.write(bbuf , 0 , hasRead);  
  20.             }  
  21.         }  
  22.         catch (IOException ioe)  
  23.         {  
  24.             ioe.printStackTrace();  
  25.         }  
  26.         finally  
  27.         {  
  28.             //使用finally块来关闭文件输入流  
  29.             if (fis != null)  
  30.             {  
  31.                 fis.close();  
  32.             }  
  33.             //使用finally块来关闭文件输出流  
  34.             if (fos != null)  
  35.             {  
  36.                 fos.close();  
  37.             }  
  38.         }  
  39.     }  
  40. }  

eg(Writer)

 

[java] view plaincopy
  1. public class FileWriterTest  
  2. {  
  3.     public static void main(String[] args) throws IOException  
  4.     {  
  5.         FileWriter fw = null;  
  6.         try  
  7.         {  
  8.             //创建字符输出流  
  9.             fw = new FileWriter("poem.txt");  
  10.             fw.write("锦瑟 - 李商隐/r/n");   
  11.             fw.write("锦瑟无端五十弦,一弦一柱思华年。/r/n");  
  12.             fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。/r/n");  
  13.             fw.write("沧海月明珠有泪,蓝田日暖玉生烟。/r/n");  
  14.             fw.write("此情可待成追忆,只是当时已惘然。/r/n");  
  15.         }  
  16.         catch (IOException ioe)  
  17.         {  
  18.             ioe.printStackTrace();  
  19.         }  
  20.         finally  
  21.         {  
  22.             //使用finally块来关闭文件输出流  
  23.             if (fw != null)  
  24.             {  
  25.                 fw.close();  
  26.             }  
  27.         }  
  28.     }  
  29. }  

以上都是节点流的处理,但用起来比较麻烦,下面使用处理流来简化i/o操作

 

[java] view plaincopy
  1. public class PrintStreamTest  
  2. {  
  3.     public static void main(String[] args)throws IOException  
  4.     {  
  5.         PrintStream ps = null;  
  6.         try  
  7.         {  
  8.             //创建一个节点输出流:FileOutputStream  
  9.             FileOutputStream fos = new FileOutputStream("test.txt");  
  10.             //以PrintStream来包装FileOutputStream输出流  
  11.             ps = new PrintStream(fos);  
  12.             //使用PrintStream执行输出  
  13.             ps.println("普通字符串");  
  14.             ps.println(new PrintStreamTest());  
  15.         }  
  16.         catch (IOException ioe)  
  17.         {  
  18.             ioe.printStackTrace(ps);  
  19.         }  
  20.         finally  
  21.         {  
  22.             ps.close();  
  23.         }  
  24.     }  
  25. }  

转换流,主要用于从字节流到字符流,方便流的操作,然后利用BufferedReader来方便字符流的操作,eg

 

[java] view plaincopy
  1. public class KeyinTest  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         BufferedReader br = null;  
  6.         try  
  7.         {  
  8.             //将Sytem.in对象转换成Reader对象  
  9.             InputStreamReader reader = new InputStreamReader(System.in);  
  10.             //将普通Reader包装成BufferedReader  
  11.             br = new BufferedReader(reader);  
  12.             String buffer = null;  
  13.             //采用循环方式来一行一行的读取  
  14.             while ((buffer = br.readLine()) != null)  
  15.             {  
  16.                 //如果读取的字符串为"exit",程序退出  
  17.                 if (buffer.equals("exit"))  
  18.                 {  
  19.                     System.exit(1);  
  20.                 }  
  21.                 //打印读取的内容  
  22.                 System.out.println("输入内容为:" + buffer);  
  23.             }  
  24.         }  
  25.         catch (IOException ioe)  
  26.         {  
  27.             ioe.printStackTrace();  
  28.         }  
  29.         //关闭输入流  
  30.         finally  
  31.         {  
  32.             try  
  33.             {  
  34.                 br.close();               
  35.             }  
  36.             catch (IOException ioe)  
  37.             {  
  38.                 ioe.printStackTrace();  
  39.             }  
  40.         }  
  41.     }  
  42. }  

最后讲下File类的使用,eg

 

[java] view plaincopy
  1. public class FilenameFilterTest  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         File file = new File(".");  
  6.         String[] nameList = file.list(new MyFilenameFilter());  
  7.         for (String name : nameList)  
  8.         {  
  9.             System.out.println(name);  
  10.         }  
  11.     }  
  12. }  
  13. //实现自己的FilenameFilter实现类  
  14. class MyFilenameFilter implements FilenameFilter  
  15. {  
  16.     public boolean accept(File dir, String name)  
  17.     {  
  18.         //如果文件名以.java结尾,或者文件对应一个路径,返回true  
  19.         return name.endsWith(".java")  
  20.             || new File(name).isDirectory();  
  21.     }  
  22. }  

注意我加了后缀的过滤,讲了File不得不补充RandomAccessFile,任意文件访问类,拥有reader和writer的功能,但要注意

他对文件的插入只是一种覆盖,eg

 

[java] view plaincopy
  1. public class InsertContent  
  2. {  
  3.     public static void insert(String fileName , long pos ,   
  4.         String insertContent)throws IOException  
  5.     {  
  6.         RandomAccessFile raf = null;  
  7.         //创建一个临时文件来保存插入点后的数据  
  8.         File tmp = File.createTempFile("tmp" , null);  
  9.         FileOutputStream tmpOut = null;  
  10.         FileInputStream tmpIn = null;  
  11.         tmp.deleteOnExit();  
  12.         try  
  13.         {  
  14.             raf = new RandomAccessFile(fileName , "rw");  
  15.             tmpOut = new FileOutputStream(tmp);  
  16.             tmpIn = new FileInputStream(tmp);  
  17.             raf.seek(pos);  
  18.             //--------下面代码将插入点后的内容读入临时文件中保存---------  
  19.             byte[] bbuf = new byte[64];  
  20.             //用于保存实际读取的字节数  
  21.             int hasRead = 0;  
  22.             //使用循环方式读取插入点后的数据  
  23.             while ((hasRead = raf.read(bbuf)) > 0 )  
  24.             {  
  25.                 //将读取的数据写入临时文件  
  26.                 tmpOut.write(bbuf , 0 , hasRead);  
  27.             }  
  28.             //----------下面代码插入内容----------  
  29.             //把文件记录指针重新定位到pos位置  
  30.             raf.seek(pos);  
  31.             //追加需要插入的内容  
  32.             raf.write(insertContent.getBytes());  
  33.             //追加临时文件中的内容  
  34.             while ((hasRead = tmpIn.read(bbuf)) > 0 )  
  35.             {  
  36.                 raf.write(bbuf , 0 , hasRead);  
  37.             }  
  38.         }  
  39.         finally  
  40.         {  
  41.             raf.close();  
  42.         }  
  43.     }  
  44.     public static void main(String[] args) throws IOException  
  45.     {  
  46.         insert("InsertContent.java" , 45 , "插入的内容/r/n");  
  47.     }  
  48. }

疯狂JAVA讲义---第十五章:输入输出(上)流的处理和文件