文件 IO流


  • 文件类File
  1. 相对路径
  2. 绝对路径

File对象既可以代表文件也可以代表文件夹

1 File file = new File("d:\\bingtu.txt");

判断文件是否存在

  • exists()
1 boolean b = file.exists();

创建文件

  • createNewFile()
1 file1.createNewFile();

创建文件夹

  • mkdir
  • mkdirs
1             //mkdir只能创建当前文件夹,如果父级目录不存在,则会创建失败
2             file2.mkdir();
3             //mkdirs可以创建文件夹
4             file2.mkdirs();

删除文件

删除文件夹,如果文件夹里面有东西就会删除失败

  • delete()
1 file2.delete();

判断是文件还是文件夹

  • isFile()
  • isDirectory()
1         file.isFile();//判文件
2         file.isDirectory();//判文件夹

获取子元素

  • listFiles()
 1     public boolean clearDir(String name) {
 2         File file = new File(name);
 3         if(file.exists() && file.isDirectory()) {
 4             File[] arr = file.listFiles();
 5             for(File f:arr) {
 6                 f.delete();
 7             }
 8         }
 9         return true;
10     }

重命名

  • renameTo()
1 file1.renameTo(new File("d:\\aaa\\txt"));

getName  getPath  getParent

  • IO

I/O , 输入流 , /输出流事项对程序来说

每次从文件中读4个字节然后打印输出.

 1         FileInputStream fis =new FileInputStream("d:\\aaa\\txt1.txt");//abcdefghifk
 2         byte[] arr = new byte[4];
 3         int count = 0;
 4         fis.read(arr);
 5         System.out.println(new String(arr));//abcd
 6         fis.read(arr);
 7         System.out.println(new String(arr));//edgh
 8         fis.read(arr);
 9         System.out.println(new String(arr));//igkh
10         fis.read(arr);
11         System.out.println(new String(arr));//igkh

声明的arr , 相当于一个小推车.大小为4,每次都从文件中装人4个字符,然后打印出来.

问题就在这里,每次装入一个新东西的时候,都会从里面拿出来一个和他进行置换.

那么,如果文件中的元素都被复制出来了呢?

例如上面的例子,我们文件中的字母到k就已经结束了,第10行的代码所以已经没什么东西在装了,打印出来的还是上一次数组中存的东西,

还有一点就是说,你看看第9行的代码,我们文件的最后一个元素时k.故上一次放在小推车里面的h并没有被置换出去.

也就是说:

1         //会出现重复的内容例如igkh
2         //abcd
3         //efgh
4         //igkh
5         while((count = fis.read(arr)) != -1) {
6             System.out.println(new String(arr));
7         }

这里是用了一个count对他进行记录.

当read()完的时候会返回-1.

难道我们就没有什么办法了吗?

答案是否定的

请看

1         //用0把没读的覆盖掉例如igk
2         //abcd
3         //efgh
4         //igk
5         while((count = fis.read(arr)) != -1) {
6             System.out.println(new String(arr , 0 , count));
7         }

new String(arr , 0 , count)

这句话我差了一段时间才理解的,它的方法定义是这么写的

1 String(char value[], int offset, int count)

也就是说声明了一个数组values,从offset(开端)到count(结尾)

声明了这么大的一个String

这有什么用呢,也就是说我这么写就可以每次记录count输出了几个字符,然后避免掉上次输出的元素这次还会输出的情况.

同时我还写了以下几个方法

文件的复制

 1 //从src 读一个文件,写入到 dest
 2     static void copy(String src , String dest) throws FileNotFoundException {
 3         long l1 = System.currentTimeMillis();
 4         File f_src = new File(src);
 5         File f_dest = new File(dest);
 6         if(!f_src.exists()) {
 7             throw new FileNotFoundException("找不到源文件");
 8         }
 9         if(!f_dest.exists()) {
10             try {
11                 f_dest.createNewFile();
12             } catch (IOException e) {
13                 // TODO Auto-generated catch block
14                 e.printStackTrace();
15             }
16         }
17         
18         FileInputStream fis = null;//字符流
19         BufferedInputStream bis = null;
20         FileOutputStream fos = null;
21         BufferedOutputStream bos = null;
22         try {
23             //buffer的大小是8k
24             //Buffer嵌套字符流
25             fis = new FileInputStream(src);
26             bis = new BufferedInputStream(fis);//缓存输入流
27             
28             fos = new FileOutputStream(dest);
29             bos = new BufferedOutputStream(fos);
30             
31             byte[] arr = new byte[1024*2];//声明了大小为2k的小车车装数据
32             
33             int count = 0;//每次读取多少个字节,返回字节数 , 如果读完了就会返回-1
34             //文件大小480076KB
35             //用字符流用时 3823ms
36             //嵌套上Buffer用时 3143ms
37             //....这好像看不出来啥
38             //其实如文件非常大的话,应该套上Buffer用时能到字符流用时的一半
39             while((count = bis.read(arr))!=-1) {
40                 fos.write(arr , 0 , count);//每次把count大小的数据写进去
41             }
42         } catch (IOException e) {
43             e.printStackTrace();
44         } finally {
45             try {
46                 if(fis != null) {
47                     fis.close();
48                 }
49                 if(fos != null) {
50                     fos.close();
51                 }
52             } catch (IOException e) {
53                 e.printStackTrace();
54             }
55         }
56         
57         long l2 = System.currentTimeMillis();
58         System.out.println(l2 - l1);
59     }

其中用到了

System.currentTimeMillis();

这个方法在代码块的一开始写上,记录当前时间

这么方法从程序开始设定为默认值从1970年开始,然后到代码块末未结束,再记录一下

然后这两个数相减,就能知道整个程序跑了多久.

这里我们还用到了Buffer

Buffer嵌套字符流

因为FileInputStream是一个字符流的输入(上面有一个图对它进行描述)这么频繁的一个字符一个字符的调用势必会对性能产生很大的影响

因此我们有了BufferedInputStream,这样的话每次Buffer填满的时候一次性的操作完,就很节省时间

Buffer的大小是8k

上面的代码我们测试了使用Buffer和不使用的时间差距,我们发现套上buffer会更快

文件大小480076KB

用字符流用时 3823ms

嵌套上Buffer用时 3143ms

....这好像看不出来啥

其实如文件非常大的话,应该套上Buffer用时能到字符流用时的一半

输出

 1     static void output() {
 2         FileOutputStream fos = null;
 3         try {
 4             fos = new FileOutputStream("d:\\aaa\\txt1.txt", true);
 5             String str = "********";
 6             byte[] arr = str.getBytes();
 7             fos.write(arr);
 8         } catch (FileNotFoundException e) {
 9             e.printStackTrace();
10         } catch (IOException e) {
11             e.printStackTrace();
12         } finally {
13             try {
14                 if (fos != null) {
15                     fos.close();
16                 }
17             } catch (IOException e) {
18                 // TODO Auto-generated catch block
19                 e.printStackTrace();
20             }
21         }
22     }

输入

1     void input() throws Exception {
2         FileInputStream fis = new FileInputStream("d:\\aaa\\txt1.txt");
3         int count = 0;
4         byte[] arr = new byte[4];
5         while ((count = fis.read(arr)) != -1) {
6             System.out.println(new String(arr, 0, count));
7         }
8         fis.close();
9     }

小例子:

使用Object的方法输入输出

 1 package day09;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.FileOutputStream;
 5 import java.io.ObjectInputStream;
 6 import java.io.ObjectOutputStream;
 7 
 8 public class test {
 9     public static void main(String[] args) throws Exception {
10         w();
11         r();
12     }
13     
14     static void r() throws Exception {
15         FileInputStream fis = new FileInputStream("d:\\aaa\\txt\\txt.txt");
16         ObjectInputStream ois = new ObjectInputStream(fis);
17         Cup cup = (Cup)ois.readObject();
18         System.out.println(cup);
19         fis.close();
20         ois.close();
21     }
22     
23 
24     static void w() throws Exception {
25         Cup cup = new Cup("red", 33);
26         FileOutputStream fos = null;
27         ObjectOutputStream oos = null;
28         try {
29             fos = new FileOutputStream("d:\\aaa\\txt\\txt.txt");
30             oos = new ObjectOutputStream(fos);
31             oos.writeObject(cup);
32             oos.flush();
33         }catch (Exception e) {
34             e.printStackTrace();
35         } finally {
36             fos.close();
37             oos.close();
38         }
39     }
40 }
 1 package day09;
 2 
 3 import java.io.Serializable;
 4 
 5     public class Cup implements Serializable{
 6     
 7     private String color;
 8     
 9     private int price;
10 
11     public Cup(String color , int price) {
12         // TODO Auto-generated constructor stub
13         this.color = color;
14         this.price = price;
15     }
16 }
  • transient(不可被序列化)

name加了transient防止被序列化,就是说往出传的时候,会检查他的serialVersionUID,不匹配就不会传

P因为没有序列化,所以抛出来了异常