1 File类
java.io.File 类,是文件和目录路径名的抽象表示形式,java把电脑中的文件和文件夹(目录)封装成为一个File类,可以使用File类的方法对文件/文件夹进行操作
一些静态变量
String pathSeparator和char pathSeparatorChar:与系统有关的的路径分隔符,Windows是分号,Linux是冒号String separator和char separatorChar:与系统有关的下级目录表示符,Windows是\,Linux是/注意:路径是不区分大小写的
1.1 构造方法
File(String pathName) 通过将给定路径字符串转换为抽象路径名来创建一个新File类实例
- 路径可以是以文件结尾,也可以是以文件夹结尾
- 路径可以是相对路径,也可以是绝对路径
- 路径可以存在,也可以不存在
- 创建File对象,只是把字符串路径封装为File对象,不考虑路径的存在性
File(String parent, String child) 根据 parent 和 child 路径名字符串创建一个新File类实例File(File parent, String child) 根据父路径和子路径字符串创建一个新File类实例
1.2 功能方法
获取
public String getAbsolutePath()public String getPath()返回路径字符串表示形式(原封不动,既非绝对 ,也非相对)public String getName()返回此File表示的文件或目录的名称(构造方法中的结尾部分)public long length()返回此File表示的文件的大小public boolean exists()判断文件或目录是否存在public boolean isDirectory()判断是否为目录public boolean isFile()判断是否为文件创建删除
public boolean createNewFile()当且仅当具有该文件的名称尚不存在时,创建一个新的空文件- 文件不存在,创建文件,返回true
- 文件存在,不会创建,返回false
public boolean delete()删除此File表示的文件或目录public boolean mkdir()创建由此File表示的目录(只能创建单级目录)- 文件夹不存在,创建文件夹,返回true
- 文件夹存在,则不会创建,返回false;构造方法中给出的路径若不存在,返回false
public boolean mkdirs()创建由此File表示的目录,包括任何必须但不存在的父目录遍历
public String[] list()返回一个表示该File目录中所有子目录或文件的字符串数组public File[] listFiles()返回一个表示该File目录中所有子目录或文件的File数组如果构造方法中给出的目录的路径不存在,或者构造方法给出的路径不是一个目录,都会抛出空指针异常
1.3 Filter
File类中有两个与
listFiles()重载的方法
FileFilter
public File[] listFiles(FileFilter filter)java.io.FileFilter 接口,用于过滤File对象
其中的抽象方法
boolean accept(File pathname)测试指定抽象路径名是否包含在某个路径列表中中,如果返回true,则将文件对象保存在文件数组中 ```java //需求:找到文件目录下所有java文件 import java.io.File; import java.io.FileFilter;
public class Demo03 { public static void main(String[] args) { File file = new File(“src”); getAllFiles(file); } public static void getAllFiles(File dir){ File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(“.java”); } }); for (File file : files) { if(file.isDirectory()){ getAllFiles(file); }else{ System.out.println(file); } } } }
<a name="2ImoT"></a>### FilenameFilter`public File[] listFiles(FilenameFilter filter)`<br />`java.io.FilenameFilter` 接口,用于过滤文件名<br />**其中的抽象方法**- `boolean accept(File dir, String name)` 测试指定文件是否应该包含在某一文件列表中```java//需求:找到文件目录下所有的java文件package File;import java.io.File;public class Demo04 {public static void main(String[] args) {File file = new File("src");getAllFiles(file);}private static void getAllFiles(File dir) {File[] files = dir.listFiles((File d, String pathname) -> {return new File(d, pathname).isDirectory() || pathname.toLowerCase().endsWith(".java");});for (File file : files) {if (file.isDirectory()) {getAllFiles(file);} else {System.out.println(file);}}}}
2 IO
2.1 概述
- 输入 :把硬盘中的数据, 读取 到内存中使用
- 输出 :把内存中的数据, 写入 到硬盘中保存
顶级父类
| 输入流 | 输出流 | |
|---|---|---|
| 字节流 | InputStream | OutputStream |
| 字符流 | Reader | Writer |
2.2 字节流
字节输出流OutputStream
1.常用方法
void close()关闭此输出流并释放与此流有关的所有系统资源void flush()刷新此输出流并强制写出所有缓冲的输出字节void write(byte[] b)将byte数组写入此输出流- 如果第一个字节是正数(0-127),则查询ASCII表
- 如果第一个字节是负数,则将其与之后相邻的字节组成一个中文显示,查询系统默认码表(GBK)
void write(byte[] b, int off, int len)将b中从off开始的len个字节写入此输出流void write(int b)将指定的字节写入此输出流- 如果写入数字在0-127之间,则查询ASCII表将其转化为字符
- 否则,查询系统默认码表(中文系统,GBK)
2.FileOutputStream
构造方法
FileOutputStream(String name)创建一个向具有指定名称的文件中写入数据的输出文件流FileOutputStream(File file)同上FileOutputStream(String name, boolean append)是否追加写FileOutputStream(File file, boolean append)是否追加写字节输入流InputStream
1.常用方法
void close()int available()返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的字节数int read()读取一个字节,每读取一个则将游标向后移一位,读取到文件末尾则返回-1int read(byte[] b)将读取的字节存在缓冲数组b中int read(byte[] b, int off, int len)
2.FileInputStream
构造方法
FileInputStream(String name)-
2.3 字符流
使用字节流读取中文字符时可能会产生显示不完全(乱码)问题 ,这是因为按照GBK编码两个字节组成一个中文字符,但是按照UTF-8编码是三个字节组成一个中文字符。
字符输入流Reader
1.常用方法
public void close()public int read()从输入流读取一个字符public int read(char[] cbuf)从输入流中读取一些字符,并将其存储在cbuf数组中
2.FileReader类
构造方法
FileReader(File file)FileReader(String fileName)-
字符输出流Writer
1.常用方法
void write(int c)写入单个字符(写入的是内存缓冲区,是一个字符转换为字节的过程,必须flush才能写入文件)void write(char[] cbuf)写入字符数组abstract void write(char[] int off, int len)写入字符数组的某一部分void write(String str)写入字符串void write(String str, int off, int len)写入字符串的某一部分void flush()刷新该流的缓冲,将字节写入文件void close()关闭此流,但要先刷新它
2.FileWriter类
构造方法
FileWriter(File file)FileWriter(String fileName)
3. flush()和close()的区别
flush刷新缓冲区,流对象可以继续使用-
2.4 流对象的异常处理
JDK1.7以前,非常麻烦
- 从JDK1.7开始,在try后面增加一个(),将流对象在其中定义,当try中代码执行完毕后,会自动把流对象释放,而不用再写fianlly ```java package Stream;
import java.io.FileReader; import java.io.IOException;
public class Demo06 { public static void main(String[] args) { try (FileReader fw = new FileReader(“src/Stream/Hello.txt”);) { int c = fw.read(); } catch (IOException e) { e.printStackTrace(); } System.out.println(“Test done.”); } }
<a name="SEY37"></a># 2.5 Properties> 唯一一个与IO流相结合的集合,该类表示了一个持久的属性流,可保存在流中或从流中加载Properties集合是一个双列集合(继承自Hashtable),key和value默认都是字符串,常用方法有- `Object setProperty(String key, String value)`- `String getProperty(String key)`- `Set<String> stringPropertyNames()`- `void store(OutputStream out, String comments)` 把集合中的数据持久化写入到硬盘中存储- `void store(Writer writer, String comments)` 注释 `comments` 不能使用中文- `void load(InputStream inStream)` 把硬盘中保存的数据读取到内存中使用- `void load(Reader reader)`<a name="pj6Hp"></a># 2.6 缓冲流给基本的输入输出流增加一个缓冲区,提高读写效率<a name="kILHZ"></a>### BufferedOutputStream构造方法- `BufferedOutputStream(OutputStream out)`- `BufferedOutputStream(OutputStream out, int size)````javaimport java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.charset.StandardCharsets;public class Demo09 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("src/Stream/buffered.txt");BufferedOutputStream bos = new BufferedOutputStream(fos);bos.write("我是写入缓冲区的字符串".getBytes(StandardCharsets.UTF_8));bos.flush();bos.close();}}
BufferedInputStream
构造方法
BufferedIutputStream(InputStream in)BufferedIutputStream(InputStream in, int size)```java import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException;
public class Demo10 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream(“src/Stream/buffered01.txt”); BufferedInputStream bis = new BufferedInputStream(fis, 2); int len = 0; while((len=bis.read())!=-1){ System.out.print((char)len);; } bis.close(); } }
<a name="UQLRN"></a>### BufferedWriter构造方法- `BufferedWriter(Writer out)`- `BufferedWriter(Writer out, int size)`特有方法- `void newline()` 写入换行符<a name="sZSqy"></a>### BufferedReader构造方法- `BufferedReader(Reader reader)`- `BufferedReader(Reader reader, int size)`特有方法- `String readLine()` 读取一行文本内容,若读到文本结尾,则返回null<a name="BX2U8"></a># 3 转换流<a name="IuvAH"></a>## 3.1 常见的编码方式- ASCII- GBxxx- GB2312- GBK- GB18030- Unicode- UTF-8- UTF-16- UTF-32<a name="BmA5b"></a>## 3.2 转换流的方式<a name="LtB8a"></a>### InputStreamReader是字节流通向字符流的桥梁,可以指定charset对字节流进行解码- `InputStreamReader(InputStream in)`- `InputStreamReader(InputStream in, String charSetName)````javaimport java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;public class Demo12 {public static void main(String[] args) throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream("src/Stream/gbk.txt"),"gbk");int len = 0;while((len=isr.read())!=-1){System.out.print((char)len);}isr.close();}}
OutputStreamWriter
FileWriter 只能使用IDE默认码表写入,而 OutputStreamWriter 则可以使用指定charset进行写入
OutputStreamWriter(OutputStream out)创建使用默认编码的输出流OutputStreamWriter(OutputStream out, String charSetName)创建使用指定编码的输出流 ```java import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter;
public class Demo11 { public static void main(String[] args) throws IOException { write_gbk(); }
private static void write_gbk() throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src/Stream/gbk.txt"),"gbk");osw.write("你好,世界");osw.flush();}
}
<a name="shi"></a>### 练习:实现文件转码```javapackage Stream;import java.io.*;public class Demo13 {public static void main(String[] args) throws IOException {String fileName = "src/Stream/gbk.txt";convert_to_utf8(fileName);}private static void convert_to_utf8(String fileName) throws IOException {InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "gbk");OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName.replace("gbk", "utf8")), "utf8");int len = 0;while ((len = isr.read()) != -1) {osw.write(len);}isr.close();osw.close();}}
3.3 序列化与反序列化
先定义一个Perosn类
package Stream;import java.io.Serializable;public class Person implements Serializable {private String name;private int age;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Person(String name, int age) {this.name = name;this.age = age;}}
ObjectOutputStream
对象的序列化流 , 类通过实现 java.io.Serializable 接口以启用其序列化功能,可序列化类的所有子类都是可序列化的,序列化接口没有方法或字段,仅用于标识可序列化的语义
构造方法ObjectOutputStream(OutputStream out)
特有的成员方法void writeObject(Object obj)
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;public class Demo14 {private static java.io.OutputStream OutputStream;public static void main(String[] args) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/Stream/persons.txt"));Person p1 = new Person("小石头", 18);oos.writeObject(p1);}}
ObjectInputStream
对象的反序列化流
构造方法ObjectInputStream(InputStream in)
特有的成员方法Object readObject()
package Stream;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Demo15 {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/Stream/persons.txt"));Object obj = ois.readObject();System.out.println(obj);}}
transient(瞬态)关键字
- static关键字所修饰的内容优先于对象加载到内存中,所以不能被序列化
transient关键字所修饰的内容也不可被序列化,但并不包含static的含义
InvalidClassException
编译器(javac)会把Person.java文件编译生成Person.class,由于Person类实现了
Serializable接口,因此会根据类的定义给Person.class添加一个序列号- 反序列化时,会使用Person.class文件中的序列号和persons.txt中的序列号做比较,如果一致,则反序列化成功,若不一致,则抛出
InvalidClassException异常
问题产生的原因:每一次给类修改定义,都会重新给类生成一个序列号
解决问题的办法:为类手动指定序列号,使用以下格式private static final long serialVersionUID = 1L;
序列化集合
当想要序列化多个对象时,可以将对象保存到集合中,对集合进行序列化和反序列化
序列化
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.util.ArrayList;public class Demo16 {public static void main(String[] args) throws IOException {ArrayList<Person> list = new ArrayList<>();ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/Stream/persons.txt"));list.add(new Person("张三", 18));list.add(new Person("李四", 28));list.add(new Person("王五", 38));list.add(new Person("赵六", 48));oos.writeObject(list);oos.close();}}
反序列化
import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class Demo17 {public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/Stream/persons.txt"));Object obj = ois.readObject();System.out.println(obj);}}
3.4 打印流PrintStream
1.PrintStream的特点
- 只能输出数据,不能读取数据
- 永远不会抛出IO异常
- 有特有的方法
printprintln
2.构造方法
PrintStream(File file)输出的目的地是一个文件PrintStream(OutputStream out)输出目的地是一个字节输出流PrintStream(String fileName)输出目的地是一个文件路径
3.注意事项
- 如果使用继承自父类的
write方法写数据,那么查看数据的时候会查询码表 97->a - 如果使用自己特有的方法print/println写数据,则会写入原始数据 97->97
- 使用
System.setOut(PrintStream out)方法改变输出语句的目的地为参数传递的打印流的目的地import java.io.FileNotFoundException;import java.io.PrintStream;import java.io.File;public class Demo18 {public static void main(String[] args) throws FileNotFoundException {PrintStream ps = new PrintStream(new File("src/Stream/printstream.txt"));ps.println("我是爱南开的。");ps.close();}}
