黑马程序员 Java基础<十>---> IO流<2>(File类,Properties,打印流,合并流)

时间:2023-02-16 13:02:51

-----------android培训java培训、java学习型技术博客、期待与您交流! ------------


第一节   File类

一、概述:

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

2、特点:

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

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

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

二、创建File对象:

方式一:File f1 = new File("a.txt");

      --->   将a.txt封装成对象,可将已有的和未出现的文件或文件夹封装成对象

方式二:File f2 = new File("c:\\abc","b.txt");

      --->   分别指定文件夹和文件。好处:降低了两者的关联程度,

方式三:File d = new File("c:\\abc");     File f3 = new File(d,"c.txt");

      --->   可以传入父目录和文件名。

目录分隔符:调用File.separator,相当于是反斜杠 \


三、File类常见方法:

1、创建:

          boolean createNewFile()

--->   在指定位置创建文件,若文件存在,则返回true,与输出流不同,输出流对象已建立就创建文件,如果存在,就会被覆盖 

          boolean mkdir()

--->   创建文件夹,只能创建一级目录

          boolean mkdirs()

--->   创建多级文件夹。

2、删除:

       boolean delete()   

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

       void deleteOnExit() 

---> 在程序结束时删除文件

3、判断:

       boolean canExecute()   

---> 当前文件是否能被执行

       boolean exists()

--->  当前文件是否存在

       boolean isFile()       

---> 当前文件是否是文件

       boolean isDirectory()  

---> 当前文件是否是文件夹(目录);注意:在判断文件对象是否是文件或目录是们必须要判断该文件对象封装的内容是否存在,通过exists判断

       boolean isHidden()     

---> 当前文件是否是隐藏文件

       boolean isAbsolute()   

---> 测试此抽象路径名是否为绝对路径名

4、获取信息:

       String getName()     

---> 获取文件名

       String getPath()     

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

       String getParent()   

---> 获取父目录,该方法返回绝对路径中的父目录,获取相对路径,返回null, 如果相对路径中有上一级目录,则返回的即为该目录

       String getAbsolutePath()  

---> 获取绝对路径

       long length()             

---> 返回文件的大小

       long lastModified()       

---> 返回上次修改的时间

       static File[] listRoots() 

---> 获取文件的系统根,即各个盘符

       String[] list()           

---> 列出当前目录所有文件,包含隐藏文件。注:调用了list方法的file对象,必须是封装了一个目录,且该目录必须存在。

       boolean renameTo(File dest)

---> 对文件重命名为dest

5、列出及过滤文件:

       String[] list()

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

       File[] list(FilenameFilter filter)

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

       File[] listFiles()

---> 获取当前文件夹下的文件和文件夹,返回类型为File数组

       ListFiles(FilenameFilter filter)

---> 同list,是对获取的 当前文件夹下的文件和文件夹的 文件名过滤器。


示例:

import java.io.*;
class FileMethod
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args) throws IOException
{

//methodCreate();
//methodDel();
methodList();
}
public static void methodCreate()throws IOException
{
File f = new File("file.txt");
boolean b = f.createNewFile();
sop("create:" + b);
File dir = new File("abc");
File dir2 = new File("ab.txt");
b = dir2.mkdir();
sop("mkdir2:" + b);
b = dir.mkdir();
sop("midir:" + b);
File dirs = new File("abc\\aa\\bb\\cc");
b = dirs.mkdirs();
sop("mkdirs:" + b);
}
public static void methodDel()throws IOException
{
File f = new File("file.txt");
boolean b = f.delete();
sop("delete:" + b);
File f2 = new File("Demo.txt");
f2.createNewFile();
f2.deleteOnExit();//为避免由于在执行后面的程序发生异常,这里如果创建了一个临时文件,需要在程序结束时删除。
}

public static void methodList()throws IOException
{
File f = new File("D:\\File");
String[] arr = f.list(new FilenameFilter(){
public boolean accept(File dir,String name)
{
return name.endsWith(".bmp");
}
});
sop("len:" + arr.length);
for(String name : arr)
{
sop("bmp文件为:" + name);
}
}
}

四、递归:

对于每次循环都是用同一个功能的函数,即函数自身调用自身,这种表现形式或手法,称为递归。

注意:

1、限定条件,是作为结束循环用的,否则是死循环

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

举例一:

列出指定目录下文件或文件夹,包含子目录,即列出指定目录下所有内容

分析,因为目录中还有目录,只有使用同一个列出目录功能的函数完成即可,在列出过程中出现的还是目录的话,还可以再调用本功能,这就是利用递归原理。

import java.io.*;
class FileBack
{
public static void main(String[] args)
{
File f = new File("D:\\File\\f");
backShowName(f);
}
//获取文件及文件夹名
public static void backShowName(File dir)
{
//每次调用前,打印目录名
System.out.println(dir.getName());
//将文件存入File数组
File[] files = dir.listFiles();
for(int i=0; i<files.length;i++)
{
//如果是文件夹,调用自身
if(files[i].isDirectory())
backShowName(files[i]);
else
System.out.println(files[i].getName());
}
}
}

举例二:

删除一个带内容的目录:

删除原理:在window中,删除目录是从里往外删除的,同样使用递归

import java.io.*;
class FileBack
{
public static void main(String[] args)
{
File f = new File("D:\\File\\f");
removeDirs(f);
}
//删除文件夹所有内容
public static void removeDirs(File f)
{
//将文件存入File数组
File[] files = f.listFiles();
for (int i=0;i<files.length;i++)
{
//如果是文件夹,调用自身
if(files[i].isDirectory())
removeDirs(files[i]);
else
System.out.println(files[i].getName() + ":files:" + files[i].delete());
}
System.out.println(f.getName() + ":-dir-:" + f.delete());
}
}

举例三:

将一指定目录中的java文件的绝对路径,存到一个文本文件中,建立一个java文件列表文件

思路:

1、对指定目录进行递归

2、获取递归过程所有的java文件的路径

3、将这些路径存储到集合中

4、将集合中的数据写到一个文件中

import java.util.*;
import java.io.*;
class WriterToFiles
{
public static void main(String[] args)
{
File f = new File("D:\\JAVA");
List<File> list = new ArrayList<File>();
File dir = new File(f,"javalist.txt");
filesToList(f,list);
writeToFile(list,dir.toString());

}
//对指定目录进行递归
public static void filesToList(File f,List<File> list)
{
File[] files = f.listFiles();
for (int i=0;i<files.length;i++)
{
//如果是文件夹,再调用自身
if(files[i].isDirectory())
filesToList(files[i],list);
else
{
//获取递归过程所有的java文件的路径
if(files[i].getName().endsWith(".java"))
//将这些路径存储到集合中
list.add(files[i]);
}
}
}
//将集合中的数据写到一个文件中
public static void writeToFile(List<File> list,String javaListFile)
{
BufferedWriter bufw = null;
try
{
bufw = new BufferedWriter(new FileWriter(javaListFile));
//遍历集合,获取文件路径,并写入文件中
for(File f : list)
{
String path = f.getAbsolutePath();
bufw.write(path);
bufw.newLine();
bufw.flush();
}
}
catch (IOException e)
{
throw new RuntimeException("文件路径获取失败");
}
//最终关闭写入流资源
finally
{
try
{
if(bufw!=null)
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("文件路径获取失败");
}
}
}
}

第二节   Properties 类

一、概述:

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

2、特点:

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

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

二、特有方法:

1、设置和获取元素:

Object setProperty(String key,String value)

--->   调用Hashtable的方法put

String getProperty(String key)

--->   指定key搜索value

Set<String> stringPropertyName()

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

void load(InputStream ism)

--->   从输入字符流中读取属性列表

void load(Reader reader)

--->   从输入字符流中读取属性列表

load方法举例:

//load方法
public static void loadMthod()throws IOException
{
Properties pop =new Properties();
FileInputStream fis = new FileInputStream("info.txt");
//将流中的数据加载进集合
pop.load(fis);

pop.setProperty("zz","25");
pop.setProperty("ww","24");
FileOutputStream fos = new FileOutputStream("info.txt");
pop.store(fos,"hehe");
pop.list(System.out);
fis.close();
fos.close();

}

举例:

如何将六种的数据存储到集合中?

将文本文件中的键值数据存到集合中:

1、用一个流和文件关联

2、读取一行数据,将改行数据用“=”切割

3、将等号左边作为键,右边作为值,存入到Properties集合即可

//将流中的数据存储到集合中
public static void method()throws IOException
{
BufferedReader bufr = null;
try
{
Properties pop = new Properties();
bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
while((line=bufr.readLine())!=null)
{
String[] arr = line.split("=");
pop.setProperty(arr[0],arr[1]);
}
System.out.println(pop);
}
catch (IOException e)
{
throw new RuntimeException("文件操作失败");
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("关闭流资源操作失败");
}
}
}

示例:用于记录应用程序运行次数

如果使用次数已到,那么给出注册提示需要使用计数器,但是在程序结束后,会在内存中消失,此时就需要将其存入到文件中,所以需要一个配置文件,用于记录该软件使用的次数。便于阅读和操作数据

键值对数据 --->   Map集合;数据以文件形式存储 --->   IO技术。 --->Map+IO=Properties

import java.util.*;
import java.io.*;
class RunCount
{
public static void main(String [] args)throws IOException
{
//创建一个Properties对象,集合和io的结合
Properties pop = new Properties();
//创建一个文件对象,用于操作文件
File file = new File("count.ini");
//先判断文件是否存在,如果不存在就创建一个
if(!file.exists())
file.createNewFile();

//创建读取流对象,读取文件中的信息
FileInputStream fis = new FileInputStream(file);
//将流中的文件信息存入集合中
pop.load(fis);

//定义计数器
int count = 0;
//获取文件中键所对应的值
String value = pop.getProperty("time");
//判断值是否为null,不为空就将值传给计数器
if(value!=null)
{
count = Integer.parseInt(value);
//判断计数器是否为到达次数
if(count>=5)
{
System.out.println("次数已到,请注册");
return ;
}
}
count++;
//将获得的键值设置后存入集合中
pop.setProperty("time",count+"");
FileOutputStream fos = new FileOutputStream(file);
pop.store(fos,"");
fos.close();
fis.close();
}
}

第三节  打印流

一、概述:

1、打印流包括:PrintStream和PrintWriter

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

二、字节打印流:PrintStream

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

1、file对象。File

2、字符串路径:String

3、字符输出流:OutputStream

三、字符串打印流:PrintWriter

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

1、file对象:File

2、字符串路径:String

3、字节输出流:OutputStream

4、字符输出流:Writer

举例:

import java.io.*;

class PrintDemo
{
public static void main(String[] args) throws IOException
{
//键盘录入,创建读取流对象
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//使用打印流,将文件输出
//输出到屏幕
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
bufr.close();
out.close();
}
}

第四节  合并流

一、概述:

1、SequenceInputStream可以将多个流连接成一个源

2、构造函数:

1)SequenceInputStream(Enumeration<? extends FileInputStream> e)

二、如何合并多个文件:

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

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

3、创建SequenceInputStream对象,合并流对象

4、创建写入流对象,FileOutputStream,将数据写入流资源

5、定义数组,将读取流数据存入数组,并将数组中元素写入文件中。

举例:

假设有三个文件,将三者合并到一个新文件中

//合并流对象
public static void sequenceFile()throws IOException
{
FileOutputStream fos = null;
SequenceInputStream sis = null;
try
{
//创建集合,存储多个文件
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int i=1;i<=3;i++)
{
al.add(new FileInputStream(i+".part"));
}
//匿名内部类访问局部变量要final
final Iterator<FileInputStream> it = al.iterator();
//创建Enumeration匿名对象
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
//合并流对象,将集合元素加入。
sis = new SequenceInputStream(en);
//创建写入流对象,FileOutputStream
fos = new FileOutputStream("7.bmp");
byte[] b = new byte[1024*1024];
int len = 0;
//循环,将数据写入流资源
while((len=sis.read(b))!=-1)
{
fos.write(b);
}

}
catch (IOException e)
{
throw new RuntimeException("文件操作失败");
}
//关闭流资源
finally
{
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("关闭流资源操作失败");
}
try
{
if(sis!=null)
sis.close();
}
catch (IOException e)
{
throw new RuntimeException("关闭流资源操作失败");
}
}
}

三、切割流资源:

1、先关联文件FileInputStream

2、定义写入流变量:FileOutputStream

3、创建数组,并定义切割所需的大小|

4、循环读写数据,并每次创建一个新写入流,创建完后并写入文件中

5、关闭流资源

//切割流对象
public static void splitFile()throws IOException
{
//创建全局变量
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
//创建文件读取流
fis = new FileInputStream("0.bmp");
//创建数组
byte[] b = new byte[1024*1024];
int len = 0;
//计数器
int count = 1;
//循环写入数据
while((len=fis.read(b))!=-1)
{
//每次创建一个新写入流,写入后关闭流资源
fos = new FileOutputStream((count++)+".part");
fos.write(b,0,len);
fos.close();
}
}
catch (IOException e)
{
throw new RuntimeException("关闭流资源操作失败");
}
//关闭流资源
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("关闭流资源操作失败");
}
}

}
}