一、文件概述
在计算机中,通常都需要文件系统来管理文件,文件系统中通过“树形” 组织文件和目录,文件可以分为文本文件和二进制文件,如果文件记事本打开出现乱码就是二进制文件,否则就是文本文件,常见的二进制文件有:.txt,.c,.java等;常见的文本文件有:.doc,.jpg,.class以及office系列的一些文件。
在文件系统中,文件的路径可以分为绝对路径和相对路径。
绝对路径:就是从根目录开始到文件,也就是从盘符开始的文件,例如:D:\bin\aa\c.txt
相对路径:以./或者../开头的路径,./代表当前目录,../代表父目录(上级目录),在相对路径中必须有一个基准目录,例如:./c.txt
二、常见文件操作
1、获取文件路径
getParent():获取File对象的父目录的文件路径。
getPath():返回File对象的文件路径,就是在创建File对象时指定的路径。
getAbsolutePath():返回File对象的绝对路径,该方法在返回时会将绝对路径中的./和../理解成正确路径。
getCanonicalPath():返回File对象修饰过的绝对路径。
例如:利用相对路径和绝对路径创建文件。
public static void main(String[] args) throws IOException { File file = new File("D:/test/test.doc"); System.out.println(file.getParent()); System.out.println(file.getPath()); System.out.println(file.getAbsoluteFile()); System.out.println(file.getCanonicalFile()); System.out.println("____________________________"); File file1=new File("./test.txt"); System.out.println(file1.getParent()); System.out.println(file.getPath()); System.out.println(file1.getAbsoluteFile()); System.out.println(file1.getCanonicalFile()); }
运行结果:
2、判断文件存在以及判断类型
exists():判断File对象是否存在。
isFile():判断File对象是否为一个普通文件。
isDirectory():判断File对象是否为一个目录文件。
操作演示:
public void static void main(String[] args){ File file = new File("D:/test/test.doc"); System.out.println(file.exists()); System.out.println(file.isFile()); System.out.println(file.isDirectory()); }
运行结果:
3、文件的创建与删除
createNewFile():会根据File对象自动地创建一个空文件。
delete():删除文件,删除成功后,返回true;
deleteOnExit():根据File对象,标注文件将会被删除,删除动作会到JVM运行结束时才会进行。也就是说在程序运行结束时才会执行删除操作。
public static void main(String[] args) throws IOException { File file=new File("./abc.txt"); file.createNewFile(); System.out.println(file.exists()); file.delete(); System.out.println(file.exists()); }
运行结果:
4、展示文件夹的文件
list():返回值是String[],返回的是目录文件下的所有文件名。
listFiles():返回值是File(),返回的是目录文件下的所有的文件。
public static void main(String[] args) throws IOException { File file=new File("d:/test"); String[] fileNames=file.list(); for(int i=0;i< fileNames.length;i++){ System.out.print(fileNames[i]+" "); } System.out.println(); File[] files=file.listFiles(); for(int i=0;i<files.length;i++){ System.out.print(files[i] + " "); } }
5、创建文件夹
mkdir():创建单个目录文件。
mkdirs():创建多个嵌套的目录文件。
public static void main(String[] args) throws IOException { File file=new File("D:/test/a"); file.mkdir(); System.out.println(file.getAbsolutePath()); File file2=new File("D:/test/sa/wq/a/c"); file.mkdirs(); System.out.println(file2.getAbsolutePath()); }
运行结果:
三、用数据流来读取文件内容
在Java标准库中提供了一组类来进行文件操作:
字节流文件:也就是二进制文件,以字节的方式进行读写,利用InputStream和OutputStream类进行操作。
字符流文件:以字符的方式进行读取,利用Reader和Writer类进行操作。
但是上述的四个类都是抽象类,在真正实现时采用FileInputStream、FileOutputStream、FileReader和FileWriter。
1、操作字节流文件
a、读取字节流文件
需要创建一个FileinputStream流对象,利用read方法读取字符流文件时使用byte[]字节数组进行接收,最后对byte数组进行遍历输出。注意:在读取文件以及关闭文件时可能都会出现IOException,于是在try()的括号中构建实例,这样就不用在finally中关闭流对象,会自动关闭。
try(InputStream inputStream=new FileInputStream("D:\\one-question-per-day\\src\\test.txt")){ byte[] buffer=new byte[1024]; int len; while(true){ len=inputStream.read(buffer); if(len==-1){ break; } System.out.println(Arrays.toString(buffer)); } }catch (IOException e){ e.printStackTrace(); }
b、写字节流文件
需要创建一个FileOutputStream流对象,然后同样也是try—catch处理异常,然后利用write()方法向指定文件写入内容。
try(OutputStream outputStream=new FileOutputStream("D:\\one-question-per-day\\src\\test.txt")){ outputStream.write(11); outputStream.write(90); outputStream.write(23); }catch(IOException e){ e.printStackTrace(); }
2、操作字符流对象
a、读取字符流文件
需要创建一个FileReader对象,再创建一个char[]型数组用于接收文件的字符,最后再对char数组进行遍历。
try(Reader reader=new FileReader("D:\\one-question-per-day\\src\\test.txt")){ char[] chars=new char[1024]; int len; while(true){ len=reader.read(chars); if(len==-1){ break; } for(int i=0;i<len;i++){ System.out.println(chars[i]); } } }catch (IOException e){ e.printStackTrace(); }
b、写字符流文件
需要创建一个FileWriter对象,再用write()方法写入指定文件。
try(Writer writer=new FileWriter("D:\\one-question-per-day\\src\\test.txt")){ writer.write(99); writer.write('x'); writer.write('a'); }catch (IOException e){ e.printStackTrace(); }
四、常见题目
1、扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件。
解题思路:首先输入要指定的目录文件的路径和指定字符,首先需要判断路径是否有效,接着再利用listFiles()列出目录中的文件存放到files数组中,对数组进行遍历,若是普通文件则询问删除,若是目录文件,则递归调用本身方法。
public static void deleteFile(String path,String name){ File file=new File(path); if(!file.exists()){ System.out.println("指定路径的文件不存在"); } File[] files=file.listFiles(); if(files==null){ return; } for(File f:files){ if(f.isDirectory()){ deleteFile(f.getAbsolutePath(),name); } if(f.isFile()){ if(f.getName().contains(name)){ System.out.println(f.getAbsolutePath()+"确认删除吗?(y/n)"); Scanner sc=new Scanner(System.in); char option=sc.next().charAt(0); if(option=='y'){ f.delete(); }else if(option!='n'){ System.out.println("输入有误"); } } } } } public static void main(String[] args) { System.out.println("请输入要检索的文件路径"); Scanner sc=new Scanner(System.in); String str=sc.next(); System.out.println("请输入要删除的文件名包含的信息"); String str2=sc.next(); deleteFile(str,str2); }
2、复制普通文件
解题思路:分别创建输入流对象和输出流对象,然后定义byte数组,对原文件进行读取,将读取的内容写入新复制的文件。
public static File copyFile(File file) throws IOException { if(!file.exists()){ System.out.println("文件不存在"); } File dFile=new File("dFile.txt"); try(InputStream inputStream=new FileInputStream(file)){ try(OutputStream outputStream=new FileOutputStream(dFile)){ byte[] buffer=new byte[1024]; int len=0; while(true){ len= inputStream.read(buffer); if(len==-1){ break; } outputStream.write(buffer,0,len); } } } return dFile; }
3、扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
解题思路:该题与第一题类似,也需要用到递归思想,本题着重在于如何确定文件内容中是否含有指定字符。可以利用StringBuilder对象,将每次读到的内容添加进去,再在StringBuilder对象中检索是否包含指定字符。
public static void scanFile(File file,String massage) throws FileNotFoundException { if(!file.exists()){ System.out.println("文件不存在"); } File[] files=file.listFiles(); if(files==null){ return; } for(File f:files){ if(f.isFile()){ if(f.getName().contains(massage)||content(f,massage)){ System.out.println(f.getName()); } } if(f.isDirectory()){ scanFile(f,massage); } } } public static boolean content(File file,String massage) throws FileNotFoundException { StringBuilder stringBuilder=new StringBuilder(); try(Reader reader=new FileReader(file)) { char[] chars=new char[1024]; int len=0; while(true){ len=reader.read(chars); if(len==-1){ break; } stringBuilder.append(chars,0,len); } } catch (IOException e) { e.printStackTrace(); } return stringBuilder.indexOf(massage)==-1; }