File、IO流体系
第十六天
File、IO流体系
1.File类型
在程序中,我们使用java.io.File这个类来描述和操作磁盘上的一个文件或文件夹(目录)。
File这个类,能新建、删除、移动,重命名文件或文件夹,也能获取或者修改文件或文件夹的信息(如大小,修改时间等),但File不能访问文件里的内容。如果需要访问文件里的内容,则需要使用输入/输出流
2.路径
1)绝对路径(Absolute Path):
从磁盘的根目录开始,一层层的向内查找,直到找到这个文件。在不同的操作系统中,根目录的表示方式可能略有不同。例如:
在Unix和Linux系统中,根目录用斜杠(/)表示,如
/home/user/file.txt
;而在Windows系统中,根目录用驱动器名和冒号表示,如
C:\Users\User\file.txt
。
2)相对路径(Relative Path):
是相对于当前工作目录或另一个已知位置的路径。它描述的是文件或目录与当前位置之间的相对关系。相对路径通常省略了根目录部分,直接从当前目录开始描述路径。例如,假设当前工作目录是/home/user,要访问该目录下的文件file.txt,可以使用相对路径file.txt,而不需要写出完整的绝对路径。
./ : 表示当前工作目录。 ./可以省略 ../ : 表示返回到上一层目录
关于目录分隔符,在不同的操作系统中,不一样。在windows中,使用 \ 作为目录分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 / 作为目录分隔符。
关于路径分隔符,在不同的操作系统中,不一样。在windows中,使用 ; 作为路径分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 : 作为路径分隔符。
小贴士:虽然,在windows中,使用 \ 作为目录分隔符,但是大部分情况下,使用 / 也可以。
而File的静态常量会获取程序所在的系统环境中的具体分隔符。这样就省去了程序员来区分不同操作系统的麻烦。
System.out.println(File.separator);// 目录分隔符,用来分隔两个目录,返回一个 字符串 System.out.println(File.separatorChar);// 目录分隔符,用来分隔两个目录,返回一个字符 System.out.println(File.pathSeparator);// 路径分隔符,用来分隔两个路径,返回一个字符串 System.out.println(File.pathSeparatorChar);// 路径分隔符,用来分隔两个路径,返回一个字符
3.常用构造器
1 | File(String pathname) | 通过将指定字符串转换成抽象路径名来创建一个File实例 |
---|---|---|
2 | File(File parent,String child) | 从父抽象路径名和子路径名字符串创建新的 File实例。 |
3 | File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File实例。 |
4.常用方法
1 | String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
---|---|---|
2 | String getPath() | 将此抽象路径名转换为路径名字符串 |
3 | File getAbsoluteFile() | 返回此抽象路径名的绝对形式。 |
4 | String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串。 |
5 | String getParent() | 返回此抽象路径名的父路径名字符串,如果此路径名未指定父目录,则返回null。 |
6 | boolean renameTo(File newName) | 重命名由此抽象路径名表示的文件。 |
7 | boolean exists() | 测试此抽象路径名表示的文件或目录是否存在 |
8 | boolean canWrite() | 测试应用程序是否可以修改由此抽象路径名表示的文件 |
9 | boolean canRead() | 测试应用程序是否可以读取由此抽象路径名表示的文件 |
10 | boolean isFile() | 测试此抽象路径名表示的文件是否为普通文件 |
11 | boolean isDirectory() | 测试此抽象路径名表示的文件是否为目录 |
12 | long lastModify() | 返回此抽象路径名表示的文件上次修改的时间 |
13 | long length() | 返回由此抽象路径名表示的文件的长度 |
查询相关API
1 | String[] list() | 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录 |
---|---|---|
2 | String[] list(FilenameFilter filter) | 返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录 |
3 | File[] listFiles() | 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件 |
创建与删除API
1 | boolean createNewFile() | 当且仅当具有该名称的文件尚不存在时,创建一个由该抽象路径名命名的新的空文件 |
---|---|---|
2 | boolean mkdir() | 创建由此抽象路径名命名的目录 |
3 | boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。 |
4 | boolean delete() | 删除由此抽象路径名表示的文件或目录。注意,删除目录时,必须保证此目录下是空目录,如果目录不是空的,需要先删除里面的东西,再删除目录。 还有一点是,删除是永久删除,不会进入回收站 |
File file = new File("D:\\test\\01"); if (!file.exists()){file.mkdirs(); } File file1 = new File(file, "a.txt"); if (!file1.exists()){file1.createNewFile(); }
File f1 = new File("D:\\youcai10\\周考2.txt");System.out.println("文件名:"+f1.getName());System.out.println("文件路径:"+f1.getPath());System.out.println("绝对路径File形式:"+f1.getAbsoluteFile());System.out.println("绝对路径String形式:"+f1.getAbsolutePath());System.out.println("父路径:"+f1.getParent());System.out.println("是否存在:"+f1.exists());System.out.println("是可读文件吗?"+f1.canRead());System.out.println("是可写文件吗?"+f1.canWrite());System.out.println("是可执行文件吗?"+f1.canExecute());System.out.println("是文件吗?"+f1.isFile());System.out.println("是文件夹吗?"+f1.isDirectory());System.out.println("是隐藏的吗?"+f1.isHidden());System.out.println("最后一次修改时间:"+f1.lastModified());//重命名//f1.renameTo(new File("D:\\youcai10\\周考2.txt"));//重命名方法:有移动的作用。f1.renameTo(new File("D:\\youcai10\\周考3.txt"));System.out.println(f1.getName());
1.IO流基础
我们在编程时,除了自身定义一些数据信息外,经常还会引入外界的数据,或者是将自身的数据发送给外界。如:编程时,想读取硬盘上的某一个文件,又或者想将程序中的某些数据写入到硬盘上的一个文件里。这时,我们就要使用IO流(Input Output Stream)。
这个“外部”范围很广,包括诸如键盘、显示器、文件、磁盘、网络、另外一个程序等。“数据”也可以是任何类型的,例如一个对象、字符串、图像、声音等
Input(输入):是指数据流入程序,通常我们读取外界数据时使用,所以输入是用来读取数据的。
Output(输出):是指数据从程序流出,通常我们需要写出数据到外界时使用,所以输出是用来写出数据的
一个流就是一个从数据源向目的地的数据序列
I/O流类一旦被创建就会自动打开
通过调用close方法,可以显式关闭任何一个流,如果流对象不再被引用,Java的垃圾回收机制也会隐式地关闭它
不论数据从哪来,到哪去,也不论数据本身是何类型,读写数据的方法大体上都是一样的
2.io流的分类
IO流体系中,我们如果按照数据的流向分类,可以分为如下两类:输入流和输出流**。**
如果按照处理数据的单位分类:字节流 和 字符流。
如果按照流的功能分类,可以分为 节点流 和 处理流。
节点流:可以从一个特定的IO设备上读/写数据的流。也称之为低级流
处理流:是对一个已经存在的流的连接和封装,通过所封装的流的功能调用实现数据读/写操作。通常处理流的构造器上都会带有一个其他流的参数。也称之为高级流或者过滤流
字节流(InputStream,OutputStream)
3.1文件流 (FileInputStream,FileOutputStream)
3.2缓冲流 (BufferInputStream,BufferOutputStream)
3.3对象流 (ObjectInputStream,ObjectrOutputStream)
3.4数据流 (DateInputStream,DateOutputStream)
3.1文件流 (FileInputStream,FileOutputStream)
3.1.1FileOutputStream(中文汉字乱码)
FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\test\\01\\z.txt")); fileOutputStream.write((int) 'A'); byte[] bytes = "我爱你中国".getBytes(); fileOutputStream.write(bytes); byte[] bytes1 = new byte[10]; for (int i = 0; i < bytes1.length; i++) {bytes1[i] = (byte) ('0' + i); // 写入 '0' 到 '9' } fileOutputStream.write(bytes1, 0, 7); // 写入 '0' 到 '6'
3.1.2FileInputStream(中文汉字乱码)
FileInputStream fileInputStream = new FileInputStream(new File("D:\\test\\01\\z.txt")); int read = fileInputStream.read(); System.out.println((char) read); int read1 = fileInputStream.read(); System.out.println((char) read1); System.out.println("------------------------------------------------"); byte[] bytes = new byte[10]; int read2 = fileInputStream.read(bytes); if (read2!=-1){System.out.println(new String(bytes,0,read2)); } System.out.println("------------------------------------------------"); int read3 = fileInputStream.read(bytes, 0, 9); System.out.println(new String(bytes,0,read3)); while ((read2=fileInputStream.read(bytes))!=-1){System.out.println(new String(bytes,0,read2)); }
3.2.1BufferOutputStream(中文汉字乱码) bufferedOutputStream.close()必须关闭
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("D:\\test\\01\\z.txt"))); bufferedOutputStream.write('q'); bufferedOutputStream.write("我爱你中国".getBytes()); bufferedOutputStream.write("werwerer".getBytes(),1,3); bufferedOutputStream.close();
3.2.2BufferInputStream(中文汉字乱码)
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\test\\01\\z.txt")); int read = bufferedInputStream.read(); System.out.println((char) read); byte[] bytes = new byte[10]; int read1 = bufferedInputStream.read(bytes); System.out.println(new String(bytes,0,read1)); while ((read1=bufferedInputStream.read(bytes))!=-1){System.out.println(new String(bytes,0,read1)); }
3.3.1对象流 ObjectrOutputStream
常用构造器
ObjectOutputStream(OutputStream os)
ObjectInputStream(InputStream is)
Serializable接口
ObjectOutputStream在对对象进行序列化时有一个要求,就是需要对象所属的类型必须实现Serializable接口。此接口内什么都没有,只是作为可序列化的标识。
serailVersionUID
通常实现序列化接口的类需要提供一个常量serialVersionUID,表明该类的版本。若不显示的声明,在该对象序列化时也会根据当前类的各个方面计算该类的默认serialVersionUID。但是不同平台的编译器实现有所不同,所以想要跨平台,都应该显示的声明版本号。
如果类的对象序列化存入硬盘上面,之后随着需求的变化更改了类的属性(增加或减少或改名等),那么当反序列化时,就会出现异常(InvalidClassException),这样就造成了不兼容性的问题。
但当serialVersionUID相同时,就会将不一样的field以type的预设值反序列化,避免不兼容问题。
transient关键字
对象在序列化后得到的字节序列往往比较大,有时候我们在对一个对象序列化操作时,可以忽略某些不必要的属性,从而对序列化后得到的字节序列“瘦身”。
使用transient关键字修饰的属性在序列化时其值将被忽略
3.3.1对象流 ObjectrOutputStream
3.3.2对象流 ObjectrinputStream
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\test\\01\\v.txt")); objectOutputStream.writeObject(new Person(12,"sdasd")); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\test\\01\\v.txt")); Object o = objectInputStream.readObject(); System.out.println(o);
class Person implements Serializable{ private static final long serialVersionUID = 1231238126946189L; public Person(int age, String name) {this.age = age;this.name = name;} int age;String name; @Overridepublic String toString() {return "Person{" +"age=" + age +", name='" + name + '\'' +'}';} }
3.4,1数据流 (DateInputStream,DateOutputStream)
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("D:\\test\\01\\x.txt")); dataOutputStream.writeUTF("wdwdawda"); DataInputStream dataInputStream = new DataInputStream(new FileInputStream("D:\\test\\01\\x.txt")); String s = dataInputStream.readUTF(); System.out.println(s);