------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员————Java基础日常笔记---IO流二
1.1 File类由来
通过IO流一可以明白,流只能操作数据,但是不能操作文件。
而要想操作文件, 具体操作的就是文件的长度,名称,什么的,这些都是复杂的事情,因此需要用一个类来表示;
File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。
这样就弥补了流的不足,流只能操作数据,如果想要操作被数据封装的文件信息, 必须用file对象
File对象可以作为参数传递给流的构造函数。
代码如下:
/*
File类的构造方法:
1,最常见的:
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
2,File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
3,File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
*/
import java.io.*;
class FileDemo
{
public static void main(String[] args) throws IOException
{
consMethod();
}
public static void consMethod(){
//将a.txt封装成File对象,可以将已有的和未出现的文件或文件夹封装成对象,
File f1=new File("E:\\abc\\a.txt");//最常见的
File f2=new File("E:\\abc","a.txt");
//File f2=new File("E:\\abc",str);//想操作的目录不变, 但是想操作目录下的文件是可以的,
File d=new File("E:\\abc");
File f3=new File(d,"a.txt");
File f4=new File("E:"+File.separator+"abc"+File.separator+"a.txt");//跨平台性好
sop("f1="+f1);
sop("f2="+f2);
sop("f3="+f3);
sop("f4="+f4);
}
public static void sop(Object obj){
System.out.println(obj);
}
}
结果:
1.2 File类的方法
1.2.1 创建:
代码如下:
/*结果:
1,创建:
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false
和输出流不同,输出流对象已建立创建文件,而且文件以及已经存在,会覆盖
boolean createTempFile();创建临时文件
boolean mkdir():可以创建文件夹的方法,mkdir只能创建一级目录,
boolean mkdirs();可以创建多级目录
*/
import java.io.*;
class CreateFileDemoCreateFileDemo
{
public static void main(String[] args) throws Exception
{
File f=new File("E:\\文件一");
sop("创建文件是否成功?"+f.createNewFile());
//File f1=new File("E:\\文件夹\\文件一");
//sop("创建文件是否成功?"+f1.createNewFile());//找不到文件路径,如何改进呢?
File f2=new File("E:\\文件夹");
sop("创建文件夹是否成功"+f2.mkdir());
File f3=new File(f2,"文件二");
sop("在文件夹中创建文件是否成功?"+f3.createNewFile());
}
public static void sop(Object obj){
System.out.println(obj);
}
}
改进后:
1.2.2 删除
代码如下:
/*2,删除:结果:
boolean delete();删除当前对象的文件,
但是如果这个代码发生异常, 发生跳转, 那么删除就不读到,
还想删:如果放到finally中, 可能删不了,
就是一个文件在流操作, 会删不了的,
告诉JVM,在退出的时候, 删了,
void deleteOnExit();表示程序退出时删除指定文件,
*/
import java.io.*;
class DeleteFileDemo
{
public static void main(String[] args)throws Exception
{
File f=new File("E:\\文件一.txt");
System.out.println("删除文件是否成功呢?"+f.delete());
File f1=new File("E:\\文件夹\\文件二.txt");
System.out.println("删除文件是否成功呢?"+f1.delete());
}
}
总结:不管是多级目录还是文件,都可以I把最里面的文件给删除。
1.2.3 判断
代码如下;
/*结果:
3,判断
boolean canExecute();当前文件是否可执行,只有当当前文件存在时,可以执行,
这个文件可以执行, 可以挂上Runtime的对象,
就可以把这个文件中的所有文件都可以打开,
boolean canRead();是否可读
boolean canWrite();是否可写
int compareTo(File pathname):文件名可以比较大小, 按照容量, 可以自定义比较器,
boolean exists():文件是否存在,使用频率高,
流对象, 只有文件存在, 才可以去读取,
记住在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在
通过exists()来判断;
boolean isDirectory():判断是否是目录;
boolean isFile:判断是否是文件;
注意:不要直观的认为, 带着点的都是文件,也可以是文件夹,
boolean isHidden();判断是否该文件或目录被隐藏
boolean isAbsolute():所在的路径是否是绝对的,即使这个文件不存在,也可以判断,
boolean renameTo(File dest):将当前文件或目录重新命名为指定的文件或目录,
类似于移动, 剪切,
*/
import java.io.*;
class JudgeFileDemo
{
public static void main(String[] args) throws Exception
{
File f=new File("E:\\a.txt");
sop("创建文件:"+f.createNewFile());
sop("...........................");
sop("判断该文件是否存在:"+f.exists());
sop("...........................");
sop("判断是否是文件:"+f.isFile());
sop("...........................");
sop("判断是否是目录:"+f.isDirectory());
sop("...........................");
sop("判断是否是隐藏文件:"+f.isHidden());
sop("...........................");
sop("判断所在的路径是否是绝对路径:"+f.isAbsolute());
sop("...................................");
File f1=new File("E:\\a修改后.txt");
sop("判断该文件是否存在:"+f1.exists());
sop("...................................");
sop("判断重命名是否成功"+f.renameTo(f1));
sop("...................................");
sop("判断该文件是否存在:"+f1.exists());
}
public static void sop(Object obj){
System.out.println(obj);
}
}
1.2.4 获取
代码如下:
/*结果:
4,获取信息
String getName();
****虽然这个文件是不存在的(或可以存在),但是他的路径可以获取到的,****
String getPath();文件是什么路径就返回什么,和getAbsolutePath()比较不同
getAbsolutePath():返回文件的绝对路径
String getParent();该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null,
如果相对路径中有上一层目录,那么该目录就是返回结果
File getAbsoluteFile();返回绝对路径,但是这个把返回的路径封装成了对象
String和File之间可以相互转换的,
|---new一下就可以变成File对象,
|---File.toString, 变成字符串
long lastModified();可以判断最后一次修改的时间,
比如操作一个文件, 那么这个文件被修改了, 时间记录,
而别人也可以修改这个文件, 那么可以用这个方法来判断是不是
我上次修改的时间, 如果是的话, 说明这个文件没有被修改,
如果时间不同, 说明这个文件被别人修改过(不是我,)
long length();获取文件的大小;字节读取流, 有个方法是available , 可以返回字节数,
可通过length来获取,
*/
import java.io.*;
class GetFileDemo
{
public static void main(String[] args) throws Exception
{
File f=new File("E:\\abc\\a.txt");
sop("........................");
sop("getName()获取文件名:"+f.getName());//存不存在这个文件,没有关系
sop("........................");
sop(" getPath()获取路径"+f.getPath());//文件是什么路径就返回什么
sop("........................");
sop("getAbsolutePath()获取文件的绝对路径"+f.getAbsolutePath());
}
public static void sop(Object obj){
System.out.println(obj);
}
}
1.2.5 文件列表
代码如下:
/*结果:
static File[] listRoots()
列出可用的文件系统根。
String[] list(): 返回的是指定目录下当前的文件以及文件夹的名称,
** 文件类所封装的这个文件下没有内容,不是目录, 返回数组为空, 就不可以被对象指向去遍历了,
所以调用list方法的file对象必须是封装了一个目录,而且该目录还必须存在
*/
import java.io.*;
class ListFileDemo
{
public static void main(String[] args) throws Exception
{
//列出可用的文件系统根。
getSystemRoots();
//获取E盘目录(必须存在)下的所有文件以及文件夹的名称(包括E盘中不可见的文件
getList();
}
public static void getSystemRoots(){
File[] files=File.listRoots();
sop("获取有效的文件系统根目录:");
for(File file:files){
sop(file);
}
}
public static void getList(){
File file=new File("E:\\");//封装的这个file对象必须封装的是一个目录,并且这个目录是存在的;
String[] fileNames=file.list();
sop("获取E盘目录(必须存在)下的所有文件以及文件夹的名称(包括E盘中不可见的文件):");
for(String fileName:fileNames){
sop(fileName);
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
这里可以得到全部的文件名称,但是想获取自己需要的一类文件呢?
代码:
/*结果:
希望获取到指定的目录下的指定文件名.
例如:
希望得到D:\java1\正则目录中的所有.java文件名称。
String[] list(FilenameFilter filter)
-->java.io
接口 FilenameFilter
-->boolean accept(File dir, String name)
*/
import java.io.*;
class FilenameFilterDemo
{
public static void main(String[] args) throws Exception
{
File dir=new File("D:\\java1\\正则");
String[] fileNames=dir.list();
sop("得到D:\\java1\\正则目录的所有文件名称:");
for(String fileName:fileNames){
sop(fileName);
}
//希望得到D:\java1\正则目录中的所有.java文件名称。
sop("得到D:\\java1\\正则目录的所有.java文件名称:");
String[] javaFileNames=dir.list(new FilenameFilter(){
public boolean accept(File dir,String name){
return name.endsWith(".java");//返回为真,得到想要的,判断
}
});
sop("javaFileNames的字符串数组的长度:"+javaFileNames.length);
/*
发现如果是true,那么就可以得到所有的,
如果是false,那么就一个都没有得到。
说明:如果是false,就过滤了,
如果是true,就是没有过滤的。
*/
for(String javaFileName:javaFileNames){
sop(javaFileName);
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
但是这里得到的只是文件名称,如果还想操作更多的,想获取该文件的长度, 就无法办到,
代码:
/*结果:
File[] listFiles():
可以返回文件的数组,可以对文件这个对象进行操作,
真实开发比较实用
*/
import java.io.*;
class listFilesDemo
{
public static void main(String[] args)
{
File dir=new File("D:\\java1\\正则");
//获取这个目录下的所有的文件,而非文件名称了(list)
sop("获取D:\\java1\\正则目录下的所有的文件,而非文件名称了(list)");
File[] dirArr=dir.listFiles();
for(File file:dirArr){
sop("文件名:"+file.getName()+"。。该文件大小:"+file.length());
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
列出目录下所有内容-递归
首先需要了解递归:函数自身调用自身
代码如下:
/*结果:
递归:
1,递归求和
2,递归求二进制:
*/
import java.io.*;
class recursionFileDemo
{
public static void main(String[] args)
{
sop("递归求和....."+getSum(6));
sop("递归求二进制:");
toBin(6);
}
public static void getAllFile(){
}
public
public static int getSum(int num){
if(num==1){
return 1;
}
return num+getSum(num-1);
}
public static void toBin(int num){
if(num>0){
toBin(num/2);
sop(num%2);
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
图例解释:
递归要注意:
1,限定条件
2,要注意递归的次数,尽量避免内存溢出。
需求:列出指定目录下文件或文件夹,包含子目录中的内容,也就是勒出指定目录下所有的内容。
定义一个用于遍历文件夹的功能,
当遍历文件夹的过程中,碰到了一个这里面还有文件夹的,这时需要到这个文件夹里边继续遍历,用的还是这个功能,
因此首先需要定义这样的一个功能----遍历文件。
这里需要用到listFiles(),因为需要判断当前目录下的是文件还是目录。
如果是目录,就需要在往这个子目录中去遍历。
代码:
/*结果:
//列出指定目录下文件或文件夹,包含子目录中的内容,也就是勒出指定目录下所有的内容。
*/
import java.io.*;
class listAllFilesByRecursion
{
public static void main(String[] args) throws Exception
{
File dir=new File("D:\\java1");
listAllFiles(dir);
}
public static void listAllFiles(File dir){
File[] dirArr=dir.listFiles();
for(int i=0;i<dirArr.length;i++){
if(dirArr[i].isDirectory()){
listAllFiles(dirArr[i]);
}
else
System.out.println(dirArr[i]);
}
}
}
如何让文件前面有层次呢?
代码如下:
/*结果:
列出目录中的所有的文件,带层次的。
遇到一个目录,就是一级。
*/
import java.io.*;
class listAllFilesDemo
{
public static void main(String[] args)
{
File file=new File("F:\\5 自学资料\\Java 1 笔记\\java进阶");
int level=0;
showDir(file,level);
}
public static String getLevel(int level){
StringBuilder sb=new StringBuilder();
sb.append("|--");
for(int i=0;i<level;i++){
//sb.append("|--");
sb.insert(0,"");
}
return sb.toString();
}
public static void showDir(File dir,int level){
System.out.println(getLevel(level)+dir.getName());
level++;
File[] files=dir.listFiles();
for(int i=0;i<files.length;i++){
if(files[i].isDirectory()){
showDir(files[i],level);
}
else
System.out.println(files[i]);
}
}
}
删除目录下的所有文件:
代码:
//删除一个目录
import java.io.*;
class removeAllFileDemo
{
public static void main(String[] args)
{
File file=new File("D:\\JAVA - 副本");
removeAllFiles(file);
}
public static void removeAllFiles(File dir){
File[] dirArr=dir.listFiles();
for(int i=0;i<dirArr.length;i++){
if(!dirArr[i].isHidden()&&dirArr[i].isDirectory()){
removeAllFiles(dirArr[i]);
}
else
System.out.println(dirArr[i]+"...."+dirArr[i].delete());
}
System.out.println(dir+"........"+dir.delete());
}
}
结果:
练习: 代码:
/*结果:
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,建立一个java文件列表文件。
思路:
1,对指定的目录进行递归
2,获取递归过程所有的java文件的路径
3,将这些路径存储到集合中
4,将集合中的数据写入到一个文件中。
想存到文件中,
数据的持久化,
操作集合的数据,
源:集合:
目的:绝对路径, 字符串, 文本的, FileWriter,
*/
import java.io.*;
import java.util.*;
class createAllFileList
{
public static void main(String[] args) throws Exception
{
File dir=new File("D:\\java1\\lianxi\\src");
List<File> list=new ArrayList<File>();
fileToList(dir,list);
System.out.println(list.size());
writeToFile(list,"E:\\javalist.txt");
}
public static void fileToList(File dir,List<File> list){
File[] dirArr=dir.listFiles();
for(File file:dirArr){
if(file.isDirectory()){
fileToList(file,list);
}
else{
if(file.getName().endsWith(".java")){
list.add(file);
}
}
}
}
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 e1)
{
System.out.println(e1);
}
}
}
}
2.1 类 Properties
HashTable集合的子类,
也就是说他具体map集合的特点,而且他里面存储的键值对都是字符串,
是集合中和IO技术相结合的集合容器。
该对象的特点,可以用于键值形式的配置文件。
将配置信息进行了持久化保存导致的, 存到文件
每一次打开的时候,内存都在加载这个文件,
获取这个信息需要先找文件, 而且要操作这个数据, 要用到IO流技术,
Properties对象由来, 不仅可以操作键值对, 而且可以操作硬盘上的键值对信息,
代码:
/*void load(InputStream inStream)结果:
从输入流中读取属性列表(键和元素对)。
void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
这样就可以从流中加载键值对的信息,
Set<String> stringPropertyNames()
返回此属性列表中的键集,其中该键及其对应值是字符串,
如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键
*/
import java.util.*;
import java.io.*;
class PropertiesDemo
{
public static void main(String[] args) //throws Exception
{
setAndGet();
}
public static void setAndGet(){
Properties prop=new Properties();
prop.setProperty("张三","30");
prop.setProperty("李四","40");
System.out.println(prop);//打印集合
String value=prop.getProperty("张三");
System.out.println("获取Properties对象的张三的值:"+value);
Set<String> names=prop.stringPropertyNames();
for(String name:names){
System.out.println(name+"通过stringPropertyNames()得到set集合的方法来获取对应的值"+prop.getProperty(name));
}
//修改键的值
prop.setProperty("李四",88+"");
System.out.println("修改后的集合:"+prop);//打印集合
}
}
但是Properties存储配置文件,
数据有可能不是设置进去的, 有可能数据已经存在了,
代码:
/*结果:
思路:
1,用一个流和info.txt文件关联
2,读取一行数据,将该行的数据用”=“进行切割
3,等号左边作为键,右边作为值,存入到Properties集合中即可
*/
import java.util.*;
import java.io.*;
class PropertiesDemo1
{
public static void main(String[] args) throws Exception
{
BufferedReader bufr=
new BufferedReader(new FileReader("F:\\5 自学资料\\Java 1 笔记\\java进阶\\5 IO流\\3 Properties\\info.txt"));
String line=null;
Properties prop=new Properties();
while((line=bufr.readLine())!=null){
//System.out.println(line);
String[] arr=line.split("=");
System.out.println(arr[0]+"....."+arr[1]);
prop.setProperty(arr[0],arr[1]);
}
System.out.println(prop);
bufr.close();
}
}
但是如果每次都这么做的话, 就比较麻烦, 因此在Properties类中提供了这样的方法,
load(InputStream inStream) ,这样的方法,以上就是load方法的原理,
代码:
/*结果:
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
*/
import java.util.*;
import java.io.*;
class PropertiesDemo2
{
public static void main(String[] args) throws Exception
{
Properties prop=new Properties();
FileReader fr=
new FileReader("F:\\5 自学资料\\Java 1 笔记\\java进阶\\5 IO流\\3 Properties\\info.txt");
//将流中的数据加载进集合中
prop.load(fr);
System.out.println(prop);
}
}
这样做, 就将读取流和Map集合联系起来,load()方法;
但是如果需要中途操作一些数据,并将这些操作后的数据保存起来,如何?
void list(PrintStream out)
将属性列表输出到指定的输出流。
void list(PrintWriter out)
将属性列表输出到指定的输出流。
可以添加代码:
prop.setProperty("李四",20+"");
prop.list(System.out);结果:
但是发现info.txt文件中的数据没有发生变化, 改变的只是内存中的结果,
如何?
代码:
/*
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
void list(PrintStream out)
将属性列表输出到指定的输出流。
void list(PrintWriter out)
将属性列表输出到指定的输出流。
void store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,
将此 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments)
以适合使用 load(Reader) 方法的格式,
将此 Properties 表中的属性列表(键和元素对)写入输出字符。
*/
import java.util.*;
import java.io.*;
class PropertiesDemo2
{
public static void main(String[] args) throws Exception
{
Properties prop=new Properties();
FileReader fr=
new FileReader("F:\\5 自学资料\\Java 1 笔记\\java进阶\\5 IO流\\3 Properties\\info.txt");
//将流中的数据加载进集合中
prop.load(fr);
System.out.println(prop);
prop.setProperty("李四",20+"");//对集合中数据进行更改
FileWriter fw=
new FileWriter("F:\\5 自学资料\\Java 1 笔记\\java进阶\\5 IO流\\3 Properties\\info.txt");
prop.list(System.out);
prop.store(fw,"hello");//hello为注释信息,
fr.close();
fw.close();
}
}
结果:
这样就ok了。
练习:
/*结果:
需求:
用于记录应用程序运行次数
如果使用次数已到,那么给出注册提示;像共享软件
思路:
首先很容易想到的是:计数器
可以该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可以随着该应用程序的退出,该计数器也在内存中消失了。
下一次在启动该程序的时候,又重新开始从0计数。
这样不是我盟想要的,
程序即使结束了, 该计数器的值也存在,下次程序启动在会先加载该计数器的值并加1后在重新存储起来,
所以要建立一个配置文件,用于记录该软件的使用次数
需要有名称;
该配置文件使用键值对的形式,这样便于阅读书籍,并操作数据
键值对数据是map集合, 数据是以文件形式存储,使用io技术,
那么map和io,-->Properties,
配置文件可以实现应用程序数据的共享。
第一次运行程序的时候, 这个配置文件不在,
在运行的时候, 才会建立配置文件, 并往当中写1,
常见的配置文件ini或者是properties格式的文件。
扩展名就是集合名, 里面的配置信息肯定是键值对,
*/
import java.util.*;
import java.io.*;
class PropertiesTest
{
public static void main(String[] args) throws Exception
{
Properties prop=new Properties();
File file=
new File("F:\\5 自学资料\\Java 1 笔记\\java进阶\\5 IO流\\3 Properties\\count.ini");
if(!file.exists()){
file.createNewFile();
}
FileInputStream fis=new FileInputStream(file);//读取流中的数据
prop.load(fis);//将流中的数据加载进来集合
int count=0;
String value=prop.getProperty("time");
if(value!=null){
count=Integer.parseInt(value);
if(count>=5){
System.out.println("您好,使用次数已到,请注册");
return ;
}
}
count++;
prop.setProperty("time",count+"");
FileOutputStream fos=new FileOutputStream(file);
prop.store(fos,"");
fos.close();
fis.close();
}
}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------