目录
1.Io流概述
2.字符输入和输出流(Reader/Writer)
3.字节输入输出流(InputStream/OutPutStream)
一.File类
1.简介
File 类 就是当前系统中 文件或者文件夹的抽象表示
通俗的讲 就是 使用File对象 才操作我们电脑系统中的文件或者文件夹
学习File类 其实就是学习 如果通过file对象 对系统中的文件/文件夹进行增删改查
2.创建
1 前期准备
在电脑的非系统盘 创建一个 test文件夹 今天所有的操作都在这个文件夹中
2 创建
public void test() {
/* 路径分割符
* D:\haha\hehe\123.mp4 称之为路径 其中 \ 就是路径分割符 代表的是 下级目录
* 在windows系统中 路径分割符为 \ 在 Linux 和 Mac 中 路径分割符是 /
* 我们写的java代码 需要跨平台 多环境运行 开发环境:windows 生成环境:Linux
* 此时就会出现一个问题 如果我们的路径分隔符 写成 \ 在 windows中好使 到了 Linux就不识别
* 所以我们可以使用以下两种方式解决:
*
* */
/* 方式1 : windows不仅支持 \ 还支持/ */
File file1 = new File("D:/aaa/123.txt");
/* 方式2: 使用动态识别的常量 */
// ;
System.out.println(File.pathSeparator);
// \
System.out.println(File.separator);
File file2 = new File("D:" + File.separator + "aaa" + File.separator + "123.txt");
}
3添加操作
File file = new File("E:/AAA/bbb.txt");
file.createNewFile();//创建文件
File file1 = new File("E:/AAA/ccc");
file1.mkdir();//创建目录
File file2 = new File("E:/AAA/eee/ddd");
file2.mkdirs();//创建多级目录
4.删除操作
File file3 = new File("E:/AAA/bbb.txt");
file3.delete();//删除指定文件
File file4 = new File("E:/AAA/ccc");
file4.delete();//删除指定的空目录
File file5 = new File("E:/AAA/bbb.txt");
file5.deleteOnExit();//程序结束后删除
5.修改操作
File file6 = new File("E:/AAA/bbb.txt");
file6.setReadable(false);//设置指定文件不可读取
File file7 = new File("E:/AAA/bbb.txt");
file7.setWritable(false);//设置指定文件不可编写
File file8 = new File("E:/AAA/bbb.txt");
file8.renameTo(new File("E:/AAA/a.txt"));//重命名
6.查询操作
File file9 = new File("E:/AAA/a.txt");
String name = file9.getName();//查看文件名
System.out.println(name);
String parent = file9.getParent();//查看父级路径
System.out.println(parent);
String path = file9.getPath();//得到文件的路径
System.out.println(path);
boolean f = file9.isFile();//判断是否为文件
System.out.println(f);
boolean directory = file9.isDirectory();//判断是否为目录
System.out.println(directory);
File file10 = new File("E:/AAA");
String[] list = file10.list();//列出AAA下所有子文件的名称
System.out.println(Arrays.toString(list));
File[] files = file10.listFiles();//列出AAA下所有文件对象
for(File f1: files){
System.out.println(f1.toString());
}
二.Io流
1.Io流概述
IO都是全大写 说明肯定是两个单词的首字母
I inputstream 输入流 O outputstream 输出流
IO 称之为 java的输入输出流
其实学习IO 就是学习 如何通过java代码 对文件内容 进行 读(输入流) 写(输出流)
所以有一话: 读进来 写出去
Java流的分类
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
按功能分:
节点流: 用于直接操作目标设备的流 ---- 四大基流
过滤流: 是对一个已存在流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。 ---- 包装流
四大基流:
字节输入流
字节输出流
字符输入流
字符输出流
2.字符输入和输出流(Reader/Writer)
2.1.Writer(输出)
public class MyWriter {
public static void main(String[] args) throws IOException {
Writer writer = new FileWriter("E:/AAA/oo.txt",true);//加上true表示最佳内容时不会覆盖前面的内容
String str = "abcdefg";
writer.write(str);//给指定文件内添加内容
String str1 = "higklmn";
writer.write(str1);
writer.flush();//刷新流
writer.close();//关闭流
}
}
2.2.Reader(输入)
public class Text3 {
public static void main(String[] args) throws IOException {
Reader reader = new FileReader("E:/BBB/c.txt");//创建Reader对象,通过FileReader实现
int r = reader.read();//读取内容的方法,默认每次只读取一个字符,返回字符对应的数字,
char a = (char) r;//强转为字符型
System.out.println(a);
}
}
这样读取每次指挥读取一个字符,效率太慢所以我们定义新的方法。
public class MyReader {
public static void main(String[] args) throws IOException {
Reader reader = new FileReader("E:/BBB/c.txt");
int count=0;//记录妹子读取的个数
char[] cs = new char[5];//定义char型数组,长度为5
while ((count=reader.read(cs))!=-1){//读取指定目录里的5个元素放入char中,如果返回不等于-1执行循环
String str = new String(cs,0,count);//将cs转为字符串型,从索引0的位置开始转,每次读取count个字符
System.out.print(str);
}
}
}
2.3.使用字符流完成文件复制(先读取后写入):
public class Fuzhi {
public static void main(String[] args) throws IOException {
Writer writer = new FileWriter("D:/AAA/p.txt");
Reader reader = new FileReader("E:/BBB/o.txt");
int count=0;
char[] cs = new char[5];
while ((count = reader.read(cs))!=-1){
writer.write(cs,0,count);//写出cs,从0的位置开始,每次写count个字符
writer.flush();//刷新流
}
writer.close();//关闭流
reader.close();//关闭流
}
}
3.字节输入输出流(InputStream/OutPutStream)
3.1.概述:
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
3.2.字节输出流(OutPutStream)
写出数组型:
public class MyOutPutStream {
public static void main(String[] args) throws IOException {
//创建一个FileOutputStream对象, OutputStream 是一个抽象类,通过FileOutputStream实现
OutputStream ops = new FileOutputStream("D:/AAA/uu.txt",true);//true表示可以续写,不会覆盖上次写的内容
String str ="王五你好";
//将字符串转为byte数组
byte[] b = str.getBytes();
ops.write(b);
String str2 = "张三你好";
byte[] b2 = str2.getBytes();
ops.write(b2);
ops.flush();//刷新流
ops.close();//关闭流
}
}
写出字符型:
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("D:/AAA/uu.txt");
// 写出数据
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节
fos.write(99); // 写出第3个字节
// 关闭资源
fos.close();
}
}
输出结果:
abc
写出指定长度字节数组:
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("D:/AAA/uu.txt");
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
fos.write(b,2,2);
// 关闭资源
fos.close();
}
}
输出结果:
cd
3.3.字节输入流(InputStream)
读取字节:
public class MyInputStream {
public static void main(String[] args) throws IOException {
InputStream ips = new FileInputStream("D:/AAA/y.txt");
int read = ips.read();//输出一个字节,返回int型
System.out.println((char) read);//打印,将int型转为char型
read = ips.read();
System.out.println((char) read);
read = ips.read();
System.out.println((char) read);
read = ips.read();
System.out.println((char) read);
read = ips.read();
System.out.println(read);//内容读完后返回-1
ips.close();//关闭流
}
}
结果:
a
b
c
d
-1
这样读取的效率比较第所以采用循环读取
循环读取:
@Test
public void MyInputStram() throws IOException {
InputStream ips = new FileInputStream("D:/AAA/y.txt");
int count=0;//记录读取到的个数
byte[] b = new byte[5];//定义一个byte型数组,长度5
while ((count=ips.read(b))!=-1){//每次读取5个字节放入b中
//将字节数组转为字符串型
String str = new String(b,0,count);//读取b的内容,从0的位置开始,每次读取count个
System.out.println(str);
}
}
结果:
abcd
3.4.使用字节流完成文件复制(先读取后写入):
public class FuZhi2 {
public static void main(String[] args) throws IOException {
OutputStream ops = new FileOutputStream("D:/AAA/y.txt");
InputStream ips = new FileInputStream("E:/BBB/c.txt");
int count = 0;
byte[] b = new byte[5];
while ((count=ips.read(b))!=-1){
ops.write(b,0,count);
ops.flush();
}
ops.close();
ips.close();
}
}
3.5.注意:
在使用字节流读取文本类内容时如果byte型数组设置的长度不够长可能会导致中文乱码。原因:一个中文字符占3个字节所以读取时读取一个字会占三个byte空间,循环读取时可能读取某一个字符时byte数组空间不够无法放入完整字符。所以建议读取文本内容时使用字符流。
4.缓冲流(Buffer)
4.1.概述:
缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:
字节缓冲流:BufferedInputStream,BufferedOutputStream
字符缓冲流:BufferedReader,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
4.2.创建:
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
4.3.写入和读取(字节缓冲流)
public class MyBuffer {
public static void main(String[] args) throws Exception{
//写入
OutputStream ops = new FileOutputStream("D:/AAA/p.txt");
BufferedOutputStream bops = new BufferedOutputStream(ops,1);
String str = "李四你好";
byte[] b = str.getBytes();
bops.write(b);
bops.close();
//读取
InputStream ips = new FileInputStream("D:/AAA/p.txt");
BufferedInputStream biops = new BufferedInputStream(ips);
int count=0;
byte[] b2 = new byte[5];
while ((count=biops.read(b2))!=-1) {
String str1 = new String(b2,0,count);
System.out.print(str1);
}
}
}
5.对象流/序列化流(Object)
5.1.概述:
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。
5.2.创建:
FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
5.3.序列化
一个对象要想序列化,必须满足两个条件:
1.该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException 。
2.该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int age; // transient瞬态修饰成员,不会被序列化
public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address);
}
}
写出对象:
public class SerializeDemo{
public static void main(String [] args) {
Employee e = new Employee();
e.name = "zhangsan";
e.address = "beiqinglu";
e.age = 20;
try {
// 创建序列化流对象
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.txt"));
// 写出对象
out.writeObject(e);
// 释放资源
out.close();
fileOut.close();
System.out.println("Serialized data is saved"); // 姓名,地址被序列化,年龄没有被序列化。
} catch(IOException i) {
i.printStackTrace();
}
}
}
输出结果:
Serialized data is saved
5.4.反序列化
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
// 创建反序列化流
FileInputStream fileIn = new FileInputStream("employee.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
// 读取一个对象
e = (Employee) in.readObject();
// 释放资源
in.close();
fileIn.close();
}catch(IOException i) {
// 捕获其他异常
i.printStackTrace();
return;
}catch(ClassNotFoundException c) {
// 捕获类找不到异常
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
// 无异常,直接打印输出
System.out.println("Name: " + e.name); // zhangsan
System.out.println("Address: " + e.address); // beiqinglu
System.out.println("age: " + e.age); // 0
}
}