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)`
```java
import 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)`
```java
import 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>
### 练习:实现文件转码
```java
package 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;
@Override
public 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异常
- 有特有的方法
print
println
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();
}
}