【转载】J2SE知识点归纳笔记(七)---Java IO Part 1:File类与RandomAccessFile类

注:本文出自coder-pig

原文链接:http://blog.csdn.net/coder_pig/article/details/45248445





很快要到I/O流了,都是重要的内容,而且内容很多有难度的哦,如果是小花自己写不知能否坚持下去,感谢小猪的这些文章,他可是花了很多心思,整个人都老了一大截可怜,希望大家能好好看看,不枉他老人家一片苦心。。。偷笑






本节引言:


兜兜转转,又回来写Java了,上一篇J2SE知识点归纳笔记(六)---Java常用类是上2014.4.14写的,时隔一年

又来重拾之前还没写完的系列了,前些天群里一个妹子反映她Java基础薄弱,然后抱怨在csdn上找不到J2SE的

系列教程,J2SE简单嘛,个个都懒得写...真的简单么?或许吧...今天刚写完论文初稿,也算稍微轻松了那么一点,

白天上班,晚上赶论文,痛苦的一个星期也算到头了...趁着临近周末,小猪也来动下笔墨吧,(*^__^*) 嘻嘻……

哪怕有一个读者,小猪也会坚持写下去的。好了,唠叨的废话就说到这。本节要学习的东西:

Java IO,一说到IO,估计大家第一时间想起的就是:流,输入输出流,字符流,字节流等等,是吧,但是本节先不讲

流,先来点开胃菜,介绍两个文件IO的类: File(文件类)与RandomAccessFile(随机访问文件类),开始本节内容~


ps:另外说下Java IO相关的类和接口都放在java.io包下,大家要养成查API的习惯哦~







本节正文:


1.File(文件类):

1)File类的定义:

描述文件的相关特性,比如:是否可读,可写,文件大小等特性的一个类


2)创建File类对象时要注意的地方:

答:首先我们要区分两个名词:"绝对路径"和"相对路径"

绝对路径——即完整的路径,比如:D:\MyCode\Java\FileDemo

相对路径——会在代码所在的地方生成,比如:res/jay.txt  就会在你代码的目录下成jay.txt文件

另外,还有注意一点,文件的路径与Windows下不同,"\"要写成'/'或者"\\"不然会报错的喔~


如果,你想保险点,让程序跨平台的话,比如在linux下就和Windows不一样的,Linux下是"/"

解决方法就是使用File给我们提供的两个常量,他们分别是:

File.separator: "\"            File.pathSeparator:";"


如果我们是直接自己拼的话,在window下,在D盘下我们要创建一个Jay.txt文件要这样写:

File f=new File("D:\\Jay.txt");    如果在Linux下呢?要写成 //

如果我们用使用上面的两个常量的话,我们无需理在什么系统下,直接:

String fileName="D:"+File.separator+"Jay.txt";

File f=new File(fileName);

打印下fileName:  




好了,记得把这两个变量Mark下来哦~



3)File的常见方法:

1)判断文件或者目录是否存在:  exists()

2)判断是否为目录:   isDirectory()

3)判断是否为文件:    isFile()

4)判断文件是否可读:    canRead()

5)判断文件是否可写:    canWrite()

6)判断文件是否隐藏:    isHidden()

7)判断文件路径是否为绝对路径:  isAbsolute()

8)判断文件路径是否相同:  equals():返回true,false        

                                        compareTo():是否相等,相等返回0,小于返回负数,大于返回正数

9)获取文件的绝对路径:   getAbsolutePath()

10)获取文件名称:  getName()

11)获取文件大小:  length()

12)获取文件最后被修改的时间 :  lastModified()

13)获取文件的路径:   getPath()

14)获取文件的上层文件的目录:   getParent()

15)创建一个新文件:    createNewFile()

16)创建一个新目录:    mkdir()

17)删除文件或目录:  delete()

18)修改文件的名称:   renameTo(str)

19)修改文件为只读:  setReadOnly() 

20)修改最后的修改时间:   setLastModified(long time) 



4)File的使用示例:

①创建一个文件:

  1. public void newFile(String fileName)throws Exception  
  2. {  
  3.     File f=new File(fileName);  
  4.     f.createNewFile();  
  5. }  

②删除一个文件:

  1. public void deleteFile(String fileName)  
  2. {  
  3.     File f=new File(fileName);  
  4.     if(f.exists())f.delete();  
  5.     else System.out.println("文件不存在");  
  6. }  

③创建一个文件夹:

  1. public void newDir(String fileName)  
  2. {  
  3.     //fileName写文件夹名哦,比如:D:\Test  
  4.     File f=new File(fileName);  
  5.     f.mkdir();  
  6. }  

④删除文件夹

删除文件夹的方法和删除文件是一样的,都是调用delete( )方法,空文件夹可以直接删除,

但是有一点要注意的是,非空文件夹是不能直接删除的哦!!!我们需要先把里面的文件都

删除了,才能删除文件夹哦,那么现在我们要做的是,就是删除文件夹里的文件咯,如果

有几层怎么破?我们需要考虑这个问题,这里的话,如果我们使用递归的话,就很容易解决

这个问题了,代码如下:

  1. import java.io.File;  
  2.   
  3. public class RemoveDir {  
  4.     public static void main(String[] args) {  
  5.         File file = new File("D:\\Test");  
  6.         removeDir(file);  
  7.     }  
  8.   
  9.     public static void removeDir(File file) {  
  10.         File[] files = file.listFiles();  
  11.         for (File f : files) {  
  12.             if (f.isDirectory())// 递归调用  
  13.             {  
  14.                 removeDir(f);  
  15.             } else {  
  16.                 f.delete();  
  17.             }  
  18.         }   
  19.         // 一层目录下的内容都删除以后,删除掉这个文件夹  
  20.         file.delete();  
  21.     }  
  22. }  

好吧,递归就是这么奇妙~


⑤判断路径是否为文件夹(目录):

  1. public boolean isDir(String fileName)  
  2. {  
  3.     File f=new File(fileName);  
  4.     if(f.isDirectory()){  
  5.            <span style="white-space:pre">     </span>return true;  
  6.        <span style="white-space:pre"> </span>}  
  7.     return false;  
  8. }  


⑥遍历某文件夹下所有文件(文件名,包含隐藏文件):

  1. public void getAllFile1(String fileName) {  
  2.     File f = new File(fileName);  
  3.     String[] str = f.list();  
  4.     for (int i = 0; i < str.length; i++) {  
  5.         System.out.println(str[i]);  
  6.     }  
  7. }  


⑦遍历某文件夹下所有文件(包括完整路径,包含隐藏文件)

  1. public void getAllFile2(String fileName) {  
  2.     File f = new File(fileName);  
  3.     File[] str = f.listFiles();  
  4.     for (int i = 0; i < str.length; i++) {  
  5.         System.out.println(str[i]);  
  6.     }  
  7. }  


⑧遍历某目录下的全部文件(包含子目录,完整路径,隐藏文件)

还是用到我们的递归:

  1.     /* 
  2.      * 获取某目录下的全部文件(包含子目录,完整路径,隐藏文件) 
  3.      * */  
  4.     public void getAllFile3(File file) {  
  5.         if(file != null){  
  6.             if(file.isDirectory()){  
  7.                 File[] fileArray=file.listFiles();  
  8.                 if(fileArray!=null){  
  9.                     for (int i = 0; i < fileArray.length; i++) {  
  10.                         //递归调用  
  11.                         getAllFile3(fileArray[i]);  
  12.                     }  
  13.                 }  
  14.             }  
  15.             else{  
  16.                 System.out.println(file);  
  17.             }  
  18.         }  
  19. }  


5)学以致用的两个小例子:

①遍历某个文件夹下特定的文件

比如某个目录下的所有.zip文件,笔者的电脑下载了很多编程视频,

我们想遍历查看所有.zip的文件的名称:


核心是:判断是否为目录,文件名的筛选

好吧,下面我们就来实现吧:


  1. /* 
  2.  * 遍历某目录下特定文件的文件名与路径 
  3.  */  
  4. public static void getSpecificFile(File file, String suffix) {  
  5.     if (file != null) {  
  6.         if (file.isDirectory()) {  
  7.             File[] fileArray = file.listFiles();  
  8.             String name1 = file.getName();  
  9.             System.out.println("——————" + name1);  
  10.             if (fileArray != null) {  
  11.                 for (int i = 0; i < fileArray.length; i++) {  
  12.                     // 递归调用  
  13.                     getSpecificFile(fileArray[i], suffix);  
  14.                 }  
  15.             }  
  16.         } else {  
  17.             if (file.getName().toString().endsWith(suffix)) {  
  18.                 System.out.print("               ");  
  19.                 System.out.println(file  
  20.                         .getName()  
  21.                         .toString()  
  22.                         .substring(  
  23.                                 0,  
  24.                                 file.getName().toString().length()  
  25.                                         - suffix.length()));  
  26.             }  
  27.         }  
  28.     }  
  29. }  


调用方法处代码:



部分运行截图:





②批量文件命名:

比如我们写App的时候,下载了一大堆了素材图片:



而下载的时候:他们的文件名是这样的:


我们是想把他们作为头像的,我们想把他们改成head1.png,head2.png...这种文件名格式的,

难道我们一个个手动的去改么=-=,如果这些图标有上百个,改到什么时候呢?

学以致用,这里我们就来实现简单的批量文件名修改:

比如我们这里需要批量修改下述的图标:



代码实现:

  1. /** 
  2.  * 批量修改文件名: 
  3.  * @param filename 要是目录哦! 
  4.  */  
  5. public static boolean changeFileNames(String fileName,String suffix)  
  6. {  
  7.     File f = new File(fileName);  
  8.     if(!f.isDirectory())  
  9.     {  
  10.         return false;  
  11.     }  
  12.     int j = 0;  
  13.     File[] fs = f.listFiles();  
  14.     for(int i = 0;i < fs.length;i++)  
  15.     {  
  16.         String str = fs[i].getName();  
  17.         if(str.endsWith(suffix))  
  18.         {  
  19.             fs[i].renameTo(new File(fileName + File.separator +"head" + j +suffix));  
  20. /               System.out.println(fileName + File.separator +"head" + j +suffix);  
  21.             j++;  
  22.         }  
  23.     }  
  24.     return true;  
  25. }  


运行后:



好了,就是那么简单,是不是又有趣呢?这里并没有都是一些简单的东西,笔者可以根据自己的需要,

进行拓展,比如遍历文件后,生成另外的txt文件而不是直接打印到屏幕上等....




2.RandomAccessFile类

1)这个类是干嘛的?

随机访问文件类,其实和File的功能类似,都是用于操作文件,但是RandomAccessFile类

seek( )方法来访问文件,可以从文件的任意位置读写文件,这个seek可以看做文件指针吧,

而这个类,我们用的最多的无疑是:Java多线程文件下载~

ps:其实这个小猪已经在Android入门之路的day 8写过了,这里就再贴一遍哈,别怪小猪偷懒哈偷笑,

另外这个多线程下载的话,文件小的话效果不大哦~比如下个1,2mb的东西....另外示例给的是

Tomact搭建的web空项目,要下载的东西丢到Webroot目录下即可,另外你可以可以直接改成

网上的一个下载链接~



我们都知道使用多线程下载文件可以更快地完成文件的下载,但是为什么呢?

答:因为抢占的服务器资源多,假设服务器最多服务100个用户,服务器中的一个线程对应一个用户

100条线程在计算机中并发执行,由CPU划分时间片轮流执行,加入a有99条线程下载文件,那么

相当于占用了99个用户资源,自然就有用较快的下载速度

ps:当然不是线程越多就越好,开启过多线程的话,app需要维护和同步每条线程的开销,这些开销

反而会导致下载速度的降低,另外还和你的网速有关!


多线程下载的流程

获取网络连接——本地磁盘创建相同大小的空文件——计算每条线程需从文件哪个部分开始下载,结束

——依次创建,启动多条线程来下载网络资源的指定部分



ps:这里直接用J2SE来完成多线程操作,直接建立一个工程,使用Junit运行指定方法即可

如果再Android下用单元测试有点麻烦,照顾一部分朋友,你直接new一个Java Project即可!


代码如下:

DownLoader.java

  1. package com.jay.test;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.RandomAccessFile;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import org.junit.Test;  
  8.   
  9.   
  10. public class Downloader {  
  11.     //添加@Test标记是表示该方法是Junit测试的方法,就可以直接运行该方法了  
  12.         @Test  
  13.         public void download() throws Exception  
  14.         {  
  15.             //设置URL的地址和下载后的文件名  
  16.             String filename = "meitu.exe";  
  17.             String path = "http://10.13.20.32:8080/Test/XiuXiu_Green.exe";  
  18.               
  19.             URL url = new URL(path);  
  20.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  21.             conn.setConnectTimeout(5000);  
  22.             conn.setRequestMethod("GET");  
  23.               
  24.             //获得需要下载的文件的长度(大小)  
  25.             int filelength = conn.getContentLength();  
  26.             System.out.println("要下载的文件长度"+filelength);  
  27.             //生成一个大小相同的本地文件  
  28.             RandomAccessFile file = new RandomAccessFile(filename, "rwd");  
  29.             file.setLength(filelength);  
  30.             file.close();  
  31.             conn.disconnect();  
  32.             //设置有多少条线程下载  
  33.             int threadsize = 3;  
  34.             //计算每个线程下载的量  
  35.             int threadlength = filelength % 3 == 0 ? filelength/3:filelength+1;  
  36.             for(int i = 0;i < threadsize;i++)  
  37.             {  
  38.                 //设置每条线程从哪个位置开始下载  
  39.                 int startposition = i * threadlength;  
  40.                 //从文件的什么位置开始写入数据  
  41.                 RandomAccessFile threadfile = new RandomAccessFile(filename, "rwd");  
  42.                 threadfile.seek(startposition);  
  43.                 //启动三条线程分别从startposition位置开始下载文件  
  44.                 new DownLoadThread(i,startposition,threadfile,threadlength,path).start();  
  45.             }  
  46.             int quit = System.in.read();  
  47.             while('q' != quit)  
  48.             {  
  49.                 Thread.sleep(2000);  
  50.             }  
  51.         }  
  52.       
  53.       
  54.     private class DownLoadThread extends Thread {  
  55.           
  56.           
  57.         private int threadid;  
  58.         private int startposition;  
  59.         private RandomAccessFile threadfile;  
  60.         private int threadlength;  
  61.         private String path;  
  62.         public DownLoadThread(int threadid, int startposition,  
  63.                 RandomAccessFile threadfile, int threadlength, String path) {  
  64.             this.threadid = threadid;  
  65.             this.startposition = startposition;  
  66.             this.threadfile = threadfile;  
  67.             this.threadlength = threadlength;  
  68.             this.path = path;  
  69.         }  
  70.           
  71.         public DownLoadThread() {}  
  72.           
  73.         @Override  
  74.         public void run() {  
  75.             try  
  76.             {  
  77.                 URL url = new URL(path);  
  78.                 HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  79.                 conn.setConnectTimeout(5000);  
  80.                 conn.setRequestMethod("GET");  
  81.                 //指定从什么位置开始下载  
  82.                 conn.setRequestProperty("Range""bytes="+startposition+"-");  
  83.                 //System.out.println(conn.getResponseCode());  
  84.                 if(conn.getResponseCode() == 206)  
  85.                 {  
  86.                     InputStream is = conn.getInputStream();  
  87.                     byte[] buffer = new byte[1024];  
  88.                     int len = -1;  
  89.                     int length = 0;  
  90.                     while(length < threadlength && (len = is.read(buffer)) != -1)  
  91.                     {  
  92.                         threadfile.write(buffer,0,len);  
  93.                         //计算累计下载的长度  
  94.                         length += len;  
  95.                     }  
  96.                     threadfile.close();  
  97.                     is.close();  
  98.                     System.out.println("线程"+(threadid+1) + "已下载完成");  
  99.                 }  
  100.                   
  101.                   
  102.             }catch(Exception ex){System.out.println("线程"+(threadid+1) + "下载出错"+ ex);}  
  103.         }  
  104.           
  105.     }  
  106. }  


运行截图:



如图,使用多线程完成了对文件的下载!双击exe文件可运行,说明文件并没有损坏!


注意事项:

int filelength = conn.getContentLength();   //获得下载文件的长度(大小)

RandomAccessFile file = new RandomAccessFile(filename, "rwd");  

//该类运行对文件进行读写,是多线程下载的核心

int threadlength = filelength % 3 == 0 ? filelength/3:filelength+1;

//计算每个线程要下载的量

conn.setRequestProperty("Range", "bytes="+startposition+"-");

//指定从哪个位置开始读写,这个是URLConnection提供的方法

//System.out.println(conn.getResponseCode());

//这个注释了的代码是用来查看conn的返回码的,我们前面用的都是200,

而针对多线程的话,通常是206,必要时我们可以通过调用该方法查看返回码!

int quit = System.in.read();

while('q' != quit){Thread.sleep(2000);}

//这段代码是做延时操作的,因为我们用的是本地下载,可能该方法运行完了,而我们的

线程还没有开启,这样会引发异常,这里的话,让用户输入一个字符,如果是'q'的话就退出


代码下载:J2SEMulDownLoader.zip





最后说两句:

关于JavaIO中的File和RandowAccessFile就介绍这里了,得意

大家可以发挥自己的创造力,使用这两个类,实现自己想要的功能~


最后把File的东东都贴到一个工具类中,有需要的可以复制粘贴:

  1. import java.io.File;  
  2.   
  3.   
  4. public class FileUtil {  
  5.     /* 
  6.      * 创建一个新文件 
  7.      * */  
  8.     public static void newFile(String fileName) throws Exception {  
  9.         File f = new File(fileName);  
  10.         f.createNewFile();  
  11.     }  
  12.   
  13.       
  14.     /* 
  15.      * 删除文件 
  16.      * */  
  17.     public static void deleteFile(String fileName) {  
  18.         File f = new File(fileName);  
  19.         if (f.exists())  
  20.             f.delete();  
  21.         else  
  22.             System.out.println("文件不存在");  
  23.     }  
  24.   
  25.     /* 
  26.      * 创建一个文件夹(目录) 
  27.      * */  
  28.     public static void newDir(String fileName) {  
  29.         // fileName写文件夹名哦,比如:D:\Test  
  30.         File f = new File(fileName);  
  31.         f.mkdir();  
  32.     }  
  33.   
  34.     /* 
  35.      * 删除一个文件夹(目录) 
  36.      * */  
  37.     public static void deleteDir(File file) {  
  38.         File[] files = file.listFiles();  
  39.         for (File f : files) {  
  40.             if (f.isDirectory())// 递归调用  
  41.             {  
  42.                 deleteDir(f);  
  43.             } else {  
  44.                 f.delete();  
  45.             }  
  46.         }  
  47.         // 一层目录下的内容都删除以后,删除掉这个文件夹  
  48.         file.delete();  
  49.     }  
  50.   
  51.     /* 
  52.      * 判断是否为一个文件夹(目录) 
  53.      * */  
  54.     public static boolean isDir(String fileName) {  
  55.         File f = new File(fileName);  
  56.         if (f.isDirectory()) {  
  57.             return true;  
  58.         }  
  59.         return false;  
  60.     }  
  61.   
  62.     /* 
  63.      * 获取目录下的全部文件名,包含隐藏文件 
  64.      */  
  65.     public static void getAllFile1(String fileName) {  
  66.         File f = new File(fileName);  
  67.         String[] str = f.list();  
  68.         for (int i = 0; i < str.length; i++) {  
  69.             System.out.println(str[i]);  
  70.         }  
  71.     }  
  72.   
  73.     /* 
  74.      * 获取目录下的全部文件名包含完整路径,包含隐藏文件 
  75.      */  
  76.     public static void getAllFile2(String fileName) {  
  77.         File f = new File(fileName);  
  78.         File[] str = f.listFiles();  
  79.         for (int i = 0; i < str.length; i++) {  
  80.             System.out.println(str[i]);  
  81.         }  
  82.     }  
  83.   
  84.     /* 
  85.      * 获取某目录下的全部文件(包含子目录,完整路径,隐藏文件) 
  86.      */  
  87.     public static void getAllFile3(File file) {  
  88.         if (file != null) {  
  89.             if (file.isDirectory()) {  
  90.                 File[] fileArray = file.listFiles();  
  91.                 if (fileArray != null) {  
  92.                     for (int i = 0; i < fileArray.length; i++) {  
  93.                         // 递归调用  
  94.                         getAllFile3(fileArray[i]);  
  95.                     }  
  96.                 }  
  97.             } else {  
  98.                 System.out.println(file);  
  99.             }  
  100.         }  
  101.     }  
  102.   
  103.     /* 
  104.      * 遍历某目录下特定文件的文件名与路径 
  105.      */  
  106.     public static void getSpecificFile(File file, String suffix) {  
  107.         if (file != null) {  
  108.             if (file.isDirectory()) {  
  109.                 File[] fileArray = file.listFiles();  
  110.                 String name1 = file.getName();  
  111.                 System.out.println("——————" + name1);  
  112.                 if (fileArray != null) {  
  113.                     for (int i = 0; i < fileArray.length; i++) {  
  114.                         // 递归调用  
  115.                         getSpecificFile(fileArray[i], suffix);  
  116.                     }  
  117.                 }  
  118.             } else {  
  119.                 if (file.getName().toString().endsWith(suffix)) {  
  120.                     System.out.print("               ");  
  121.                     System.out.println(file  
  122.                             .getName()  
  123.                             .toString()  
  124.                             .substring(  
  125.                                     0,  
  126.                                     file.getName().toString().length()  
  127.                                             - suffix.length()));  
  128.                 }  
  129.             }  
  130.         }  
  131.     }  
  132.   
  133.     /** 
  134.      * 批量修改文件名: 
  135.      * @param filename 要是目录哦! 
  136.      */  
  137.     public static boolean changeFileNames(String fileName,String suffix)  
  138.     {  
  139.         File f = new File(fileName);  
  140.         if(!f.isDirectory())  
  141.         {  
  142.             return false;  
  143.         }  
  144.         int j = 0;  
  145.         File[] fs = f.listFiles();  
  146.         for(int i = 0;i < fs.length;i++)  
  147.         {  
  148.             String str = fs[i].getName();  
  149.             if(str.endsWith(suffix))  
  150.             {  
  151.                 fs[i].renameTo(new File(fileName + File.separator +"head" + j +suffix));  
  152. //              System.out.println(fileName + File.separator +"head" + j +suffix);  
  153.                 j++;  
  154.             }  
  155.         }  
  156.         return true;  
  157.     }  
  158. }  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值