Java基础---IO(二)--File类、Properties类、打印流、序列流(合并流)

时间:2023-03-09 01:54:20
Java基础---IO(二)--File类、Properties类、打印流、序列流(合并流)

第一讲     File类

一、概述

1、File类:文件和目录路径名的抽象表现形式

2、特点:

1)用来将文件或文件夹封装成对象

2)方便于对文件与文件夹的属性信息进行操作

3)File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变

4)File对象可以作为参数传递给流的构造函数

二、File对象创建

方式一:

File f =new File("a.txt");

将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。

方式二:

File f2=newFile("c:\\abc","b.txt");

将文件所在目录路径和文件一起传入,指定文件路径。

方式三:

File d=new File("c:\\abc");

File f3=new File(d,"c.txt");

将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。

小知识:

File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。

三、File类的常见方法

1、创建

booleancreateNewFile();

//在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立就创建文件。而且文件已经存在,会覆盖。

boolean mkdir();//创建文件夹,只能创建一级文件夹

例:

File dir=new File("abc");

dir.mkdir();//创建abc这个文件夹

boolean mkdirs();//创建多级文件夹

2、删除

boolean delete();

//删除文件或目录。文件存在,返回true;文件不存在或者正在被执行,返回false。

void deleteOnExit();//在程序退出时删除指定文件

3、判断

boolean canExecute();//是否是可执行文件

boolean exists();//文件是否存在

boolean isFile();//是否是文件

boolean isDirectory();//是否是文件夹

boolean isHidden();//是否是隐藏文件

boolean isAbsolute();//文件是否是绝对路径

记住:在判断文件对象是否是文件或者目录时,必须要判断该文件对象封装的内容是否存在。通过exists判断。

4、获取信息

String getName();//获取文件名

String getPath();

//获取文件的相对路径(即创建的对象传入的参数是什么就获取到什么)

String getParent();

//获取文件父目录。返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

String getAbsolutePath();//获取文件的绝对路径

long lastModified();//返回文件最后一次被修改的时间

long length();//返回文件长度

5、列出文件及文件过滤

static File[] listRoots();//列出可用的文件系统根目录,即系统盘符

String[] list();

//列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。

String[]list(FilenameFilter filter);

//返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。

//FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法,accept(Filedir,String name),返回的是boolean型,对不符合条件的文件过滤掉。

File[] listFiles();//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹

File[] ListFiles(FilenameFilterfilter);//返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。

  1. <span style="font-size:14px;">/*
  2. 练习:用String[] list(FilenameFilter filter)方法获取一个目录下所有的.java文件,其他文件不要。
  3. 思路:1、FilenameFilter是一个过滤器接口,用匿名内部类传入filter对象
  4. 2、复写FilenameFilter接口的accept(File file,String name)方法,并判断name是否是java文件
  5. 3、遍历String类型数组
  6. */
  7. import java.io.*;
  8. class  GetJavaFile
  9. {
  10. public static void main(String[] args)
  11. {
  12. File file=new File("E:\\Java Study\\Practice\\day07");
  13. getJavaFile(file);
  14. }
  15. //获取一个目录下所有的.java文件方法
  16. public static void getJavaFile(File dir)
  17. {
  18. //传入FilenameFilter匿名内部类子类对象,并复写accept方法
  19. String[] javaFile=dir.list(new FilenameFilter()
  20. {
  21. public boolean accept(File dir,String name)
  22. {
  23. return name.endsWith(".java");//判断文件名是否是以.java结尾
  24. }
  25. });
  26. System.out.println("len:"+javaFile.length);
  27. //遍历数组
  28. for (String s : javaFile )
  29. {
  30. System.out.println(s);
  31. }
  32. }
  33. }
  34. </span>

四、递归

1、定义

当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。这种表现形式,或者编程手法,称为递归。

2、递归注意事项

a、限定条件。是来结束循环调用,否则是死循环。

b、注意递归的次数,尽量避免内存溢出。因为每次调用自身的时候都会先执行下一次调用自己的方法,所以会不断在栈内存中开辟新空间,次数过多,会导致内存溢出。

示例一

  1. /*
  2. 需求:列出指定目录下文件或文件夹,包含子目录,即列出指定目录下所有内容(带层次的)。
  3. 分析,因为目录中还有目录,只有使用同一个列出目录功能的函数完成即可,在列出过程中出现的还是目录的话,还可以再调用本功能,这就是利用递归原理。
  4. */
  5. import java.io.*;
  6. class  RecursionDemo
  7. {
  8. public static void main(String[] args)
  9. {
  10. //关联指定路径
  11. File dir=new File("e:\\Java Study\\Practice");
  12. //列出关联路径中所有的.java文件
  13. allFileList(dir,0);
  14. }
  15. //列出指定目录下的所以内容
  16. public static void allFileList(File dir,int level)
  17. {
  18. //有层次的输出
  19. System.out.println(getLevel(level)+dir);
  20. level++;
  21. File[] fileArr=dir.listFiles();//获取本目录下的所以文件和目录的抽象路径
  22. //遍历
  23. for (File file : fileArr)
  24. {
  25. if(file.isDirectory())
  26. {
  27. //如果目录下还是目录,则继续调用本函数
  28. allFileList(file,level);
  29. }
  30. else
  31. System.out.println(getLevel(level)+file);//显示(列出)文件
  32. }
  33. }
  34. //带层次的列表
  35. public static String getLevel(int level)
  36. {
  37. StringBuilder sb=new StringBuilder();
  38. sb.append("|--");
  39. //每多一级目录,就多输出指定字符
  40. for (int x=level;x>0 ; x--)
  41. {
  42. //sb.append("|--");
  43. sb.insert(0,"|  ");
  44. }
  45. return sb.toString();
  46. }
  47. }

示例二

  1. /*
  2. 删除一个带内容的目录。
  3. 删除原理:
  4. 在windows中,删除目录从里面往外面删除的。
  5. 既然是从里往外删除。就需要用到递归。
  6. */
  7. import java.io.*;
  8. class RemoveDir
  9. {
  10. public static void main(String[] args)
  11. {
  12. //指定目录
  13. File dir=new File("e:\\1");
  14. //删除目录
  15. removeDir(dir);
  16. }
  17. //删除传入目录
  18. public static void removeDir(File dir)
  19. {
  20. File[] files=dir.listFiles();//列出目录下的所以文件和文件夹
  21. //遍历
  22. for (File file : files )
  23. {
  24. //如果还是目录且非隐藏
  25. if(!file.isHidden()&&file.isDirectory())
  26. removeDir(file);//继续删除目录里的内容
  27. else
  28. System.out.println(file.toString()+":-file-:"+file.delete());//删除文件
  29. }
  30. System.out.println(dir+":::dir:::"+dir.delete());//删除目录
  31. }
  32. }

示例三

  1. /*
  2. 练习:
  3. 将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表的文件。
  4. 思路:
  5. 1、对指定的目录进行递归。
  6. 2、获取递归过程所有的java文件的路径。
  7. 3、将这些路径存储到集合中。
  8. 4、将集合中的数据写入到一个文件中。
  9. */
  10. import java.util.*;
  11. import java.io.*;
  12. class  JavaFileList
  13. {
  14. public static void main(String[] args)
  15. {
  16. //指定目录
  17. File dir=new File("e:/Java Study/Practice");
  18. //定义一个List集合,用于存储.java文件的File对象
  19. List<File> list =new ArrayList<File>();
  20. //调用获取文件路径方法
  21. fileToList(dir,list);
  22. //指定写入文件
  23. File file=new File(dir,"javafilelist.txt");
  24. //调用写入文件方法
  25. writeToFile(list,file);
  26. }
  27. //获取指定文件夹内的所有java文件的绝对路径,并存入集合中
  28. public static void fileToList(File dir,List<File> list)
  29. {
  30. File[] files=dir.listFiles();//列出dir路径下的所以文件和目录,
  31. //遍历
  32. for (File file : files)
  33. {
  34. //如果是目录,则继续获取
  35. if(file.isDirectory())
  36. {
  37. list.add(file.getAbsoluteFile());//把父目录路径也存入
  38. fileToList(file,list);
  39. }
  40. //将是.java文件的绝对路径存入
  41. else if(file.getName().endsWith(".java"))
  42. list.add(file);
  43. }
  44. }
  45. //将集合中元素写入到一个文本文件中
  46. public static void writeToFile(List<File> list,File file)
  47. {
  48. BufferedWriter bw=null;
  49. try
  50. {   //使用字符流缓冲区对象关联写入的文件
  51. bw=new BufferedWriter(new FileWriter(file));
  52. for (File file0 : list )
  53. {
  54. bw.write(file0.getAbsolutePath());//写入
  55. bw.newLine();//换行
  56. bw.flush();//刷新
  57. }
  58. }
  59. catch (IOException e)
  60. {
  61. throw new RuntimeException("写入文件失败");
  62. }
  63. finally
  64. {
  65. try
  66. {
  67. if(bw!=null)
  68. bw.close();//关流
  69. }
  70. catch (IOException e)
  71. {
  72. throw new RuntimeException("流资源关闭失败");
  73. }
  74. }
  75. }
  76. }

第二讲      Properties类

一、概述

1、Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。

2、特点:

1)可用于键值对形式的配置文件

2)在加载时,需要数据有固定的格式,常用的是:键=值

二、特有方法

1、设置

Object setProperty(String key,String value);

//设置键和值,调用Hashtable的方法put

2、获取

String getProperty(String key);

//指定key搜索value

Set<String> stringPropertyName();

//返回属性列表的键集,存入Set集合

3、加载流和存入流

void load(InputStream ism);

//从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

void load(Readerreader);

//从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

voidlist(PrintStream out);//将属性列表输出到指定的输出流

void store(OutputStreamout,String comments);

//对应load(InputStream )将属性列表(键值对)写入输出流。comments属性列表的描述。

void store(Writerwriter, String comments);

//对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。

示例

  1. //演示,如何将流中的数据存储到集合中。
  2. //想要将info.txt中键值数据存到集合中进行操作。
  3. /*
  4. 1,用一个流和info.txt文件关联。
  5. 2,读取一行数据,将该行数据用"="进行切割。
  6. 3,等号左边作为键,右边作为值。存入到Properties集合中即可。
  7. */
  8. //将文件数据存储进Properties集合方法
  9. public static void method()throws IOException
  10. {
  11. //使用字符读取缓冲流关联文件
  12. BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
  13. String line = null;
  14. //定义Properties集合
  15. Properties prop = new Properties();
  16. while((line=bufr.readLine())!=null)
  17. {
  18. String[] arr = line.split("=");//将一行数据以“=”号进行分割
  19. //将=左边作为键存入,将=右边作为值存入
  20. prop.setProperty(arr[0],arr[1]);
  21. }
  22. bufr.close();//关流
  23. System.out.println(prop);
  24. }

练习:

  1. /*
  2. 练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。
  3. 分析:
  4. 很容易想到的是:计数器。可是该计数器定义在程序中,随着该应用程序的退出,该计数器也在内存中消失了。
  5. 所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。键值对数据是map集合。数据是以文件形式存储。使用io技术。那么map+io——>Properties。
  6. 思路:1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建
  7. 2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。
  8. 3、将值小于等于5次的信息数据存入文件中伤感的句子
  9. */
  10. import java.util.*;
  11. import java.io.*;
  12. class  RunCount
  13. {
  14. public static void main(String[] args)throws IOException
  15. {
  16. int count=runCount();
  17. if(count>5)//如果程序被使用了超过5次,则终止使用,并提示
  18. {
  19. System.out.println("次数到了,交钱!!!!!");
  20. return ;
  21. }
  22. else
  23. System.out.println("程序第"+count+"次Run!");
  24. }
  25. //获取程序运行的次数
  26. public static int runCount()throws IOException
  27. {
  28. Properties ps=new Properties();//创建集合对象
  29. File file=new File("info.ini");//将文件进行封装
  30. if(!file.exists())//判断是否存在
  31. file.createNewFile();
  32. FileReader fr=new FileReader(file);//将文件于读取流进行关联
  33. ps.load(fr);//加载流中的文件数据到集合中
  34. int count=0;//定义计数器
  35. String value=ps.getProperty("time");//获取次数值
  36. if(value!=null)//如过值不等于null,则将其赋值给count
  37. {
  38. count=Integer.parseInt(value);
  39. }
  40. count++;//每启动一次自增
  41. ps.setProperty("time",count+"");//将次数记录住集合
  42. FileWriter fw=new FileWriter(file);
  43. ps.store(fw,"");//将集合中的数据存入硬盘文件中
  44. fr.close();//关流
  45. fw.close();
  46. return count;//返回程序启动的次数
  47. }
  48. }

第三讲    打印流

一、概述

1、打印流包括:PrintStream和PrintWriter

2、该流提供了打印方法,可将各种类型的数据都原样打印。

二、字节打印流:PrintStream

构造方法中可接收的参数类型:

1、File对象。File

2、字符串路径:String

3、字符输出流:OutputStream

三、字符串打印流:PrintWriter

构造方法中可接受的参数类型

1、File对象:File

2、字符串路径:String

3、字节输出流:OutputStream

4、字符输出流:Writer

示例

  1. import java.io.*;
  2. class  PrintStreamDemo
  3. {
  4. public static void main(String[] args) throws IOException
  5. {
  6. //键盘录入
  7. BufferedReader bufr =
  8. new BufferedReader(new InputStreamReader(System.in));
  9. //打印流关联文件,自动刷新
  10. PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);
  11. String line = null;
  12. while((line=bufr.readLine())!=null)
  13. {
  14. if("over".equals(line))//结束字符
  15. break;
  16. out.println(line.toUpperCase());
  17. //out.flush();
  18. }
  19. //关流
  20. out.close();
  21. bufr.close();
  22. }
  23. }

第四讲    序列流

一、概述

1、SequenceInputStream对多个流进行合并。也被称为合并流。

2、常用构造函数

SequenceInputStream(Enumeration<?extends FileInputStream> e)

二、常见合并多个流文件步骤

1、创建集合,并将流对象添加进集合

2、创建Enumeration对象,将集合元素加入。

3、创建SequenceInputStream对象,合并流对象淘宝开店

4、创建写入流对象,FileOutputStream关联写入文件

5、利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。

示例:

  1. /*
  2. SequenceInputStream
  3. 合并流
  4. 需求:将三个文本文件中的数据合并到一个文本文件中
  5. 思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中
  6. 2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration
  7. 3、输出流关联新文本文件
  8. 4、反复读写操作
  9. */
  10. import java.util.*;
  11. import java.io.*;
  12. class  SequenceInputStreamDemo
  13. {
  14. public static void main(String[] args)throws IOException
  15. {
  16. Vector<InputStream> ve=new Vector<InputStream>();//创建vector集合,并添加相关流对象
  17. ve.add(new FileInputStream("1.txt"));
  18. ve.add(new FileInputStream("2.txt"));
  19. ve.add(new FileInputStream("3.txt"));
  20. Enumeration<InputStream> en=ve.elements();//创建枚举对象
  21. SequenceInputStream sis=new SequenceInputStream(en);//合并流
  22. FileOutputStream fos=new FileOutputStream("4.txt");//关联写入文件
  23. //反复读写操作
  24. byte[] buf=new byte[1024];
  25. int len=0;
  26. while((len=sis.read(buf))!=-1)
  27. {
  28. fos.write(buf,0,len);
  29. }
  30. //关流
  31. fos.close();
  32. sis.close();
  33. }
  34. }

练习:

    1. /*
    2. 切割文件
    3. 需求:将一个mp3文件按1M大小切割成几部分
    4. 思路:1、使用文件字节流关联mp3文件
    5. 2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中
    6. */
    7. import java.util.*;
    8. import java.io.*;
    9. class  SplitFile
    10. {
    11. public static void main(String[] args) throws IOException
    12. {
    13. //指定要切割的文件
    14. File file=new File("C:\\Users\\asus\\Desktop\\苏芮 - 一样的月光.mp3");
    15. //将指定文件进行切割
    16. splitFile(file);
    17. //指定要合并到的文件
    18. File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\一样的月光.mp3");
    19. //将部分文件进行合并指定文件中
    20. merge(file1);
    21. }
    22. //接收一个文件,将其按1M大小进行切割
    23. public static void splitFile(File file)throws IOException
    24. {
    25. //关联要切割的文件
    26. BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
    27. BufferedOutputStream bos=null;
    28. //定义1M大小存储容器
    29. byte[] buf=new byte[1024*1024];
    30. int len=0,x=0;
    31. while ((len=bis.read(buf))!=-1)
    32. {
    33. //每满1M就写入一个新文件中
    34. bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));
    35. bos.write(buf,0,len);
    36. bos.close();//没写完一个文件要记得关流
    37. }
    38. //关流
    39. bis.close();
    40. }
    41. //将部分文件合并为一个可执行文件
    42. public static void merge(File file)throws IOException
    43. {
    44. //定义一个集合存储这些部分文件关联路径数据
    45. ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
    46. for (int x=1;x<=6 ; x++)
    47. {
    48. al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));
    49. }
    50. //因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类
    51. final  ListIterator<FileInputStream> it=al.listIterator();
    52. Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
    53. {
    54. public boolean hasMoreElements()
    55. {
    56. return it.hasNext();
    57. }
    58. public FileInputStream nextElement()
    59. {
    60. return it.next();
    61. }
    62. };
    63. //关联枚举对象
    64. SequenceInputStream sis=new SequenceInputStream(en);
    65. //将合并的文件数据写入指定文件中
    66. FileOutputStream fos=new FileOutputStream(file);
    67. //定义临时存储数据的数组
    68. byte[] buf=new byte[1024];
    69. int len=0;
    70. while((len=sis.read(buf))!=-1)
    71. {
    72. fos.write(buf,0,len);//写数据
    73. }
    74. //关流
    75. fos.close();
    76. sis.close();
    77. }
    78. }