File类常用操作
File是文件和目录的路径的抽象表示,它并不是一个真正的文件,仅仅是路径名,可以存在也可以不存在
方法 | 说明 |
---|---|
File(String pathname) | 直接写路径进行构造 |
File(String parent,String child) | 目录和子目录进行拼接,都是String |
File(File file,String child) | 前面是文件,后面是子目录的文件名 |
exists() | 判断文件是否存在 |
isDirectory() | 判断是否是文件夹 |
isFile() | 判断是否是文件(非文件夹) |
length() | 获取文件长度 |
lastModified() | 获取文件最后修改时间 |
setLastModified(0 ) | 设置文件修改时间为1970.1.1 08:00:00 |
f1.renameTo(f2) | 文件重命名 |
list() | 以字符串数组的形式 ,返回当前文件夹下的所有文件 |
listFiles() | 以文件数组的形式 ,返回当前文件夹下的所有文件 |
getParent() | 以字符串形式返回文件所在文件夹 |
getParentFile() | 以文件形式返回获取所在文件夹 |
mkdir() | 创建文件夹,如果父文件夹skin不存在,创建就无效 |
mkdirs() | 创建文件夹,如果父文件夹skin不存在,就会创建父文件夹 |
createNewFile() | 创建一个空文件,如果父文件夹skin不存在,就会抛出异常 |
getParentFile().mkdirs() | 创建一个空文件之前,通常都会创建父目录 |
listRoots() | 列出所有的盘符c: d: e: 等等 |
delete() | 刪除文件 |
deleteOnExit(); | VM结束的时候,刪除文件,常用于临时文件的删除 |
递归遍历目录
public class Test {
public static void main(String[] args) {
//给定一个路径
File srcFile = new File("E:\\IdeaProjects\\javatest");
//调用方法
getAllFilePath(srcFile);
}
public static void getAllFilePath(File srcFile) {
File[] files = srcFile.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
//递归调用
getAllFilePath(file);
} else {
System.out.println(file.getAbsolutePath());
}
}
}
}
}
IO流的概述与分类
IO:输入(读)/输出(写)(Input/Output),从其他位置加载到程序(内存)中称为输入,反之称为输出
流:流是一种抽象概念,是对数据传输的总称,数据在设备间的传输称为流,流的本质是数据传输
按数据的流向分:
- 输入流:读数据
- 输出流:写数据
按数据类型分:
- 字节流(万能):字节输入流、字节输出流
- 字符流:字符输入流、字符输出流
我们说的IO流的分类一般是按数据类型
分的
InputStream与OutputStream
InputStream是一个抽象类,是所有输入字节流类的超类
OutputStream也是一个抽象类,是所有字节输出流类的超类,输出流接收输出字符并将其发送到某个接收器
字节流写数据(字节输出流FileOutputStream)
如果文件不存在会自动创建,写数据的时候有三种方式
方法 | 说明 |
---|---|
write(int b) | 一次写一个字节 |
write(byte[] b) | 直接写一个字节数组 |
write(byte[] b,int off,int len) | 从off开始写,写的长度为len |
通常情况下,close方法放在finally
中,在close的时候先判断是否为null
public class Test {
public static void main(String[] args) throws IOException {
//给定一个路径,调用系统功能创建文件
FileOutputStream fos = new FileOutputStream("E:\\IdeaProjects\\javatest\\fos.txt");
//写数据,这里直接写97的时候是a
fos.write("97".getBytes());
//关闭流并释放系统资源
fos.close();
}
}
字节流写数据如何换行以及追加
换行通过写入换行符即可,不同系统换行符不同:
- windows:\r\n
- Linux:\n
- mac:\r
追加写入的实现,在创建FileOutputStream的时候在后面添加true
,这样就是追加了
FileOutputStream fos = new FileOutputStream("E:\\IdeaProjects\\javatest\\fos.txt",true);
字节流读数据(字节输入流FileInputStream)
public class Test {
public static void main(String[] args) throws IOException {
//给定一个路径,调用系统功能创建文件
FileInputStream fis = new FileInputStream("E:\\IdeaProjects\\javatest\\fos.txt");
//读数据,一次读一个字节,如果文件达到末尾则返回-1
int read = fis.read();
System.out.println((char)read);
//一次读完所有的内容
int data;
while ((data=fis.read())!=-1) {
System.out.println((char) data);
}
//一次读取字节数组(常用)
byte[] bytes = new byte[1024];
int len;
while ((len=fis.read(bytes))!=-1) {
//这里经常写为fos.write(bytes);即写入输出流
System.out.println(new String(bytes));
}
//关闭流并释放系统资源
fis.close();
}
}
★【经典文件复制案例】:使用字节数组
public class Test {
public static void main(String[] args) throws IOException {
//输入流读数据
FileInputStream fis = new FileInputStream("E:\\IdeaProjects\\javatest\\fos.txt");
//输出流写数据
FileOutputStream fos = new FileOutputStream("E:\\IdeaProjects\\javatest\\fos-backup.txt");
byte[] bytes = new byte[1024];
int len;
while ((len=fis.read(bytes))!=-1) {
fos.write(bytes);
}
//关闭流并释放系统资源
fos.close();
fis.close();
}
}
字节缓冲流
-
BufferedOutputStream
:类实现一个缓冲输出流。通过设置这样的输出流,一个应用程序可以写字节到基本的输出流,而不必导致每个字节写入的底层系统的调用。默认大小为8192字节 -
BufferedInputStream
:当BufferedInputStream
创建,内部缓冲区创建数组。根据需要从流中读取字节或跳过时,内部缓冲区根据需要从包含的输入流中重新填充,一次许多字节。默认大小为8192字节
因为使用了缓冲流,大大减少了对底层的调用次数,因此可以提高效率。
注:字节缓冲流仅仅提供缓冲区
,而真正的读写数据还是要依靠基本的字节流对象
,因此构造方法中传入字节输入输出流,同时调用的方法与字节流对象相同
★【经典文件复制案例】:使用字节缓冲流
public class Test {
public static void main(String[] args) throws IOException {
//输入流读数据
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\IdeaProjects\\javatest\\fos.txt"));
//输出流写数据
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\IdeaProjects\\javatest\\fos-backup.txt"));
byte[] bytes = new byte[1024];
int len;
while ((len=bis.read(bytes))!=-1) {
bos.write(bytes);
}
//关闭流并释放系统资源
bos.close();
bis.close();
}
}
为什么会有字符流
字节流操作汉字或韩文、日文的时候不方便,因为读的时候是一个字节一个字节的读,而汉字在UTR-8
编码下占用3个字节
,在GBK
编码下占用2个字节
,因此直接输出会乱码,于是Java提供了字符流
字符流 = 字节流+编码表
注:汉字在存储的时候,不论使用哪种编码存储,第一个字节都是负数
字符编码解码的方法
public class Test {
public static void main(String[] args) throws IOException {
String s = "中国";
//默认是UTF-8
//[-28, -72, -83, -27, -101, -67]
System.out.println(Arrays.toString(s.getBytes()));
//[-28, -72, -83, -27, -101, -67]
System.out.println(Arrays.toString(s.getBytes("UTF-8")));
//[-42, -48, -71, -6]
System.out.println(Arrays.toString(s.getBytes("GBK")));
byte[] bytes = s.getBytes();
//中国
System.out.println(new String(bytes));
//中国
System.out.println(new String(bytes,"UTF-8"));
//涓浗
System.out.println(new String(bytes,"GBK"));
}
}
Reader和Writer
Reader:字符输入流的抽象类
Writer:字符输出流的抽象类
字符流写数据(字符输出流OutputStreamWriter)
方法 | 说明 |
---|---|
write(int c) | 一次写一个字符 |
write(char[] c) | 直接写一个字节数组 |
write(char[] c,int off,int len) | 写一个字符数组的一部分,写的长度为len |
write(String str) | 写一个字符串(常用) |
writer(String str,int off,int len) | 写一个字符串的一部分(常用) |
public class Test {
public static void main(String[] args) throws IOException {
//第二个参数可以指定字符集
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\IdeaProjects\\javatest\\a.txt"));
//刷新流,将数据进行操作,即从缓冲区释放
osw.flush();
osw.write("我爱你哦哦哦哦哦");
osw.close();
}
}
注:close首先会先刷新流,然后再关闭资源
字符流读数据(字符输入流OutputStreamReader)
public class Test {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\IdeaProjects\\javatest\\a.txt"));
//一次读一个字符
int ch;
while ((ch=isr.read())!=-1) {
System.out.println((char)ch);
}
//使用字符数组
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars))!=-1) {
System.out.print(new String(chars));
}
}
}
注:字符流与字节流读写数据的方式大同小异,只是对象不同
★【经典文件复制案例】字符流复制文件
public class Test {
public static void main(String[] args) throws IOException {
//字符输入流
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\IdeaProjects\\javatest\\a.txt"));
//字符输出流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\IdeaProjects\\javatest\\a-backup.txt"));
//使用字符数组读写文件
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars))!=-1) {
osw.write(chars);
}
osw.close();
isr.close();
}
}
★【经典文件复制案例——简化版】字符流复制文件
InputStreamReader与OutputStreamWriter操作起来太长了,可以使用子类FileReader
和FileWriter
,但是如果想解决编码问题还是要老老实实的使用父类
public class Test {
public static void main(String[] args) throws IOException {
//字符输入流
FileReader isr = new FileReader("E:\\IdeaProjects\\javatest\\a.txt");
//字符输出流
FileWriter osw = new FileWriter("E:\\IdeaProjects\\javatest\\a-backup.txt");
//使用字符数组
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars))!=-1) {
osw.write(chars);
}
osw.close();
isr.close();
}
}
字符缓冲流
BufferedReader
与BufferedWriter
BufferedWriter
有特有的方法newLine()
,写入一个换行符,这个函数会调用系统默认的换行符
BufferedReader
有特有的方法readLine()
,读取一行文字,如果达到末尾则返回null
★【经典文件复制案例】使用字符缓冲流
public class Test {
public static void main(String[] args) throws IOException {
//读
BufferedReader reader = new BufferedReader(new FileReader("E:\\IdeaProjects\\javatest\\a.txt"));
//写
BufferedWriter writer = new BufferedWriter(new FileWriter("E:\\IdeaProjects\\javatest\\a-backup.txt"));
//使用字符数组
char[] chars = new char[1024];
int len;
while ((len = reader.read(chars))!=-1) {
writer.write(chars);
}
reader.close();
writer.close();
}
}
★【常用】使用字符缓冲流特有功能复制
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("E:\\IdeaProjects\\javatest\\a.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("E:\\IdeaProjects\\javatest\\a-backup.txt"));
//使用字符数组
String line;
while ((line = reader.readLine())!=null) {
writer.write(line);
writer.newLine();
}
reader.close();
writer.close();
}
}
IO总结
什么是输入与输出
输入简单来说就是读
,是针对程序或者内存来说的,就是从外界读取,可以是从文件中,或者是网络请求中
输出简单来说就是写
,是针对程序或者内存来说的,将已经读取到的或者输入的信息写入外部文件中
几个IO操作类
字节流:
类名 | 功能 |
---|---|
InputStream | 所有字节输入流的超类 |
OutputStream | 所有字节输出流的超类 |
FileInputStream | 常用的字节输入流 |
FileOutputStream | 常用的字节输出流 |
BufferedInputStream | 字节输入缓冲流 |
BufferedOutputStream | 字节输出缓冲流 |
字符流:
类名 | 功能 |
---|---|
Reader | 所有字符输入流的超类 |
Writer | 所有字符输出流的超类 |
InputStreamReader | 常用的字符输入流 |
OutputStreamWriter | 常用的字符输出流 |
FileReader | 常用的字符输入流——简化版 |
FileWriter | 常用的字符输出流——简化版 |
BufferedReader | 字符输入缓冲流 |
BufferedWriter | 字符输出缓冲流 |
使用字节/字符数组读写的套路
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars))!=-1) {
osw.write(chars);
}
特殊操作流
标准输入流:System.in
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//Java封装了一个类实现键盘录入,方便我们调用
//Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入一个字符串:");
String line = reader.readLine();
System.out.println("你输入的是:"+line);
}
}
}
标准输出流:System.out
public class Test {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
out.println("hello,这里换行");
out.print("oh,不换行");
out.print("oh,不换行");
}
}
字节打印流:PrintStream
,继承OutputStream
,只负责输出数据,有自己独有的方法
public class Test {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("E:\\IdeaProjects\\javatest\\ps.txt");
//使用字节输出流的形式写到文件,是a
ps.write(97);
//使用特有的方法写入文件,看到的就是97
ps.println(97);
//ps.print(99);不换行
}
}
字符打印流:PrintWriter
public class Test {
public static void main(String[] args) throws FileNotFoundException {
//如果后面加了true,会自动刷新缓冲区
PrintWriter ps = new PrintWriter("E:\\IdeaProjects\\javatest\\ps.txt");
//字符流的形式写到文件,是a
ps.write(97);
ps.write("\r\n");
ps.flush();
//使用特有的方法写入文件,看到的就是97
ps.println(97);
ps.flush();
}
}
对象序列化流:ObjectOutputStream
,需要对象实现Serializable
接口,但不需要重写任何方法
public class Student implements Serializable {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\IdeaProjects\\javatest\\a.txt"));
oos.writeObject(new Student(10,"小黑"));
oos.close();
}
}
对象反序列化流:ObjectInputStream
,可以反序列化ObjectOutputStream
序列化之后的对象,需要对象实现Serializable
接口
public class Student implements Serializable {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\IdeaProjects\\javatest\\a.txt"));
Object object = ois.readObject();
Student student = (Student) object;
System.out.println(student.name+":"+student.age);
}
}