Java : File
在java的世界里,everything is object,文件和目录也不例外。无论在WINDOWS、LINUX or MAC,目录和普通文件都可以封装成对象。java提供了File类来操作计算机系统中的文件和目录。
File中有两个常量:
File.separator,即目录分隔符。在windows中为"\"但涉及到转移字符,所以正确的写法是“\\”;在linux中表示为“/”,如下文所示。
File.pathSeparator 用于分割多个路径的字符,比如在我使用的fedora系统中为“:”,例如“
MODULEPATH=/etc/scl/modulefiles:/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles
”;而在WINDOWS中为“;”,查看一下WINDOWS中的环境变量就明白了。
File.separator 用于分割目录的字符,例如“/home/owen/desktop”中的“/”,又或者windows中“C:\\windows\\system32”中的“\”
1 import java.io.*; 2 /* 3 * File类:用来将文件或者文件夹封装成对象 4 */ 5 6 public class FileDemo { 7 8 public static void main(String[] args) { 9 //创建文件对象,可以将已有的或者未出现的文件或者文件夹封装成对象 10 File f1 = new File("a.txt"); 11 //创建文件对象,指定父目录和文件 12 File f2 = new File("/home/owen/myProgram","File.txt"); 13 //File.separator,目录分隔符,有跨平台性 14 File f3 = new File(File.separator+"home"+File.separator+"owen"+File.separator+"myProgram"+File.separator+"File.tmp"); 15 16 System.out.println(f1); 17 System.out.println(f2); 18 System.out.println(f3); 19 20 //File类常见方法: 21 //创建: boolean createNewFile(),在指定位置创建文件,如果该文件已经存在,则不创建,返回false。与输出流不同,输出流对象一建立就会创建文件,或者覆盖 22 File cf = new File("creat.txt"); 23 try { 24 System.out.println("Creat a txt success? "+cf.createNewFile()); 25 } catch (IOException e) { 26 e.printStackTrace(); 27 } 28 //创建临时文件 29 //static File createTempFile(String prefix, String suffix)在默认文件目录中创建一个空文件,使用给定前缀和后缀生成名称 30 //static FIle createTempFile(String prefix, String suffix, File directory)在指定文件目录中创建一个空文件,使用给定前缀和后缀生成名称 31 //创建目录mkdir mkdirs. mkdir只能创建一级目录,mkdirs可以创建多级目录 32 File mkd = new File("/home/owen/myProgram/data/bulider"); 33 System.out.println("mkdir success? " + mkd.mkdir()); 34 System.out.println("mkdirs success? " + mkd.mkdirs()); 35 36 //删除 37 //boolean delete() 38 System.out.println("Delete creat.txt success? " + cf.delete()); 39 //void deleteOnExit(),在虚拟机退出时删除. 应用:比如当有可能删除时正常使用的文件 40 f1.deleteOnExit(); 41 42 //判断 43 //boolean canExecute,该文件是否可执行 44 System.out.println("File.txt can execute? " + f2.canExecute()); 45 String str = new String("/usr/bin/cp"); 46 File f4 = new File(str); 47 System.out.println("\"cp\" can execute? " + f4.canExecute()); 48 //boolean exists(),文件是否存在。 该方法有高使用频率 49 System.out.println("cp is in /usr/bin? " + f4.exists()); 50 //boolean isDirectory,判断文件是否为目录 51 //boolean isFile,判断是否为普通文件 52 //!!!在判断文件对象是否为文件或者目录时,一定要先判断该对象是否存在 53 54 //listRoots,列出可用的根文件 55 File[] rootList = File.listRoots(); 56 for(File f: rootList){ 57 System.out.println(f); 58 } 59 //list 列出指定目录下的文件或者文件夹(所有的文件,包含隐藏文件).只能用存在的目录对象调用list,不可以使用不存在的目录调用list,也不可以对普通文件对象调用list 60 File listDirectory = new File("/home/owen/private"); 61 String[] ld = listDirectory.list(); 62 System.out.println("列出private中的文件"); 63 for (String s: ld){ 64 System.out.println(s); 65 } 66 67 68 } 69 70 }
下面给出两个利用递归方法,列出指定目录下的文件和文件夹的例子。
1 import java.io.*; 2 3 /* 4 * 使用递归需要注意: 5 * 1.限定条件,避嫌出现无限循环 6 * 2.注意递归次数,避免内存溢出 7 * */ 8 public class listFilesDemo { 9 10 public static void main(String[] args) { 11 File dir = new File("/home/owen/"); 12 // listDirectoryByRecursive(dir); 13 listDirectoryByRecursive(dir,0); 14 15 } 16 17 //使用递归方法列出指定目录下的内容;但该方法不能较好现实层级关系 18 /* 19 public static void listDirectoryByRecursive(File dir){ 20 System.out.println(dir);//打印该目录名称 21 File[] files = dir.listFiles();//把dir下的文件名称存放到files数组中 22 for (int x = 0; x < files.length; x++){ 23 if (files[x].isDirectory())//如果指定目录下的文件是文件夹则使用递归方法继续激烈该文件夹中的内容 24 listDirectoryByRecursive(files[x]); 25 else 26 System.out.println(files[x]);//如果是普通文件,则列出文件名称 27 } 28 } 29 */ 30 //列出指定目录下的文件名称,带层级关系 31 public static void listDirectoryByRecursive(File dir,int level){ 32 System.out.println(getLevel(level)+dir.getName());//打印该目录名称 33 File[] files = dir.listFiles();//把dir下的文件名称存放到files数组中 34 level++; 35 for (int x = 0; x < files.length; x++){ 36 if (files[x].isDirectory())//如果指定目录下的文件是文件夹则使用递归方法继续激烈该文件夹中的内容 37 listDirectoryByRecursive(files[x],level); 38 else 39 System.out.println(getLevel(level)+files[x]);//如果是普通文件,则列出文件名称 40 } 41 } 42 public static String getLevel(int level){ 43 StringBuilder sb = new StringBuilder(); 44 for (int x =0; x < level; x++){ 45 if(sb.length()==0) 46 sb.append("|--"); 47 else 48 sb.append("--"); 49 } 50 return sb.toString(); 51 } 52 53 }
带行号的Reader,LineNumberReader:
1 import java.io.*; 2 3 public class LineNumberReaderDemo { 4 5 public static void main(String[] args) { 6 LineNumberReader lnr = null; 7 try{ 8 lnr = new LineNumberReader(new FileReader("xinwen.txt")); 9 String line = null; 10 lnr.setLineNumber(100);//设置行号开始为100 11 while((line=lnr.readLine())!=null){ 12 System.out.println(lnr.getLineNumber()+":"+line); 13 } 14 } 15 catch(IOException e) 16 { 17 e.printStackTrace(); 18 } 19 finally{ 20 try{ 21 if(lnr!=null) 22 lnr.close(); 23 } 24 catch(IOException e){ 25 throw new RuntimeException("close readFile erro"); 26 } 27 } 28 29 } 30 31 }
使用自定义的方法实现带行号的Reader:
import java.io.*; public class MyLineNumberReaderDemo { public static void main(String[] args) { MyLineNumberReader mlnr = null; try{ mlnr = new MyLineNumberReader(new FileReader("xinwen.txt")); mlnr.setLineNumber(200); String line=null; while((line = mlnr.myReadLine())!=null){ System.out.println(mlnr.getLineNumber()+":"+line); } } catch(IOException e){ e.printStackTrace(); } finally{ try{ if(mlnr!=null) mlnr.myClose(); } catch(IOException e) { throw new RuntimeException("关闭读取错误"); } } } } //LineNumberReader继承了BufferedReader,<--这个类重写了readLine方法。所以我们自定义的MylineNumberReader也可以extends BufferedReader,这样就不用自己写readLine方法和close方法了。 class MyLineNumberReader{ private Reader r; private int lineNumber; MyLineNumberReader(Reader r){ this.r = r; } public void setLineNumber(int lineNumber){ this.lineNumber = lineNumber; } public int getLineNumber(){ return lineNumber; } /* * 如果MyReadLineNumberReader extends BufferedReader,那么这里可以这样写 * public String myReadLine() throws IOException{ * lineNumber++; * return super.readLine(); * } * */ public String myReadLine()throws IOException{ lineNumber++; StringBuilder sb = new StringBuilder(); int ch = 0; while((ch = r.read())!=-1){ // if(ch == '\r') //貌似不要这个判断也是对的??? // continue; if(ch == '\n') return sb.toString(); else sb.append((char)ch); } if(sb.length()!=0) return sb.toString(); else return null; } //如果MyReadLineNumberReader extends BufferedReader,那么就可以不用写任何close方法,因为BufferedReader继承了Reader,我们只需要在使用时调用父类BufferedReader的父类Reader的close方法即可 public void myClose()throws IOException { r.close(); } }