[关闭]
@lemonguge 2015-07-01T08:06:37.000000Z 字数 8236 阅读 374

Java I/O系统(一)

I/O


笔者首次接触I/O的时候,查看API后发现类库中提供了如此多的类,当时就感到不知所措了。曾经两次学习到了一半就放弃了,因为实在是记不过来,后来坚持下来把I/O学习完,感受还是很多的。现在对Java I/O系统会进行详细的介绍,希望能对读者有些帮助吧。

为什么I/O中会有如此多的类呢?

“对语言设计人员来说,创建好的输入/输出系统是一项特别困难的任务。”——《Think in Java》

无论是系统、还是语言的设计中I/O的设计都是异常复杂的。面临的最大的挑战一般是如何覆盖所有可能的因素,我们不仅仅要考虑文件、控制台、网络、内存等不同的种类,而且要处理大量的不同的读取方式,如:顺序读取、随机读取、缓存读取、二进制读取、按字符读取、按行读取、按字读取……


File类

在学习Java I/O之前,我们应该学习java.io.File类,笔者认为学习这个类是最容易获得成就感的,同时能对后面的学习起到非常大的作用。

大家第一次看到File类时,我们可能会认为它是一个文件,实际上它要强大的多,它能代表一个特定文件的名称,又能代表一个文件目录的名称。查看API可以发现File类并没有默认的构造器,因为当你创建这个类的对象时就必须初始化FilePath文件路径,此时该对象可以表示一个实际存在的或者不存在的文件或文件目录。实际上,FilePath(文件路径)对这个类说是个更好的名字。

在API中可以发现File类有4个属性,后缀为Char的属性表示为一个字符,pathSeparatorseparator属性表示一个字符串,和后缀为Char的属性内容相同,只是表示形式不同。因为字符串的形式更短且更为常用,所有才会出现这两个变体。

  1. public static void showFileProp() {
  2. System.out.println(File.pathSeparator);
  3. System.out.println(File.separator);
  4. System.out.println(File.pathSeparatorChar);
  5. System.out.println(File.separatorChar);
  6. } /* Output:
  7. ;
  8. \
  9. ;
  10. \
  11. *///:~

File.pathSeparator表示路径分隔符,File.separator表示名称分隔符。大家可能会认为,我直接在Windows下使用\进行名称分隔不行吗?当然是可以的。但是在Linux下就不是\了。所以,要想使得我们的代码跨平台,更加健壮,所以,笔者建议大家都采用这两个字符串常量。

创建文件或文件夹

创建一个File对象,有两种方式:相对路径和绝对路径。

相对路径

  1. import java.io.File;
  2. import java.io.IOException;
  3. public class CreateFile {
  4. public static void main(String[] args) throws IOException {
  5. creRelFile();
  6. creRelDir();
  7. }
  8. // 在相对路径下创建文件
  9. public static void creRelFile() throws IOException {
  10. File file = new File("file.txt"); // 创建一个实际不存在的file对象
  11. System.out.println(file.createNewFile()); // 在当前项目下创建了一个名为file,后缀为txt的文件
  12. file = new File("file.txt"); // 创建一个实际存在的file对象,已表示为一个文件
  13. System.out.println(file.createNewFile()); //将创建失败
  14. }
  15. // 在相对路径下创建目录
  16. public static void creRelDir() {
  17. File dir = new File("file.txt"); // 创建一个实际存在的file对象,已表示为表示一个文件
  18. System.out.println(dir.mkdir()); // 将创建失败
  19. dir = new File("dir.txt"); // 创建一个实际不存在的file对象
  20. System.out.println(dir.mkdir()); // 在当前项目下创建了一个名为dir.txt的目录
  21. }
  22. } /* Output:
  23. true
  24. false
  25. false
  26. true
  27. *///:~

绝对路径

  1. public static void creAbsFile() throws IOException {
  2. File file = new File("D:" + File.separator + "file.txt");
  3. // 等价于File file = new File("D:\\file.txt");
  4. // 在windows下,名称分隔为“\”,由于`java`的正则原因所以需要两个
  5. System.out.println(file.createNewFile());
  6. file = new File("D:" + File.separator + "io" + File.separator + "file.txt"); // 假设D盘下没有io目录
  7. try {
  8. System.out.println(file.createNewFile());
  9. } catch (IOException e) {
  10. System.out.println(e);
  11. }
  12. } /* Output:
  13. true
  14. java.io.IOException: 系统找不到指定的路径。
  15. *///:~

在使用绝对路径时,应该时刻注意当前文件路径是否存在。

  1. public static void creAbsDir() throws IOException {
  2. File dir = new File("D:" + File.separator + "io" + File.separator + "dir" + File.separator); // 假设D盘下没有io目录
  3. System.out.println(dir.mkdir()); // 只能创建单级目录
  4. System.out.println(dir.mkdirs()); // 可以创建多级目录
  5. File file = new File(dir, "file.txt"); // 通过父路径对象和子路径来创建file对象
  6. System.out.println(file.createNewFile()); // 创建文件
  7. } /* Output:
  8. false
  9. true
  10. true
  11. *///:~

在D盘下的“io目录”里的“dir目录”中可以找到file.txt文件。

File实用方法

查看文件属性

  1. public static void fileCommonMethod() throws IOException {
  2. File file = new File("file.txt");
  3. if (!file.exists()) // 判断虚拟文件路径是否存在
  4. file.createNewFile();
  5. System.out.println(file.isFile());
  6. System.out.println(file.isDirectory()); // 判断是否表示一个目录
  7. System.out.println(file.isAbsolute()); // 测试此抽象路径名是否为绝对路径名。
  8. System.out.println(file.isHidden()); // 判断文件是否为隐藏
  9. System.out.println(file.getName());
  10. System.out.println(file.canExecute());// 是否可执行
  11. System.out.println(file.canRead());// 是否可读
  12. System.out.println(file.canWrite());// 是否可写
  13. System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified())));// 最近修改时间
  14. // 无符号右移30位即/1024/1024/1024,查看以G为单位的存储空间
  15. System.out.println(Long.toString(file.getFreeSpace() >>> 30) + "G");// 当前分区的可用空间,即D盘的可用容量
  16. System.out.println(Long.toString(file.getTotalSpace() >>> 30) + "G");// D盘总容量
  17. System.out.println(Long.toString(file.getUsableSpace() >>> 30) + "G");// //D盘可用于虚拟机的空间
  18. System.out.println(file.getPath());// 创建File对象中写什么便输出什么
  19. System.out.println(file.getParent());
  20. System.out.println(file.getAbsolutePath());
  21. System.out.println(new File(file.getAbsolutePath()).getName());
  22. System.out.println(new File(file.getAbsolutePath()).getPath());
  23. System.out.println(new File(file.getAbsolutePath()).getParent());
  24. System.out.println(new File(new File(file.getAbsolutePath()).getParent(),"file.txt").getPath());
  25. } /* Output:
  26. true
  27. false
  28. false
  29. false
  30. file.txt
  31. true
  32. true
  33. true
  34. 2015-06-13 12:15:55
  35. 144G
  36. 299G
  37. 144G
  38. file.txt
  39. null
  40. G:\itcast_wordspace\io\file.txt
  41. file.txt
  42. G:\itcast_wordspace\io\file.txt
  43. G:\itcast_wordspace\io
  44. G:\itcast_wordspace\io\file.txt
  45. *///:~

列出目录的全部文件(包含隐藏文件)

File.listRoots()和listFiles()方法
  1. public static void listRootFiles() throws IOException {
  2. // 列出可用的文件系统根。
  3. File[] files = File.listRoots(); // 在Windows环境下,驱动器也会被提供根目录
  4. System.out.println(files.length);
  5. System.out.println("-------");
  6. for (File file : files) {
  7. System.out.println(file + "=" + String.valueOf(file.getFreeSpace() >>> 30) + "G");
  8. File sys = new File(file, File.separator);
  9. String name = sys.getName();
  10. System.out.println(name); // 每个分区和驱动器的名字虽然无法显示且长度为0,但不为null,也不为""。
  11. // System.out.println(name.length()); // 0
  12. // System.out.println(name==""); // false
  13. // System.out.println(name==null); // false
  14. if (sys.listFiles() != null)
  15. for (File sf : sys.listFiles()) // 当前分区的所有目录
  16. System.out.println(sf.getName());
  17. System.out.println("-------");
  18. }
  19. } /* Output:
  20. 5
  21. -------
  22. C:\=41G
  23. $Recycle.Bin
  24. cache_index.db
  25. CFLog
  26. Documents and Settings
  27. ... // 太多不全部显示
  28. -------
  29. D:\=275G
  30. $RECYCLE.BIN
  31. BaiduYunDownload
  32. DMDownLoad
  33. ...
  34. -------
  35. E:\=0G // 此为一个驱动器
  36. -------
  37. G:\=144G
  38. $RECYCLE.BIN
  39. CW
  40. IntelliJ_Project
  41. ...
  42. -------
  43. I:\=98G
  44. $RECYCLE.BIN
  45. System Volume Information
  46. video
  47. ...
  48. -------
  49. *///:~
list()方法
  1. public static void listFiles() {
  2. File file = new File("D:"+File.separator);
  3. String[] fileStrs = file.list(); // 指定此抽象路径名表示的目录中的文件和目录。
  4. for(String fileStr : fileStrs)
  5. System.out.println(fileStr);
  6. } /* Output:
  7. $RECYCLE.BIN
  8. BaiduYunDownload
  9. dir.txt
  10. file.txt
  11. oraysl.status
  12. Program Files
  13. ... // 太多不全部显示
  14. *///:~
FilenameFilter和FileFilter

FilenameFilter接口中只有一个方法:boolean accept(File dir, String name),该方法的作用是测试指定文件是否应该包含在某一文件列表中。

  1. public static void filenameFilter() {
  2. File file = new File("D:"+File.separator);
  3. String[] fileNames = file.list(new FilenameFilter(){
  4. @Override
  5. public boolean accept(File dir, String name) {
  6. return name.endsWith(".txt");
  7. }
  8. });
  9. System.out.println(Arrays.toString(fileNames));
  10. for(String fileName : fileNames)
  11. System.out.println(fileName+" "+(new File(file,fileName).isDirectory()?"is a Dir":"is a File"));
  12. } /* Output:
  13. [dir.txt, file.txt]
  14. dir.txt is a Dir
  15. file.txt is a File
  16. *///:~

FileFilter接口中也只有一个方法:boolean accept(File pathname),该方法的作用是测试指定抽象路径名是否应该包含在某个路径名列表中。

  1. public static void fileFilter() {
  2. File file = new File("D:" + File.separator);
  3. File[] files = file.listFiles(new FileFilter() {
  4. @Override
  5. public boolean accept(File pathname) {
  6. return !pathname.isDirectory(); // 过滤掉所有的目录
  7. }
  8. });
  9. System.out.println(Arrays.toString(files));
  10. } /* Output:
  11. [D:\file.txt, D:\oraysl.status]
  12. *///:~
renameTo()方法

该方法表示的是重命名一个文件或目录、移动一个文件。

  1. // 重命名的情况
  2. public static void renameToRn() throws IOException {
  3. File dir = new File("D:" + File.separator);
  4. File dest = new File(dir, "newdir.txt");
  5. System.out.println(dest.exists());
  6. File file = new File(dir, "dir.txt");
  7. if(!file.exists())
  8. file.mkdir();
  9. System.out.println(file.renameTo(dest)); // 重命名目录
  10. System.out.println(file.exists());
  11. System.out.println(dest.exists());
  12. } /* Output:
  13. false
  14. true
  15. false
  16. true
  17. *///:~
  1. public static void renameToMv() {
  2. File file = new File("D:" + File.separator+"file.txt"); // 文件存在
  3. File dest = new File("G:" + File.separator+"newfile.txt");
  4. System.out.println(file.exists());
  5. System.out.println(dest.exists());
  6. System.out.println(file.renameTo(dest));
  7. System.out.println(file.exists());
  8. System.out.println(dest.exists());
  9. System.out.println("---------");
  10. file = new File("D:" + File.separator+"dir.txt"); // 目录存在
  11. dest = new File("C:" + File.separator+"newfile.txt");
  12. System.out.println(file.exists());
  13. System.out.println(dest.exists());
  14. System.out.println(file.renameTo(dest));
  15. } /* Output:
  16. true
  17. false
  18. true
  19. false
  20. true
  21. ---------
  22. true
  23. false
  24. false
  25. *///:~
delete()方法

删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。

  1. public static void delete() {
  2. File dir = new File("D:" + File.separator + "a" + File.separator + "b" + File.separator + "c");
  3. System.out.println(dir.mkdirs()); // 创建多级目录
  4. System.out.println(dir.getName()); // 该虚拟文件路径表示为一个c目录
  5. System.out.println(dir.delete()); // 仅仅删除了c目录!
  6. } /* Output:
  7. true
  8. c
  9. true
  10. *///:~
  1. public static void delete() throws IOException {
  2. File dir = new File("D:" + File.separator + "a" + File.separator + "b" + File.separator + "c");
  3. System.out.println(dir.mkdirs()); // 创建多级目录
  4. File file = new File(dir, "file.txt");
  5. System.out.println(file.createNewFile());
  6. System.out.println(dir.delete()); // 目录中有文件,删除失败
  7. } /* Output:
  8. true
  9. true
  10. false
  11. *///:~
  1. public static void removeDir(File dir) {
  2. File[] files = dir.listFiles();
  3. for(File file : files){
  4. if(file.isDirectory()){
  5. removeDir(file);
  6. }else{
  7. System.out.println(file+":"+file.delete());
  8. }
  9. }
  10. System.out.println(dir+":"+dir.delete());
  11. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注