今日目标
- File类
- 字节流
- 字节输入流
- 字节输出流
- 字符流
- 字符输入流
- 字符输出流
- 缓冲区流
- 对象流
一.File类
File类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。
File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。
- 常用构造方法
new File(File parent,String child );
new File(String parent,String child);
new File(String pathName);
@Test//File可以表示文件,或文件夹
public void test1(){
//方式1:文件完整的路径
File file1 = new File("C:\\Users\\Public\\Pictures\\Sample Pictures/妲己.jpg");
//方式2:拆分为文件夹路径和文件路径
File file2 = new File("C:\\Users\\Public\\Pictures\\Sample Pictures/","妲己.jpg");
//表示一个文件夹
File f = new File("C:\\Users\\Public\\Pictures\\Sample Pictures/");
//方式3:文件夹对象和文件路径
File file3 = new File(f, "妲己.jpg");
}
- 常用方法
方法名 | 描述 |
---|---|
String getName() | 获取文件(夹)名 |
String getPath() | 获取文件(夹)路径 |
boolean exists() | 文件(夹)是否存在 |
boolean isFile() | 是否是一个文件 |
boolean isDirectory() | 是否是一个目录(文件夹) |
boolean createNewFile() | 创建一个文件 |
boolean mkdir() | 创建一个具体的文件夹 |
boolean mkdirs() | 创建多级文件夹 |
boolean delete() | 删除某个文件(夹) |
String [] list() | 返回某个文件夹下的所有文件(夹)名 |
File [] listFiles() | 获取某个文件夹下所有的文件(夹) |
File filex = new File("D:\\imgs\\a.jpg");
File file = new File("D:\\imgs/a.jpg");
File file1 = new File("D:\\imgs/","a.jpg");
File f = new File("D:\\imgs/");
File file2=new File(f,"a.jpg");
System.out.println(f.getName());
System.out.println(filex.getName());
System.out.println(file.getName());
System.out.println("------获取文件(夹)路径");
System.out.println(file.getPath());
System.out.println("------文件(夹)是否存在");
System.out.println(file.exists());
System.out.println("-------是否是一个文件");
System.out.println(filex.isFile());
System.out.println(f.isFile());
System.out.println("---------是否是一个目录(文件夹)");
System.out.println(f.isDirectory());
System.out.println(filex.isDirectory());
System.out.println("---------创建一个文件");
File f1 = new File("D:\\imgs/a1.txt");
f1.createNewFile();
System.out.println("---------创建一个具体的文件夹");
File f2 = new File("D:\\imgs/a2");
f2.mkdir();
System.out.println("---------创建多级文件夹");
File f3 = new File("D:\\imgs/a3/b3");
f3.mkdirs();
System.out.println("删除某个文件(夹)");
f2.delete();
System.out.println("返回某个文件夹下的所有文件(夹)名");
System.out.println(Arrays.toString(f.list()));
//Arrays.stream(f.list()).forEach(System.out::println);
System.out.println("----------获取某个文件夹下所有的文件(夹)");
File[] files = f.listFiles();
for (File file3 : files) {
System.out.println(file3);
}
System.out.println("---------");
案例:
1.输出jdk安装目录下,所有的文件(夹)名称,并说明该文件是一个文件或文件夹。
(遍历文件夹)
public static void show(File f){
File[] files = f.listFiles();
for (File file : files) {
if (file.isDirectory()){
System.out.println(file.getName()+"是一个文件夹");
show(file);
}else {
System.out.println(file.getName()+"是一个文件");
}
}
}
2.cmd黑窗口切换到某个目录下,输入以下命令,查看效果:
dir *.* >a.txt
dir *.* /b >b.txt
dir *.* /s >c.txt
dir *.* /b /s >d.txt
以上命令还可以写在记事本中,然后改后缀名为bat,双击运行即可。
3.使用递归,输出某个文件夹下所有的文件,以及子文件夹中所以的文件。
public void showFile(File f){
if(f.isDirectory()){//文件夹
System.out.println(f.getName()+":是一个文件夹:");
File[] files = f.listFiles();
for (File file : files) {
showFile(file);//递归:调用自己
}
}else {//文件
System.err.println(f.getName()+":是一个文件");
}
}
二.字节流
1.字节输入流
- 构造方法
new FileInputStream(String文件路径);
new FileInputStream(File文件对象);
- 使用步骤
1.创建输入流流对象
2.调用read方法//具有记忆功能,读出边界会返回-1
3.关闭流对象
- read方法:从字节输入流中读取数据
//无参,返回一个字节,表示读取一个字节数据
int read()
//传入一个字节数组,表示将读到的字节存入数组中,返回存入的字节个数
int read(byte[] bytes)
//传入一个字节数组,数组下标,存放个数,表示将读到的字节存入数组,从数组的第off+1个元素开始存放,共存放len个。返回实际存入的字节个数。
int read(byte[] b,int off,int len)
- 常用方法
//返回字节输入流中还有多少个可以读取的字节个数
int available();
public void test5() throws IOException {
File f1 = new File("D:\\imgs\\a3.txt");//a3只有五个字符长度
System.out.println(f1.exists());
FileInputStream fis = new FileInputStream(f1);
for (int i=0;i<6;i++){
int r=fis.read();//一个一个读取
System.out.println(r);
}
}
@Test//测试字节输入流--一次读一个字节
public void test1() throws IOException {
//绝对路径
File f1 = new File("D:\\imgs\\a3.txt");
System.out.println(f1.exists());
FileInputStream fiss = new FileInputStream(f1);
fiss.read();
int a1=fiss.available();
System.out.println("还有"+a1+"个没有读完");
fiss.read();
int a2=fiss.available();
System.out.println("还有"+a2+"个没有读完");
System.out.println("------");
File f2 = new File("D:\\imgs\\a3.txt");
System.out.println(f2.exists());
//1.构建一条通向文件f2的管道--流对象
FileInputStream fis = new FileInputStream(f2);
//2.调用方法
int l=fis.available();
for (int i = 0; i <l ; i++) {
System.out.println(fis.read());
}
//关闭资源
fis.close();
}
@Test//测试字节输入流--一次读多个字节
public void test2() throws IOException {
//相对路径
File f1 = new File("D:\\imgs\\a3.txt");
System.out.println(f1.length());//5
//1.构建一条通向文件f1的管道--流对象
FileInputStream fis = new FileInputStream(f1);
//2.调用方法 --根据文件的字节长度,去构建一个相同长度的数组
byte[] bs = new byte[fis.available()];
//读取到文件中的字节数据,存入数组中,返回读到的实际字节个数
int r = fis.read(bs);
int r2 = fis.read(bs);
System.out.println(Arrays.toString(bs));
System.out.println(r);//5
System.out.println(r2);//-1
//关闭资源
fis.close();
}
@Test//测试字节输入流--在第2个方法基础上截取
public void test3() throws Exception {
//直接构建流对象
FileInputStream fis = new FileInputStream("D:\\imgs\\a3.txt");
//调用read方法
byte[] bs = new byte[fis.available()];
System.out.println(Arrays.toString(bs));
int r = fis.read(bs,1,3);//都是从第一个开始读,读3个,放到bs下标为1的位置
//输出字节数组
System.out.println(Arrays.toString(bs));
}
@Test//案例
public void test4()throws Exception{
FileInputStream fis = new FileInputStream("D:\\imgs\\a3.txt");
//调用read方法
byte[] bs = new byte[fis.available()];
int r = fis.read(bs);
//输出字节数组
System.out.println(Arrays.toString(bs));
System.out.println(new String(bs));
}
案例:
创建一个文本文件,写入:
i am a good boy,so nothing is gonna change my love for you ,making love out of nothing at all
使用字节输入流读取该文件内容,并输出。
@Test
public void tests() throws IOException {
FileInputStream fis = new FileInputStream("D:\\imgs\\a4.txt");
byte[] bs = new byte[fis.available()];
fis.read(bs);
System.out.println(Arrays.toString(bs));
System.out.println(new String(bs));
}
找到文件,将其另存为,格式改为UTF-8即可
再次运行
2.字节输出流
- 构造方法
new FileOutputStream(String);
new FileOutputStream(String,Boolean);
new FileOutputStream(File);
new FileOutputStream(File,Boolean);
- 使用步骤
1.创建输出流对象
2.调用write方法
3.关闭流对象
- write方法:向字节输出流中写入数据
//写入一个字节数据b
void write(int b);
//将字节数组b写入输出流中
void write(byte[] b);
//从字节数组b的第off+1个元素开始,向输出流中写入len个字节
void write(byte[] b,int off,int len);
FileOutputStream fos = new FileOutputStream("src/b.txt");//相对路径
//写一个字节
int a=996,a1=97;
byte b=(byte)a;
byte b1=(byte)a1;
System.out.println(b);
System.out.println(b1);
fos.write(b);
fos.write(b1);
//写一个字节数组
os.write(("I know,I'm not good enough, but I'm the only one in the world. " +
"Please cherish it.我知道,我不是最好的," +
"但我是这个世界上独一无二的,请珍惜!").getBytes());
//写一个字节数组 的 部分数据
os.write(("I know,I'm not good enough, but I'm the only one in the world. " +
"Please cherish it.我知道,我不是最好的," +
"但我是这个世界上独一无二的,请珍惜!").getBytes(),2,4);
案例
将下面的语句写入一个文本文件中:
I know,I'm not good enough, but I'm the only one in the world. Please cherish it.
FileOutputStream os = new FileOutputStream("src/b.txt");
//写一个字节数组
os.write(("I know,I'm not good enough, but I'm the only one in the world. " +
"Please cherish it.我知道,我不是最好的," +
"但我是这个世界上独一无二的,请珍惜!").getBytes());
扩充:带缓冲区字节输入流和输出流
BufferedInputStream
BufferedOutputStream
//对比FileInputStream和FileOutputStream,测试读或写10000次的耗时
@Test//对比测试带缓冲区的字节流和文件字节流的读写效率
public void test3() throws Exception {
FileInputStream fis = new FileInputStream("src/a.txt");
FileInputStream fis2 = new FileInputStream("src/c.txt");
FileOutputStream fos = new FileOutputStream("src/b.txt");
FileOutputStream fos2 = new FileOutputStream("src/d.txt");
BufferedInputStream bis = new BufferedInputStream(fis2);
BufferedOutputStream bos = new BufferedOutputStream(fos2);
BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream("src/c.txt"));
BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("src/d.txt"));
long l1 = System.currentTimeMillis();
while (fis.available()>0){
fos.write(fis.read());
}
long l2 = System.currentTimeMillis();
while (bis.available()>0){
bos.write(bis.read());
}
bos.close();//刷新缓冲区
long l3 = System.currentTimeMillis();
System.out.println(l2-l1);
System.out.println(l3-l2);
}
案例2–复制文件
结合字节输入流和输出流,边读边写,将某个文件复制到磁盘另一个位置。
2种方式:
- 创建一个比较大的数组,将输入流中所有的数据读取到数组中,再将数组中所有的数据一次写入输出流
- 结合while循环,一次读一个字节,写一个字节,边读边写。
//将a3.txt的数据传入到b.txt中
File f1 = new File("D:\\imgs\\a3.txt");
FileInputStream fis = new FileInputStream(f1);
byte[] bs = new byte[fis.available()];
fis.read(bs);
FileOutputStream fos1 = new FileOutputStream("src/b.txt");
fos1.write(bs);
@Test
public void test2() throws Exception {
//需要两个流
FileInputStream is = new FileInputStream("src/a.txt");
//第二个参数:true表示在原来的后面追加,而不是覆盖
FileOutputStream os = new FileOutputStream("src/b.txt",true);
//方式一:
/*while (is.available()>0){
os.write(is.read());
}*/
//方式2:
/*int l=is.available();
for (int i = 0; i <l ; i++) {
os.write(is.read());
}*/
//方式3
int r=-1;
while ((r=is.read())!=-1){
os.write(r);
}
}
回顾
三.字符流(day21)
读写字符数据文件:txt文件
1.字符输入流
- 构造方法
new FileReader(String);
new FileReader(File);
File file = new File("D:\\imgs\\a3.txt");
FileReader fr1 = new FileReader(file);
FileReader fr = new FileReader("day21-java21\\src/a1.txt");
- 使用步骤
1.构建流对象
2.调用read方法
3.关闭流对象
- read方法:从字符输入流中读取字符数据
//读取一个字符,并返回读到的字符,如果没有读到,返回-1
int read();
//读取到的字符存入字符数组c
read(char[] c);
//读取到的字符存入字符数组c,从下标offset开始,个数为len
read(char[] c,int offset,int len);
FileReader fr = new FileReader("day21-java21\\src/a1.txt");
System.out.println(fr.read());
System.out.println(fr.read());
System.out.println(fr.read());
System.out.println("------");
FileReader fr2 = new FileReader("day21-java21\\src/a.txt");
char[] cs = new char[6];
fr2.read(cs);//这里如果换成System.out.println(fr2.read(cs));结果会是6,表示读取的长度
System.out.println(cs);
System.out.println("------");
FileReader fr3 = new FileReader("day21-java21\\src/a.txt");
char[] cs1 = new char[24];
fr3.read(cs1,10,5);
System.out.println(cs1);
案例
创建一个文本文件,写入:空山不见人,但闻人语响。返景入深林,复照青苔上。
使用字符输入流读取文本内容,输出在控制台。
输出效果如下:
空山不见人,
但闻人语响。
返景入深林,
复照青苔上。
FileReader fr4 = new FileReader("day21-java21\\src/a.txt");
char[] cs2 = new char[6];
while (fr4.read(cs2)!=-1){
System.out.println(cs2);
}
2.字符输出流
对于字符流 一般写入的时候想要马上看到一般需要flush(),
close()和flush()的区别?
A:close()关闭流对象,但是先刷新一次缓冲区,关闭之后,流对象不可以继续再使用了。
B:flush()仅仅是刷新缓冲区(一般写字符时要用,因为字符是先进入的缓冲区),流对象还可以继续使用
- 构造方法
new FileWriter(String);
new FileWriter(String,boolean);//boolean不填,默认是false,true表示在原来的后面追加,而不是覆盖
new FileWriter(File);
new FileWriter(File,boolean);
FileWriter fw = new FileWriter("day21-java21\\src/a1.txt");
File file = new File("day21-java21\\src/a1.txt");
FileWriter fw1 = new FileWriter(file);
- write方法:向字符输出流中写入字符数据
//写入一个字符
void write(int c)
//写入一个字符串
void write(String str)
//写入一个字符数组
void write(char[] c)
//写入一个字符串,从off开始,写len个
void write(String str,int off,int len)
//写入一个字符数组,从off开始,写len个
void write(char[] c,int off,int len)
FileWriter fw = new FileWriter("day21-java21\\src/a1.txt",true);
fw.write(97);//a
fw.write("Hello,你好");
char[] cs = new char[10];
fw.write(cs);
fw.write("123456",2,4);//3456
char[] cs1 = {'1', '2', '3', '4', '5', '6', '7', '8'};
fw.write(cs1,3,4);//4567
fw.close();//关闭,不关闭将看不到数据的写入
案例
请把下面的话写入一个文本文件中:
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。
FileWriter fw2 = new FileWriter("day21-java21\\src/a1.txt");
fw2.write("昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。");
fw2.close();
四.其它流–扩展
1.缓冲流
-
BufferedInputStream
-
BufferedOutputStream
-
BufferedReader
-
BufferedWriter
@Test
public void test2() throws IOException {
FileWriter fw = new FileWriter("src/a1.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("昨夜雨疏风骤,浓睡不消残酒。");
bw.newLine();//换行
bw.write("试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。");
bw.close();// bw.flush();也可以
BufferedReader br = new BufferedReader(new FileReader("src/a1.txt"));
String s=br.readLine();//读一行
System.out.println(s);
}
2.转换流
- InputStreamReader
- OutputStreamWriter
3.数据流
- DataInputStream
- DataOutputStream
4.对象流
- ObjectInputStream
- ObjectOutputStream
作业
测试其它流的用法
转换流:
@Test
public void test1() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("src/a.txt"));//hello
BufferedReader br = new BufferedReader(isr);
System.out.println( br.read());//104
System.out.println(br.readLine());//ello
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src/a.txt"));
BufferedWriter bw = new BufferedWriter(osw);
bw.write("132");
bw.close();
}
对象流
@Test
public void test2() throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/a.txt"));
oos.writeObject(new Monkey("菲菲"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/a.txt"));
Monkey m=(Monkey) ois.readObject();
System.out.println(m);
}
public class Monkey implements Serializable {
private String name;
@Override
public String toString() {
return "Monkey{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Monkey() {
}
public Monkey(String name) {
this.name = name;
}
}