1.File与IO流
File: 文件目录经名的抽象表示
路径分隔符可以使用\\,/,//,但是再系统目录中默认使用\表示路径分割
File与IO流的的区别:
File只是对于文件外部的操作,对于文件和的文件夹的创建但是不能读取文件内容或者向文件写入内容。
IO流:数据的读入写出,文件的上传下载
流:一连串流动的数据,已先入先出的方式进行传输-->流就是管道
数据源------>io-------->目的地
流的分类:
操作单元分:
字节流:万能流 (字节是目前计算机最基本的存储单位,所以可以处理一切数据)
字符流:纯文本内容 (对于文本内容的一个扩展,使用字符流处理文本内容)
流向分:以程序为中心
输入流
输出流
功能流:
节点流:真实能做读入写出的
功能流:增强节点流的功能,提高节点流的性能
字符缓冲流 数据流 对象流
流之间的分类是相辅相成的
2.字节流
InputStream 字节输入流中最上层父类
文件流 : FileInputStream 文件字节输入流->节点流 字节流 输入流
操作文件,数据源为文件,使用文件字节输入流
字节数组流 : ByteArrayInputStream 字节数组输入流 ->节点流 字节流 输入流
操作字节数组,数据源是字节输入,使用字节数组输入流OutputStream 字节流输出流
FileOutputStream 文件字节输出流 -> 节点流
目的地为文件
ByteArrayOutputStream 字节数组输出流 -> 节点流
目的地为字节数组在输出流写出的时候,如果目的地文件不存在,系统会自动创建目的地文件,如果目的地文件所在路径不存在,抛出异常java.io.FileNotFoundException:(系统找不到指定的路径。)
FileInputStream
//创建对象两种形式
//1. 通过文件的形式
InputStream inputStream = new FileInputStream(new File("g:/a.txt"));
//2. 通过文件地址的形式
InputStream inputStream2 = new FileInputStream("g:/a.txt");
//读入内容 3种
//1.一个个读取
/* System.out.println((char)inputStream.read());
System.out.println((char)inputStream.read());
System.out.println((char)inputStream.read());
System.out.println(inputStream.read());*/
//2.使用循环
/* int num = 0;
while((num=inputStream.read())!=-1){
System.out.println((char)num);
}*/
//3.使用字节数组 避免一个个读取 性能低
/* byte[] b = new byte[1024];
int len = 0; //返回读取到到的长度
while ((len=inputStream.read(b))!=-1){
System.out.println(new String(b,0,len));
}*/
//4.byte[] readAllBytes() 从输入流中读取所有剩余字节。
byte[] arr = inputStream.readAllBytes();
System.out.println(new String(arr));
//关闭
inputStream.close();
FileOutputStream
//1.构建流,指定目的地
//FileOutputStream(String name)
//OutputStream os = new FileOutputStream("D://test.txt"); //默认覆盖原文件中内容
OutputStream os = new FileOutputStream("g://test2.txt",true); //boolean参数->true为追加 false为覆盖
//2.写出
os.write(97);
byte[] arr = "你好再见".getBytes();
os.write(arr);
//3.刷出
os.flush();
//4.关闭
os.close();
3.字符流
字符流 (纯文本数据)
Reader 字符输入流
FileReader 文件字符输入流 ->节点流
Writer 字符输出流
FileWriter 文件字符输出流 ->节点流
通过字符流实现文件拷贝
//构建流
Reader rd = new FileReader("g://如何学习.txt");
Writer rt = new FileWriter("g://dest.txt");
//读写
//读入 int read() 每次读入一个字符数据
//读入 int read(char[] cbuf) 将字符读入数组。返回读取的字符数,如果已到达流的末尾,则返回-1
char[] car = new char[1024];
int len = -1;
while ((len = rd.read(car)) != -1){
//void write(char[] cbuf) 写一个字符数组。
//void write(char[] cbuf, int off, int len) 写一个字符数组的一部分。
//void write(int c) 写一个字符。
//void write(String str) 写一个字符串。
//void write(String str, int off, int len) 写一个字符串的一部分。
rt.write(car,0,len);
}
//刷出
rt.flush();
//关闭
rt.close();
rd.close();
4.功能流
字节缓冲流
功能流 : 使用:包裹节点流使用
缓冲流 Buffered : 加快节点流的读写效率
字节缓冲流 :
字节输入缓冲流 BufferedInputStream
字节输出缓冲流 BufferedOutputStream
无新增方法,可以发生多态
字符缓冲流
//1.构建流
InputStream is = new BufferedInputStream(new FileInputStream("D://test.txt"));
OutputStream os = new BufferedOutputStream(new FileOutputStream("D://test1.txt"));
//2.读入写出
byte[] car = new byte[1024];
int len = -1;
while((len = is.read(car))!=-1){
os.write(car,0,len);
}
//3.刷出
os.flush();
//4.关闭
os.close();
is.close();
字符缓冲流
字符流缓冲流
字符输入缓冲流 BufferedReader
新增功能: String readLine() 读一行文字。
字符输出缓冲流 BufferedWriter
新增功能: void newLine() 写一个行分隔符。存在新增功能,不能发生多态
//1.构建流(输入,输出)
BufferedReader rd = new BufferedReader(new FileReader("D://test.txt"));
BufferedWriter rt = new BufferedWriter(new FileWriter("D://dest.txt"));
//2.读写
String msg = null;
while((msg=rd.readLine())!=null){
rt.write(msg);
//rt.newLine(); //换行符
}
//3.刷出
rt.flush();
//4.关闭
rt.close();
rd.close();
数据流
功能流 :
Data流 | 基本数据类型流 : 读写数据+保留数据类型->基本数据类型|字符串
是字节流的功能流
DataInputStream Data输入流
新增功能 : readXxx()
DataOuutputStream Data输出流
新增功能 : writeXxx()注意: 读入与写出的顺序保持一致
读入数据的时候必须从源文件中读入,否则抛出异常 java.io.EOFException
public static void main(String[] args) throws IOException {
write("g:/b.txt");
read("g:/b.txt");
}
//写出
public static void write(String path) throws IOException {
//构建输出流
DataOutputStream ds = new DataOutputStream(new FileOutputStream(path));
//准备数据
int i = 100;
char ch = 'a';
boolean flag = false;
String str = "哈哈";
//3.写出
ds.writeInt(i);
ds.writeChar(ch);
ds.writeBoolean(flag);
ds.writeUTF(str);
//4.刷出
ds.flush();
//5.关闭
ds.close();
}
//读入
public static void read(String path) throws IOException {
//1.构建输入流
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
int i = is.readInt();
char ch = is.readChar();
boolean flag = is.readBoolean();
String msg = is.readUTF();
//3.处理数据
System.out.println(i);
System.out.println(ch);
System.out.println(flag);
System.out.println(msg);
//4.关闭
is.close();
}
对象流
Object流|对象流 | 引用数据类型
字节流的功能流
ObjectInputStream 反序列化输入流
新增方法 Object readObject() 从ObjectInputStream中读取一个对象。 等等
ObjectOutputStream 序列化输出流
新增方法 void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。序列化:将对象数据转为可存储后者可传输的状态的过程
不是所有类型的数据都能序列化 java.io.Serializable
如果写出的对象类型没有实现序列化接口,会遇到运行时异常 java.io.NotSerializableException
序列化与反序列化顺序保持一致
不是所有的属性都需要序列化 transient
static的成员不会被序列化
如果父类实现类序列化接口,子类所有内容都可以进行序列化
子类实现了序列化接口,只能序列化子类独有的内容序列号: 当实现了序列化的类型默认存在一个序列号
当类中的成员发生改变,序列号默认会重新生成
作用: 使用序列号可以实现检查前后版本不一致问题java.io.InvalidClassException异常
解决不同版本的兼容问题: 手动设置序列号
通过快捷键生成序列号:
1.类型必须实现了序列化接口
2.Setting中进行配置
3.双击类名alt+enter,自动生成序列号
public static void main(String[] args) throws Exception {
// testWrite("g://heihei.txt");
testRead("g://heihei.txt");
}
private static void testRead(String path) throws Exception {
ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
Person p = (Person)is.readObject();
int[] arr = (int[]) is.readObject();
//3.处理数据
System.out.println(p);
System.out.println(Arrays.toString(arr));
//4.关闭
is.close();
}
private static void testWrite(String path) throws Exception {
//1.定义输出流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(path));
//2.准备数据
Person p = new Person("张三",18);
p.a = 10;
int[] arr = {1,2,3,4,5};
//3.写出
os.writeObject(p);
os.writeObject(arr);
//4.刷出
os.flush();
//5.关闭
os.close();
p.a = 100;
}
}
class Person implements Serializable {
private static final long serialVersionUID = -3362400290433691785L;
private String name;
private transient int age;
public static int a ;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
",a="+a+
'}';
}
}
6.CommonsIo
/*
CommonsIO 是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等。
是一个第三方的开源组件
使用第三方组件的步骤:
1.对应官网中下载源码 jar
2.在项目下新建一个文件夹目录lib,lib下存放以后项目所依赖的所有jar包
3.选中jar包,右键add as lib...
4.在项目下对应类中进行使用
*/
public class Class001_CommonsIO {
public static void main(String[] args) throws IOException {
//#### IO工具类IOUtils
//`IOUtils.copy(InputStream input, OutputStream output) `// 此方法有多个重载方法,满足不同的输入输出流
IOUtils.copy(new FileInputStream("D://test.txt"),new FileOutputStream("D://xixi.txt"));
//IO 工具类 FilenameUtils
//`FilenameUtils.getBaseName(String filename)` // 去除目录和后缀后的文件名
System.out.println(FilenameUtils.getBaseName("D://test.txt"));
//`FilenameUtils.getExtension(String filename)` // 获取文件的后缀
System.out.println(FilenameUtils.getExtension("D://logo.png"));
//`isExtension(String fileName, String text) `// 判断fileName是否是text后缀名
System.out.println(FilenameUtils.isExtension("D://logo.jpg","png"));
//IO 工具类 FileUtils
//`FileUtils.copyFile(File srcFile, File destFile)` // 复制文件
FileUtils.copyFile(new File("D://test.txt"), FileUtils.getFile("D://hehe.txt"));
//`FileUtils.copyFileToDirectory(File srcFile, File destDir)` // 复制文件到一个指定的目录
FileUtils.copyFileToDirectory(new File("D://test.txt"), new File("D://eee")); //目标路径不存在,也可以帮助创建
//`FileUtils.writeStringToFile(File file, String data, String encoding, boolean append)`// 指定知否追加
FileUtils.writeStringToFile(new File("D://test.txt"), "\r\nwangwuwuwuwuwuwuwu", "UTF-8",true);
//`FileUtils.deleteDirectory(File directory)` // 删除文件夹,包括文件夹和文件夹里面所有的文件
FileUtils.deleteDirectory(new File("D://DDD"));
//`FileUtils.copyDirectory(File srcDir, File destDir)` // 复制文件夹(文件夹里面的文件内容也会复制)
FileUtils.copyDirectory(new File("D://AAA"), new File("D://BBB"));
//`FileUtils.copyDirectoryToDirectory(File srcDir, File destDir)` // 以子目录的形式将文件夹复制到到另一个文件夹下
FileUtils.copyDirectoryToDirectory(new File("D://AAA"), new File("D://BBB"));
//`FileUtils.copyDirectory(File srcDir, File destDir, FileFilter filter)` // 复制文件夹,带有文件过滤功能
FileUtils.copyDirectory(new File("D://AAA"), new File("D://HAHA"), FileFilterUtils.fileFileFilter());
}
}
拷贝文件
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 1.构建流(输入流 输出流)
is = new FileInputStream("D://test.txt");
os = new FileOutputStream("D://DDD/test.txt");
// 2.读入写出
byte[] car = new byte[1024];
int len = -1; //记录每次读入到字节数组中数据的个数
while((len = is.read(car))!=-1){
os.write(car,0,len);
}
// 3.刷出
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7.扩展内容:
字节流和字符流的区别:
- 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode
- 字节流默认不适用缓冲区,字符流使用缓冲区
- 字节流统称用于处理二进制数据,实际上他可以处理任意类型的数据,但他不支持直接写入或读取Unicode码元;字符流统称处理文本数据,他支持写入读取Unicode码元。
对于flush:
为什么输出流有flush()方法而输入流没有,对于输出流和输入流有一根管道进行数据传输,对于输出流全部写出完成则意味着输入流的全区写入完成,所以只需要输出流有flush刷新功能则可。
为什么在输出流close关闭前需要进行flush刷新,是输入流的在关闭时,只能包装数据源的数据全部输入完,但不能包装目的地拿到全部数据,可能还有数据存在通道中,强制关闭时,则通过中的数据则会丢失,但flush后,通道中的全部数据都会被强制刷出到目的地中,则不会导致数据的丢失,所以在通道关闭前需要先把通道中的数据进行刷出再关闭。
复制问价夹所有内容到另一个文件夹中
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyAll {
public static void main(String[] args) {
//复制问价夹的所有内容 到另一个文件夹里
copy(new File("g:/aaa"), new File("g:/bbb"));
}
private static void copy(File a, File b) {
//先列出a的所有文件
File[] files = a.listFiles();
for (File file : files) {
//获得当前的文件名
String name = file.getName();
//判断是不是文件夹
if (file.isDirectory()) {
File c = new File(b.getAbsolutePath() + "/" + name);
//判断当前文件夹是否存在
if (!c.exists()) {
//创建文件夹
c.mkdir();
}
copy(file, c);
} else {
//先判断问价是否存在
File newFile = new File(b.getAbsolutePath() + "/" + name);
if (!newFile.exists()) {
//复制文件 使用IO流进行
//创建流
FileReader fileReader = null;
FileWriter fileWriter = null;
System.out.println(name);
try {
fileReader = new FileReader(file);
fileWriter = new FileWriter(newFile);
char[] bytes = new char[1024];
while (fileReader.read(bytes) != -1) {
fileWriter.write(bytes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.flush();
fileWriter.close();
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}