File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径)
使用File可以做到:
- 访问其表示的文件或目录的属性信息,例如:名字,大小,修改时间等等
- 创建和删除文件或目录
- 访问一个目录中的子项
但是File不能访问文件数据.
创建File时要指定路径,而路径通常使用相对路径。 相对路径的好处在于有良好的跨平台性。 **"./"**是相对路径中使用最多的,表示"当前目录",而当前目录是哪里 取决于程序运行环境而定,在idea中运行java程序时,这里指定的 当前目录就是当前程序所在的项目目录。
可用操作File file = new File("./test.txt");
String name = file.getName();
System.out.println(name); //test.txt
//返回文件大小 单位是字节
long length = file.length();
System.out.println("大小:"+length + "字节"); //大小:14字节
//是否可读
boolean cr = file.canRead();
//是否可写
boolean cw = file.canWrite();
//是否隐藏
boolean ih = file.isHidden();
//获取绝对路径
System.out.println(file.getAbsolutePath()); //D:...
创建一个新文件
boolean exists()判断当前File表示的位置是否已经实际存在该文件或目录
createNewFile()方法,可以创建一个新文件
//在当前目录下新建一个文件:test.txt
File file = new File("./test.txt");
//boolean exists()判断当前File表示的位置是否已经实际存在该文件或目录
if(file.exists()){
System.out.println("该文件已存在!");
}else{
file.createNewFile();//将File表示的文件创建出来
System.out.println("文件已创建!");
}
删除一个文件
这个操作会直接删除文件,没有挽回的余地,不会放在回收站里可以还原。
File file = new File("test.txt");
if(file.exists()){
file.delete();
System.out.println("文件已删除!");
}else{
System.out.println("文件不存在!");
}
创建目录
mkDir():创建当前File表示的目录 mkDirs():创建当前File表示的目录,同时将所有不存在的父目录一同创建
File dir = new File("./a/b/c/d/e/f");
if(dir.exists()){
System.out.println("该目录已存在!");
}else{
// dir.mkdir();//创建目录时要求所在的目录必须存在
dir.mkdirs();//创建目录时会将路径上所有不存在的目录一同创建
System.out.println("目录已创建!");
}
删除目录
delete()方法可以删除一个目录,但是只能删除空目录。
File dir = new File("demo");
// File dir = new File("a");
if(dir.exists()){
dir.delete();//delete方法删除目录时只能删除空目录
System.out.println("目录已删除!");
}else{
System.out.println("目录不存在!");
}
访问一个目录中的所有子项
listFiles 可以访问一个目录中的所有子项
//获取当前目录中的所有子项
File dir = new File(".");
if(dir.isDirectory()){
File[] subs = dir.listFiles();
System.out.println("当前目录包含"+subs.length+"个子项");
for(int i=0;i
获取目录中符合特定条件的子项
重载的listFiles方法:File[] listFiles(FileFilter)
该方法要求传入一个文件过滤器,并仅将满足该过滤器要求的子项返回。
File dir = new File(".");
if(dir.isDirectory()){
File[] subs = dir.listFiles(new FileFilter(){
public boolean accept(File file) {
return file.getName().startsWith(".");
}
});
System.out.println(subs.length);
}
JAVA IO
- java io可以让我们用标准的读写操作来完成对不同设备的读写数据工作。
- Java 将IO按照方向划分为输入与输出,参照点是我们写的程序。
- 输入:用来读取数据的,是从外界到程序的方向,用于获取数据。
- 输出:用来写出数据的,是从程序到外界的方向,用于发送数据。
- java 将 IO 比喻为“流”,即:stream。就像生活中的“电流”,“水流”一样,它是以同一个方向顺序移动的过程。只不过这里流动的是字节(2进制数据)。所以在IO中有输入流和输出流之分,我们理解他们是链接程序与另一端的“管道”,用于获取或发送数据到另一端。
Java定义的两个超类(抽象类)
java.io.InputStream:
所有字节输入流的超类,其中定义了读取数据的方法。因此将来不管读取的是什么设备(连接该设备的流)都有这些读取的方法,因此我们可以用相同的方法读取不同的设备中的数据。
java.io.OutputStream:
所有字节输出流的超类,其中定义了写出数据的方法。
Java将流分为两类:节点流与处理流:
节点流:也成为低级流,节点流的另一端是明确的,是实际读写数据的流,读写一定是建立在节点流基础上进行的。
处理流:也称为高级流,处理流不能独立存在,必须连接在其他流上,目的是当数据流经当前流时对数据进行加工处理来简化我们对数据的操作。
实际应用时,我们可以通过串联一组高级流到某个低级流上以流水线式的加工处理对某设备的数据进行读写,写这个过程也称为流的链接,这也是IO的精髓所在。
文件流
文件流是一对低级流,用于读写文件数据的流,用于链接程序和文件(硬盘)的“管道”,负责读写文件数据。
java.io.FileInputStream和FileOutputStream
这是一对低级流,继承自InputStream和OutputStream。用于读写硬盘上文件的流
使用文件输出流向文件传入数据
public class FOSDemo {
public static void main(String[] args) throws IOException {
//向当前目录下的demo.dat文件中写入数据
//文件流创建时,如果该文件不存在会自动将其创建(前提是该文件所在目录必须存在!)
FileOutputStream fos = new FileOutputStream("./demo.dat");
fos.write(1);
fos.write(2);
fos.close();
System.out.println("执行完了!");
}
}
使用文件输入流从文件中读取数据
FileInputStream fis = new FileInputStream("./demo.dat");
int d = fis.read();
System.out.println(d);//1
d = fis.read();
System.out.println(d);//2
d = fis.read();
System.out.println(d);//-1
fis.close();
文件复制
- 使用文件输入流读取数据。
- 使用文件输出流复制文件。
- 过程中使用 int 保存读取的数据。
FileInputStream fis = new FileInputStream("C:\Users\17561\Pictures\Saved Pictures\affea75861db83009156c2189ac0f52310f4e1fd.jpg");
FileOutputStream out = new FileOutputStream("./echo.jpg");
int d;//用来保存读取的数据
while ((d = fis.read()) != -1){
System.out.println("复制中...");
out.write(d);
}
System.out.println("复制结束");
//不能忘记关闭流
fis.close();
out.close();
块读写的文件复制操作
int read(byte[] date)
- 一次型从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
- 块写操作 void write(byte[] data) 一次性将给定的字节数组所有字节写入到文件中 void write(byte[] data,int offset,int len) 一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
- 通过提高每次读写的数据量,减少实际读写的次数,可以提高读写效率。单字节读写是一种随机读写形式。而一组一组字节的读写是块读写形式。
FileInputStream fis = new FileInputStream("./echo.jpg");
FileOutputStream fos = new FileOutputStream("./echo2.jpg");
int len; //记录每次读取到的数据量
//一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。单位是字节
byte[] date = new byte[1024*10]; //一次读取10KB
while ((len = fis.read(date)) != -1){ //读取的数据量不为1则表示没有到末尾
fos.write(date,0,len); //读取储存数据,,读取了多少就写多少
System.out.println("复制中...");
}
System.out.println("复制结束");
fos.close();
fis.close();
写文本数据
String提供方法:
byte[] getBytes(String charsetName)
将当前字符串转换为一组字节
参数为字符集的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个。
FileOutputStream fos = new FileOutputStream("demo.txt");
//一
String str = "有没有那么一首歌,会让你想起我。";
byte[] bata = str.getBytes("UTF-8");
fos.write(bata);
//二
fos.write("有没有那么一首歌,会让你轻轻跟着和。".getBytes("UTF-8"));
System.out.println("写出完毕");
//关闭流
fos.close();
文件输出流–追加模式
FileOutPutStream默认创建模式为覆盖模式,即:如果连接的文件存在,则会将该文加原有数据全部删除。然后将通过当前流写出的内容保存在文件中。
重载的构造方法允许我们再传入一个boolean型参数,如果这个值为true,则 文件流为追加模式,即:若连接文件时该文件存在,原有数据全部保留,通过当前 流写出的数据会顺序的追加到文件中。
FileOutputStream fos = new FileOutputStream("demo.txt",true);
读取文本数据
String提供了将字节数组转换为字符串的构造方法:
String(byte[]data,String charsetName)
将给定的字节数组中的所有字节按照指定的字符集转换为字符串
String(byte[]data,int offset,int len,String charsetName)
将给定的字节数组从下标offset处开始的连续len个字节按照指定的字符集 转换为字符串
FileInputStream fis = new FileInputStream("demo.txt");
byte[] bata = new byte[1024];
int len =fis.read(bata); //块读操作
System.out.println("实际读取到了" + len + "个字节");
String line = new String(bata,0,len,"UTF-8");
System.out.println(line);
System.out.println(line.length());
fis.close();
高级流
如果把低级流比作自来水管的话,那么高级流就可以看作是净水器,热水器等对流进行操作以便更好的使用的工具,所以高级流必须依附于低级流而存在,否则是没有意义的
1.缓冲流
java.io.BufferedOutputStream 和 BufferedInputStream.
缓冲流是一对高级流,作用是提高读写数据的效率. 缓冲流内部有一个字节数组,默认长度是8K.缓冲流读写数据时一定是将数据的读写方式转换为块读写来保证读写效率.
使用缓冲流完成文件复制操作
FileInputStream fis = new FileInputStream("D:\壁纸\754c7f8f7d04fd5ad658f6d82fbc4fa7aedc6497.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("./live.jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int d;
while ((d = bis.read()) != -1){
System.out.println("复制中");
bos.write(d);
}
System.out.println("复制结束");
bos.close();
bis.close();
缓冲输出流写出数据时的缓冲区问题
通过缓冲流写出的数据会被临时存入缓冲流内部的字节数组,直到数组存满数据才会真实写出一次
FileOutputStream fos = new FileOutputStream("bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
String line = "有没有那么一首歌,会让你轻轻跟着和";
//line 中存储的数据是小于8KB的,没有写满缓冲区
byte[] data = line.getBytes("UTF-8");
bos.write(data);
bos.flush();
System.out.println("写出完毕!");
bos.close();
2.对象流
java.io.ObjectOutputStream 和 ObjectInputSteam
对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。
对象序列化:
将一个java对象按照其结构转换为一组字节的过程
public class Person implements Serializable {}
//Serializable 序列化一个对象需要实现这个接口
Person p = new Person(name,age,gender,otherInfo); //new对象
FileOutputStream fos = new FileOutputStream("person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p); //序列化
System.out.println("写出完毕!");
oos.close();
对象反序列化:
将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)
//从person.obj文件中将对象反序列化回来
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Person p = (Person)ois.readObject();
System.out.println(p);
3.字符流
- java将流按照读写单位划分为字节流字符流。
- java.io.InputSteam 和 OutputStream 是所有字节流的超类。
- 而java.io.Reader 和 Writer 则是所有字符流的超类,他们和字节流的超类是平级关系。
- Reader 和 Writer 是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法。
- 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成。
转换流
java.io.InputStreamReader 和 OutputStreamWriter
它们是字符流非常常用的一对实现类同时也是一对高级流,实际开发中我们不直接操作它们,但是他们在流连接中是非常重要的一环。
使用转换输出流向文件中写入文本数据
FileOutputStream fos = new FileOutputStream("./osw.txt",true);
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("贝加尔湖畔");
osw.write("假如爱有天意");
System.out.println("写出完毕");
osw.close();
使用转换输入流读取文本文件
FileInputStream fis = new FileInputStream("./osw.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
int d;
while ((d = isr.read()) != -1){
System.out.print((char) d);
}
isr.close();
字符流读一个字符的方法定义:
int read();
读取一个字符,返回的int值实际上表示的是一个char(低16位有效),如果返回的int值表示的是-1则说明读到了末尾
转换流的意义:
实际开发中我们还有功能更好的字符高级流,但是其他的字符高级流都有一个共通点:不能直接链接在字节流上。而实际操作设备的都是低级流同时也都是字节流,因此不能直接在流连接中串联起来。转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上,在流连接中起到“转换器”的作用(负责字符与字节的实际转换)
4.缓冲字符输出流:
java.io.PrintWriter
缓冲字符流内部也有一个缓冲区,读写文本数据以块读写的形式加快效率,并且缓冲流有一个特别的功能:可以按行读写文本数据。
java.io.PrintWriter 具有自动行刷新的缓冲字符输出流,实际开发中更常用,它内部总是自动连接BufferedWriter作为块写加速使用
PrintWriter pw = new PrintWriter("pw.txt0","UTF-8");
pw.println("第一行");
pw.println("第2行");
pw.println("第three行");
System.out.println("写出完毕");
pw.close();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jTKGoUEV-1637044342233)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
在流链接中使用PW
如果实例化PW时第一个参数传入的是一个流,则此时可以再传入一个boolean型的参数,此值为true时就打开了自动行刷新功能。 即: 每当我们用PW的println方法写出一行字符串后会自动flush.
//字节流,文件流,低级流
FileOutputStream fos = new FileOutputStream("Demo2.txt");
//转换流 同时写编码格式
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
//块写加速
BufferedWriter bw = new BufferedWriter(osw);
//按行输出
PrintWriter pw = new PrintWriter(bw,true);
pw.println("第一行");
pw.println("第二行");
pw.println("人不能永远趴着");
System.out.println("写出完毕");
pw.close();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEzgFFGx-1637044342236)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
缓冲字符输入流:java.io.BufferedReader
这是一个高级的字符流,特点是块读文件数据,并且可以按行读取字符串。
使用java.io.BufferedReader按行读取文本数据
IO总结
IO流 输入流 输出流 分类 字节流InputStream 字节流OutputStream 字符流Reader 字符流Writer 低级流/节点流 文件流FileInputStream连接程序和文件管道负责从文件中读取字节 文件流FileOutputStream连接程序和文件管道负责从文件中写出字节 高级流/处理流 BufferedInputStream块读字节数据加速 BufferedOutPutStream块写字节数据加速 字符转换流 InputStreamReader转换流:1.连接字节与字符流2.将读取的字节转换为字符 OutputStreamWriter转换流:1.链接字符与字节流2.将写出的字符转换为字节 字符流块加速 BufferedReader块读文件数据加速按行读取字符串 BUfferedWriter块写加速 PrintWriter1. 块写文本数据加速2.按行写出字符串3.自动的行刷新功能 对象流 ObjectInputStream进行对象的反序列化 ObjectOutputStream进行对象的序列化
| |
| PrintWriter1. 块写文本数据加速2.按行写出字符串3.自动的行刷新功能 | | | | | |
| 对象流 | ObjectInputStream进行对象的反序列化 | | | ObjectOutputStream进行对象的序列化 | |



