黑马程序员技术交流社区

标题: 【阳哥笔记】极速秒杀Java基础之笔记系列—Day23( IO )! [打印本页]

作者: 阳哥忠粉    时间: 2015-6-7 20:16
标题: 【阳哥笔记】极速秒杀Java基础之笔记系列—Day23( IO )!


笔记总链接:http://bbs.itheima.com/thread-200600-1-1.html

8、IO

8.2 IO流

    8.2.7 File类

    需求:获取c盘目录下的隐藏文件。

    代码:
  1. import java.io.File;
  2. import java.io.FilenameFilter;

  3. public class FileListDemo{
  4.        public static void main(String[] args){
  5.             listDemo();
  6.       }

  7.        public static void listDemo(){
  8.             File dir = new File("c:\\" );

  9.             File[] files = dir.listFiles( new FilterByHidden());

  10.              for(File file : files){
  11.                   System.out.println(file);
  12.             }
  13.       }
  14. }

  15. class FilterByHidden implements FilenameFilter{
  16.        public boolean accept(File dir,String name){
  17.              return dir.isHidden();
  18.       }
  19. }
复制代码
   运行结果:

    8.2.8 递归  


    函数自身直接或者间接的调用到了自身。
    一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。这时可以用递归来解决问题。


    P.S.
    1、递归一定明确条件,否则容易栈溢出。
    2、注意一下递归的次数。

    需求:对指定目录进行所有内容的列出(包含子目录中的内容),也可以理解为深度遍历。

    代码:
  1. import java.io.File;

  2. public class FileListDemo{
  3.        public static void main(String[] args){
  4.             File dir = new File("D:\\Java\\jdk1.6.0_02\\include" );
  5.             listAll(dir,0);
  6.       }

  7.        public static void listAll(File dir, int level){
  8.             System.out.println(getSpace(level) + "dir:" + dir.getAbsolutePath());
  9.              //获取指定目录下当前的所有文件夹或者文件对象
  10.             level++;
  11.             File[] files = dir.listFiles();

  12.              for (int x = 0; x < files.length; x++){
  13.                    if (files[x].isDirectory()){
  14.                         listAll(files[x],level);
  15.                   }
  16.                   System.out.println(getSpace(level) + "file:" + files[x].getAbsolutePath());
  17.             }
  18.       }

  19.        private static String getSpace( int level){
  20.             StringBuilder sb = new StringBuilder();

  21.             sb.append( "|--" );
  22.              for (int x = 0; x < level; x++){
  23.                   sb.append( "| " );
  24.             }

  25.              return sb.toString();
  26.       }
  27. }
复制代码
    运行结果:

    需求:利用递归求6的二进制值。

    代码:
  1. public class DiGuiDemo{
  2.        public static void main(String[] args){
  3.             toBin(6);
  4.       }

  5.        public static void toBin(int num){
  6.              if(num > 0){
  7.                   toBin(num/2);
  8.                   System.out.print(num%2);
  9.             }
  10.       }
  11. }
复制代码
   运行结果:

    需求:利用递归求1到10的和。

    代码:
  1. public class DiGuiDemo{
  2.        public static void main(String[] args){
  3.              int sum = getSum(10);
  4.             System.out.println(sum);
  5.       }

  6.        public static int getSum(int num){
  7.              if(num == 1)
  8.                    return 1;
  9.              return num + getSum(num - 1);
  10.       }
  11. }
复制代码
   运行结果:



    需求:删除一个带内容的目录。
    原理:必须从里面往外删,需要进行深度遍历。


    代码:
  1. import java.io.File;

  2. public class RemoveDirTest{
  3.        public static void main(String[] args){
  4.             File dir = new File("d:\\demo" );
  5.             removeDir(dir);
  6.       }

  7.        public static void removeDir(File dir){
  8.             File[] files = dir.listFiles();

  9.              for(File file : files){
  10.                    if(file.isDirectory()){
  11.                         removeDir(file);
  12.                   } else{
  13.                         System.out.println(file + ":" + file.delete());
  14.                   }
  15.             }
  16.             System.out.println(dir + ":" + dir.delete());
  17.       }
  18. }
复制代码
   运行结果:

    8.2.9 Properties集合


    Map
          |--Hashtable
               |--Properties


    特点:
    1. 该集合中的键和值都是字符串类型。
    2. 集合中的数据可以保存到流中,或者从流中获取。

    3. 通常该集合用于操作以键值对形式存在的配置文件。

    Properties集合的存和取。

    示例1:
  1. import java.util.Properties;
  2. import java.util.Set;

  3. public class PropertiesDemo{
  4.        public static void main(String[] args){
  5.             propertiesDemo();
  6.       }

  7.        public static void propertiesDemo(){
  8.              //创建一个Properties集合
  9.             Properties prop = new Properties();

  10.              //存储元素
  11.             prop.setProperty( "zhangsan","10" );
  12.             prop.setProperty( "lisi","20" );
  13.             prop.setProperty( "wangwu","30" );
  14.             prop.setProperty( "zhaoliu","40" );
  15.             
  16.              //修改元素
  17.             prop.setProperty( "wangwu","26" );

  18.              //取出所有元素
  19.             Set<String> names = prop.stringPropertyNames();

  20.              for(String name : names){
  21.                   String value = prop.getProperty(name);
  22.                   System.out.println(name + ":" + value);
  23.             }
  24.       }
  25. }
复制代码
   运行结果:

    演示Properties集合和流对象相结合的功能。

    示例2:
  1. import java.util.Properties;

  2. public class PropertiesDemo{
  3.        public static void main(String[] args){
  4.             propertiesDemo();
  5.       }

  6.        public static void propertiesDemo(){
  7.             Properties prop = new Properties();

  8.             prop.setProperty( "zhangsan","10" );
  9.             prop.setProperty( "lisi","20" );
  10.             prop.setProperty( "wangwu","30" );
  11.             prop.setProperty( "zhaoliu","40" );
  12.             
  13.             prop.list(System.out);
  14.       }
  15. }
复制代码
    运行结果:

    示例3:  
  1. import java.io.FileOutputStream;
  2. import java.util.Properties;

  3. public class PropertiesDemo{
  4.        public static void main(String[] args) throws Exception  {
  5.             propertiesDemo();
  6.       }

  7.        public static void propertiesDemo() throws Exception {
  8.             Properties prop = new Properties();

  9.             prop.setProperty( "zhangsan","10" );
  10.             prop.setProperty( "lisi","20" );
  11.             prop.setProperty( "wangwu","30" );
  12.             prop.setProperty( "zhaoliu","40" );
  13.             
  14.              //想要将这些集合中的字符串键值信息持久化存储到文件中
  15.              //需要关联输出流
  16.             FileOutputStream fos = new FileOutputStream("info.txt" );

  17.              //将集合中数据存储到文件中
  18.             prop.store(fos, "name+age");

  19.             fos.close();
  20.       }
  21. }
复制代码
    运行结果:





    示例4:
  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileReader;
  5. import java.io.FileWriter;
  6. import java.io.IOException;
  7. import java.util.Properties;

  8. public class PropertiesDemo{
  9.        public static void main(String[] args) throws Exception {
  10.             propertiesDemo();
  11.       }

  12.        public static void propertiesDemo() throws Exception {
  13.             Properties prop = new Properties();

  14.              //集合中的数据来自于一个文件。
  15.              //注意:必须要保证该文件中的数据是键值对。
  16.              //需要使用到读取流
  17.             FileInputStream fis = new FileInputStream("info.txt" );

  18.              //使用load方法
  19.             prop.load(fis);
  20.             prop.list(System.out);

  21.             test();
  22.             myLoad();
  23.       }
  24.       
  25.        //对已有的配置文件中的信息进行修改。
  26.        //读取这个文件。并将这个文件中的键值数据存储到集合中。再通过集合对数据进行修改。
  27.        //再通过流将修改后的数据存储到文件中
  28.        public static void test() throws Exception {
  29.              //读取这个文件
  30.             File file = new File("info.txt" );
  31.              if(!file.exists()){
  32.                   file.createNewFile();   
  33.             }
  34.             FileReader fr = new FileReader("info.txt" );

  35.              //创建集合存储配置信息
  36.             Properties prop = new Properties();

  37.              //将流中信息存储到集合中
  38.             prop.load(fr);

  39.             prop.setProperty( "wangwu","26" );

  40.             FileWriter fw = new FileWriter(file);

  41.             prop.store(fw, "");

  42.             fr.close();
  43.       }

  44.        //模拟一下load方法
  45.        public static void myLoad() throws Exception {
  46.             Properties prop = new Properties();

  47.             BufferedReader bufr = new BufferedReader(new FileReader("info.txt" ));
  48.       
  49.             String line = null;

  50.              while((line = bufr.readLine()) != null){
  51.                    if(line.startsWith("#" ))
  52.                          continue;
  53.                   String[] arr = line.split( "=");
  54.                   prop.setProperty(arr[0],arr[1]);
  55.             }

  56.             prop.list(System.out);
  57.             bufr.close();
  58.       }
  59. }
复制代码
  运行结果:

    需求:获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示,并不要再运行程序。

    思路:
    1、应该有计数器
    每次程序启动都需要计数一次,并且是在原有的次数上进行计数。
    2、计数器就是一个变量。突然冒出一想法,程序启动时进行计数,计数器必须存在于内存并进行运算。
    可是程序一结束,计数器消失了。那么再次启动该程序,计数器又重新被初始化了。
    而我们需要多次启动同一个应用程序,使用的是同一个计数器。
    这就需要计数器的生命周期边长,从内存存储到硬盘文件中。
    3、如何使用这个计数器呢?
    首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件。
    获取上一次计数器次数。并进行使用次数的判断。
    其次,对该次数进行自增,并自增后的次数重新存储到配置文件中。
    4、文件中的信息该如何进行存储并体现。
    直接存储次数值可以,但是不明确该数据的含义。所以起名字就变得很重要。
    这就有了名字和值的对应,所以可以使用键值对。
    可是映射关系map集合搞定,又需要读取硬盘上的数据,所以map+io=properties。


    代码:
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.util.Properties;

  6. public class PropertiesTest{
  7.        public static void main(String[] args) throws IOException{
  8.             getAppCount();
  9.       }

  10.        public static void getAppCount() throws IOException {
  11.              //将配置文件封装成File对象
  12.             File confile = new File("count.properties" );

  13.              if(!confile.exists()){
  14.                   confile.createNewFile();
  15.             }

  16.             FileInputStream fis = new FileInputStream(confile);
  17.       
  18.             Properties prop = new Properties();

  19.             prop.load(fis);

  20.              //从集合中通过键获取次数
  21.             String value = prop.getProperty( "time");
  22.             
  23.              //定义计数器,记录获取到的次数
  24.              int count = 0;
  25.              if(value != null){
  26.                   count = Integer.parseInt(value);
  27.                    if(count >= 5){
  28.                          throw new RuntimeException("使用次数已到,请注册,给钱!" );
  29.                   }
  30.             }
  31.             count++;

  32.              //将改变后的次数重新存储到集合中。
  33.             prop.setProperty( "time",count + "" );

  34.             FileOutputStream fos = new FileOutputStream(confile);

  35.             prop.store(fos, "");

  36.             fos.close();
  37.             fis.close();
  38.       }
  39. }
复制代码
   运行结果:

    需求:获取指定目录下,指定扩展名的文件(包含子目录中的),并且将这些文件的绝对路径写入到一个文本文件中。
    简单说:就是建立一个指定扩展名的文件的列表。

    思路:
    1. 必须进行深度遍历。
    2. 要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中。
    3. 对容器中的内容进行遍历并将绝对路径写入到文件中。


    代码:
  1. import java.io.BufferedWriter;
  2. import java.io.File;
  3. import java.io.FileWriter;
  4. import java.io.FilenameFilter;
  5. import java.io.IOException;
  6. import java.util.ArrayList;
  7. import java.util.List;

  8. public class Test{
  9.        public static void main(String[] args) throws IOException {
  10.             File dir = new File("d:\\code" );
  11.             FilenameFilter filter = new FilenameFilter(){
  12.                    public boolean accept(File dir,String name){
  13.                          return name.endsWith(".java" );
  14.                   }
  15.             };

  16.             List<File> list = new ArrayList<File>();
  17.             getFiles(dir,filter,list);
  18.             File destFile = new File(dir,"javalist.txt" );
  19.             write2File(list,destFile);
  20.       }
  21.        /*
  22.       对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤。
  23.       将过滤后的内容存储到指定容器List中。
  24.       */
  25.        public static void getFiles(File dir,FilenameFilter filter,List<File> list){
  26.             File[] files = dir.listFiles();
  27.             
  28.              for(File file : files){
  29.                    //递归
  30.                    if(file.isDirectory()){
  31.                         getFiles(file,filter,list);
  32.                   } else{
  33.                          //对便利到的文件进行过滤器的过滤。将符合条件File对象,存储到List集合中
  34.                          if(filter.accept(dir,file.getName())){
  35.                               list.add(file);
  36.                         }
  37.                   }
  38.             }
  39.       }

  40.        public static void write2File(List<File> list,File destFile) throws IOException{
  41.             BufferedWriter bufw = null;
  42.              try{
  43.                   bufw = new BufferedWriter(new FileWriter(destFile));
  44.                   
  45.                    for(File file : list){
  46.                         bufw.write(file.getAbsolutePath());
  47.                         bufw.newLine();
  48.                         bufw.flush();
  49.                   }
  50.             } finally{
  51.                    if(bufw!=null)
  52.                          try{
  53.                               bufw.close();
  54.                         } catch(IOException e){
  55.                                throw new RuntimeException("关闭失败");
  56.                         }
  57.             }
  58.       }
  59. }
复制代码
    运行结果:



    8.2.10 IO包中的其他类

    打印流

    PrintWriter与PrintStream:可以直接操作输入流和文件。


    PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
    与其他输出流不同,PrintStream永远不会抛出IOException。
    PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。

    在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。

    PrintStream:
    1. 提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式
    2. 它不抛IOException

    构造函数,接收三种类型的值:
    1. 字符串路径
    2. File对象
    3. 字节输出流


    示例1:
  1. import java.io.PrintStream;

  2. public class PrintStreamDemo{
  3.        public static void main(String[] args) throws Exception {
  4.             PrintStream out = new PrintStream("print.txt" );
  5.             
  6.              //write(int b)方法只写最低8位
  7.             out.write(97); //a
  8.             //print方法将97先变成字符串保持原样将数据打印到目的地
  9.             out.print(97); //97

  10.             out.close();
  11.       }
  12. }
复制代码
   运行结果:



    PrintWriter:字符打印流

    构造函数参数:
    1. 字符串路径
    2. File对象
    3. 字节输出流
    4. 字符输出流


    示例2:
  1. import java.io.BufferedReader;
  2. import java.io.InputStreamReader;
  3. import java.io.PrintWriter;
  4. import java.io.IOException;

  5. public class PrintWriterDemo{
  6.        public static void main(String[] args) throws IOException {
  7.             BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
  8.             PrintWriter out = new PrintWriter(System.out);

  9.             String line = null;
  10.              while((line = bufr.readLine()) != null){
  11.                    if("over" .equals(line))
  12.                          break;
  13.                   out.println(line.toUpperCase());
  14.                   out.flush();
  15.             }

  16.             out.close();
  17.             bufr.close();
  18.       }
  19. }
复制代码
    运行结果:

    示例3:  
  1. import java.io.BufferedReader;
  2. import java.io.FileWriter;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintWriter;
  5. import java.io.IOException;

  6. //写入到out.txt文件中
  7. public class PrintWriterDemo{
  8.        public static void main(String[] args) throws IOException {
  9.             BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
  10.              //PrintWriter构造函数的第二个参数设置为true,表示自动刷新
  11.             PrintWriter out = new PrintWriter(new FileWriter("out.txt" ),true);

  12.             String line = null;
  13.              while((line = bufr.readLine()) != null){
  14.                    if("over" .equals(line))
  15.                          break;
  16.                   out.println(line.toUpperCase());
  17.             }

  18.             out.close();
  19.             bufr.close();
  20.       }
  21. }
复制代码
    运行结果:




    序列流
    SequenceInputStream:对多个流进行合并。

    需求:将1.txt、2.txt、3、txt文件中的数据合并到一个文件中。

    代码:
  1. import java.io.FileInputStream;
  2. import java.io.FileOutputStream;
  3. import java.io.SequenceInputStream;
  4. import java.util.Enumeration;
  5. import java.util.Vector;

  6. public class SequenceInputStreamDemo{
  7.        public static void main(String[] args) throws Exception {
  8.             Vector<FileInputStream> v = new Vector<FileInputStream>();

  9.             v.add( new FileInputStream("1.txt" ));
  10.             v.add( new FileInputStream("2.txt" ));
  11.             v.add( new FileInputStream("3.txt" ));      

  12.             Enumeration<FileInputStream> en = v.elements();

  13.             SequenceInputStream sis = new SequenceInputStream(en);

  14.             FileOutputStream fos = new FileOutputStream("4.txt" );

  15.              byte[] buf = new byte[1024];
  16.             
  17.              int len = 0;

  18.              while((len = sis.read(buf)) != -1){
  19.                   fos.write(buf,0,len);   
  20.             }

  21.             fos.close();
  22.             sis.close();
  23.       }
  24. }
复制代码
   运行结果:














    使用ArrayList比Vector效率更高。

    改进后代码:
  1. import java.io.FileInputStream;
  2. import java.io.FileOutputStream;
  3. import java.io.SequenceInputStream;
  4. import java.util.ArrayList;
  5. import java.util.Collections;
  6. import java.util.Enumeration;
  7. import java.util.Iterator;

  8. public class SequenceInputStreamDemo{
  9.        public static void main(String[] args) throws Exception {

  10.             ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
  11.              for(int x = 1; x <= 3; x++){
  12.                   al.add( new FileInputStream(x + ".txt" ));
  13.             }
  14.             
  15.              final Iterator<FileInputStream> it = al.iterator();
  16.             
  17.             Enumeration<FileInputStream> en = Collections.enumeration(al);

  18.              /*
  19.             //Collections工具类的enumeration方法核心代码:
  20.             Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
  21.                   public boolean hasMoreElements(){
  22.                         return it.hasMoreElements();
  23.                   }

  24.                   public FileInputStream nextElement(){
  25.                         return it.next();
  26.                   }
  27.             };*/

  28.             SequenceInputStream sis = new SequenceInputStream(en);

  29.             FileOutputStream fos = new FileOutputStream("4.txt" );

  30.              byte[] buf = new byte[1024];
  31.             
  32.              int len = 0;

  33.              while((len = sis.read(buf)) != -1){
  34.                   fos.write(buf,0,len);   
  35.             }

  36.             fos.close();
  37.             sis.close();
  38.       }
  39. }
复制代码

~END~





作者: 人在旅途~东营    时间: 2015-6-7 22:03
阳哥笔记好全面啊.必须转走
作者: 探索者    时间: 2015-6-7 22:52
更新速度挺快的,赞一个
作者: 灵界    时间: 2015-6-7 23:08
阳哥,神速,根本停不下啦
作者: cyd1058    时间: 2015-6-8 21:19
阳哥,很好!很强大!
作者: 流水0215    时间: 2015-6-9 09:19
阳哥真的好厉害哈,继续加油了哈
作者: 熊乾坤    时间: 2015-6-9 22:16
赞!赞!赞!赞!赞!赞!
作者: New_PS    时间: 2015-6-11 23:04
学习ing学习ing
作者: 魏海洲    时间: 2015-6-15 23:43

阳哥,神速,根本停不下啦
作者: 凌云xs    时间: 2015-6-17 20:41
赞一个。。。
作者: Foundmoon    时间: 2015-6-17 20:53
正在学IO,刚好来看看
作者: 魏海洲    时间: 2015-6-25 18:59
更新速度挺快的,赞一个
作者: Overheat    时间: 2015-7-6 19:03
分享快乐 赞一个
作者: xiongfangyuan    时间: 2015-7-6 22:11
阳哥笔记超赞哦 !!
作者: 星痕-凌    时间: 2015-7-11 22:52
又来顶帖子了!赞一个!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 星痕-凌    时间: 2015-7-13 22:21
不错   顶!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 无与伦比的禽兽    时间: 2015-7-14 22:24
不错呀!真心不过呀!
作者: 星痕-凌    时间: 2015-7-17 21:25
不错 、顶!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 老中医    时间: 2015-7-17 22:13
我能和阳哥交个朋友吗?
作者: yangshibai    时间: 2015-9-21 23:25
最近正在学,好赞。。
作者: 宋美涛    时间: 2015-9-21 23:28
不错不错不错不错不错
作者: xuxu5112    时间: 2015-9-21 23:43
正好学到IO 学习下
作者: 1975532882    时间: 2015-10-27 08:59
好。。。。。。。。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2