一、File
概念:代表物理盘符中的一个文件或者文件夹。
1.1文件\文件夹
常见方法:
方法名 | 描述 |
---|---|
createNewFile() | 创建一个新文件。 |
mkdir() | 创建一个新目录。 |
delete() | 删除文件或空目录。 |
exists() | 判断File对象所对象所代表的对象是否存在。 |
getAbsolutePath() | 获取文件的绝对路径。 |
getName() | 取得名字。 |
getParent() | 获取文件/目录所在的目录。 |
isDirectory() | 是否是目录。 |
isFile() | 是否是文件。 |
length() | 获得文件的长度。 |
listFiles() | 列出目录中的所有内容。 |
renameTo() | 修改文件名为。 |
案例演示:
public class TestFile {
public static void main(String[] args) throws Exception {
//separator();
//fileOpe();
directoryOpe();
}
//(1)分隔符
public static void separator() {
System.out.println("路径分隔符"+File.pathSeparator);
System.out.println("名称分隔符"+File.separator);
}
//(2)文件操作
public static void fileOpe() throws Exception {
//1创建文件 createNewFile()
File file=new File("d:\\file.txt");
//System.out.println(file.toString());
if(!file.exists()) {
boolean b=file.createNewFile();
System.out.println("创建结果:"+b);
}
//2删除文件
//2.1直接删除
//System.out.println("删除结果:"+file.delete());
//2.2使用jvm退出时删除
//file.deleteOnExit();
//Thread.sleep(5000);
//3获取文件信息
System.out.println("获取文件的绝对路径:"+file.getAbsolutePath());
System.out.println("获取路径:"+file.getPath());
System.out.println("获取文件名称:"+file.getName());
System.out.println("获取父目录:"+file.getParent());
System.out.println("获取文件长度:"+file.length());
System.out.println("文件创建时间:"+new Date(file.lastModified()).toLocaleString());
//4判断
System.out.println("是否可写:"+file.canWrite());
System.out.println("是否时文件:"+file.isFile());
System.out.println("是否隐藏:"+file.isHidden());
}
//(3)文件夹操作
public static void directoryOpe() throws Exception{
//1 创建文件夹
File dir=new File("d:\\aaa\\bbb\\ccc");
System.out.println(dir.toString());
if(!dir.exists()) {
//dir.mkdir();//只能创建单级目录
System.out.println("创建结果:"+dir.mkdirs());//创建多级目录
}
//2 删除文件夹
//2.1直接删除(注意删除空目录)
//System.out.println("删除结果:"+dir.delete());
//2.2使用jvm删除
//dir.deleteOnExit();
//Thread.sleep(5000);
//3获取文件夹信息
System.out.println("获取绝对路径:"+dir.getAbsolutePath());
System.out.println("获取路径:"+dir.getPath());
System.out.println("获取文件夹名称:"+dir.getName());
System.out.println("获取父目录:"+dir.getParent());
System.out.println("获取创建时间:"+new Date(dir.lastModified()).toLocaleString());
//4判断
System.out.println("是否时文件夹:"+dir.isDirectory());
System.out.println("是否时隐藏:"+dir.isHidden());
//5遍历文件夹
File dir2=new File("d:\\图片");
String[] files=dir2.list();
System.out.println("--------------------------------");
for (String string : files) {
System.out.println(string);
}
}
}
递归删除指定文件夹
public class DeleteFile {
public static void main(String[] args) {
// 使用递归删除指定的文件夹
File file = new File("Dir"); // 需要删除的文件夹
deleteDir(file);
}
// 递归删除指定文件夹 如果文件夹不为空,递归,
// 直到文件夹为空,再删除指定文件夹
public static void deleteDir(File file) {
if (!file.exists()) {
System.out.println("目标文件不存在");
return;
}
deleteFile(file); // 调用清空文件夹的方法
file.delete(); // 删除文件夹
System.out.println(file.exists());
System.out.println("已删除指定文件");
}
// 删除指定文件夹下的子文件夹和子文件 -- 清空文件夹 -- 便于删除文件夹
public static void deleteFile(File file) {
File[] files = file.listFiles();
for (File f : files) { // 遍历
if(f.isAbsolute()) {
deleteFile(f); // 递归
}else {
f.delete(); // 删除文件
}
}
}
}
二、流
2.1流的分类
2.1.1 按方向
- 输入流:将<存储设备>中的内容读入到<内存>中。
- 输出流:将<内存>中的内容写入到<存储设备>中。
2.1.2 按单位
字节流:以字节为单位,可以读写所有数据 。
字符流:以字符为单位,只能读写文本数据 。
2.1.3 按功能
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
2.2字节流
处理二进制文件
2.2.1 字节抽象类
InputStream:字节输入流
- public int read(){}。
- .public int read(byte[] b){}。
- public int read(byte[] b,int off,int len){}。
read():依次读取文件中的数据—每次读8位—ascii码,读完了返回-1
文件中:123456789
1:00110001-------49
00110001 00110010 00110011 00110100 00110101 00110110 00110111
00111000 00111001 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111
read(byte[] buf):一次读取buf长度这么多个字节
没读完返回实际读到的字节数,数据放在buf里
读完返回-1
OutputStream:字节输出流
- public void write(int n){}。
- public void write(byte[] b){}。
- public void write(byte[] b,int off,int len){}。
字节输出流,构造的时候如果加了true就是拼接
常用 write(buf,0,length);
2.2.2文件字节
FileInputStream extends InputStream 文件字节输入流
FileOutputStream extends OutputStream 文件字节输出流
案例:FileInputStream读取文件
public class TestFileInputStream {
public static void main(String[] args) throws Exception{
//1创建FileInputStream,并指定文件路径
FileInputStream fis=new FileInputStream("d:\\aaa.txt");
//2读取文件
//fis.read()
//2.1单个字节读取
//int data=0;
//while((data=fis.read())!=-1) {
// System.out.print((char)data);
//}
//2.2一次读取多个字节
byte[] buf=new byte[1024];
int count=0;
while((count=fis.read(buf))!=-1) {
System.out.println(new String(buf,0,count));
}
//3关闭
fis.close();
System.out.println();
System.out.println("执行完毕");
}
}
案例:FileOutputStream写入文件
public class TestFileOutputStream {
public static void main(String[] args) throws Exception{
//1创建文件字节输出流对象
FileOutputStream fos=new FileOutputStream("d:\\bbb.txt",true);
//2写入文件
//fos.write(97);
//fos.write('b');
//fos.write('c');
String string="helloworld";
fos.write(string.getBytes());
//3关闭
fos.close();
System.out.println("执行完毕");
}
}
案例:
复制文件夹----包括子文件、子文件及其文件内容
copyDir(srcPath,descPath);
public class TestCopyDir {
public static void main(String[] args) {
// 复制文件夹(包括子文件夹和文件及其内容)
String srcPath = "d:/Dir"; // 源文件夹路径
String descPath = "d:/Dir1"; // 复制文文件夹路径
copyDir(srcPath,descPath);
}
// 复制文件夹的方法
public static void copyDir(String srcPath, String descPath) {
File file = new File(srcPath);
File[] files = file.listFiles();
File file2 = new File(descPath);
file2.mkdir(); // 创建文件夹
for (File f : files) {
String dPath = f.getAbsolutePath().replace("Dir", "Dir1"); // 更新路径
if (f.isDirectory()) {
new File(dPath).mkdir(); // 创建文件夹
copyDir(f.getAbsolutePath(),dPath); // 递归
}
if (f.isFile()) { // 是文件就复制
try {
FileInputStream is = new FileInputStream(f.getAbsoluteFile());
FileOutputStream os = new FileOutputStream(dPath);
byte[] buf = new byte[1024*8];
int length;
while((length = is.read(buf)) != -1) {
os.write(buf,0,length); // 复制
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.2.3字节缓冲流
BufferedInputStream extends InputStream 带有缓冲区的字节输入流
BufferedOutputStream extends OutputStream 带有缓冲区的字节输出流
- 提高IO效率,减少访问磁盘的次数。
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。
默认缓冲区大小:8192字节
案例:
public class TestBufferedInputStream {
public static void main(String[] args) throws Exception{
//1创建BufferedInputStream
FileInputStream fis=new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
//2读取
//2.1单个字节读取
//int data=0;
//while((data=bis.read())!=-1) {
// System.out.print((char)data);
//}
//2.2一次读取多个字节
byte[] buf=new byte[1024];
int count=0;
while((count=bis.read(buf))!=-1) {
System.out.println(new String(buf,0,count));
}
//3关闭
bis.close();java
}
}
public class TestBufferedOutputStream {
public static void main(String[] args) throws Exception{
//1创建字节输出缓冲流
FileOutputStream fos=new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
//2写入文件
for(int i=0;i<10;i++) {
bos.write("helloworld\r\n".getBytes());//写入8K缓冲区
bos.flush();//刷新到硬盘
}
//3关闭(内部调用flush方法)
bos.close();
}
}
2.2.4对象流
ObjectInputStream 对象输入流
ObjectOutputStream 对象输入流
- 增强了缓冲区功能。
- 增强了读写8种基本数据类型和字符串功能。
- 增强了读写对象的功能:
- readObject() 从流中读取一个对象。
- writeObject(Object obj) 向流中写入一个对象。
序列化概念:
序列化:将程序中的对象写入到文件中 — 钝化
反序列化:将文件中的对象读取到程序中 — 活化
一个类的对象要想通过对象流写入到文件中,该类就必须实现序列化接口(Serializable)
Serializable叫做序列化接口,该接口没有让我们去实现任何的方法,这种接口叫做标记型接口
transient修饰属性后,该属性不会随着对象写入到文件中
static静态属性也不会随着对象写入到文件中
对象序列化的细节:
- 必须实现Serializable接口。
- 必须保证其所有属性均可序列化。
- transient修饰为临时属性,不参与序列化。
- 读取到文件尾部的标志:java.io.EOFException。
案例:
有一个学生对象,我们需要把这个学生存在文件中
//{name:“张三”,age:20,gender:“男”}
public class Student implements Serializable{ //实现序列化接口
private static final long serialVersionUID = -9130056597294443988L; //
//如果一个属性被transient修饰,意味着这个属性的值不能被序列化
// transient String name;
String name;
int age;
public Student(String name, int age) {
super();
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;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
// 测试类
public class TestStudent {
public static void main(String[] args) throws Exception {
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 20);
Student s3 = new Student("王五", 20);
ArrayList<Student> list = new ArrayList<Student>();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/stu.txt"));
for (int i = 0; i < list.size(); i++) {
oos.writeObject(list.get(i));
}
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/stu.txt"));
for (int i = 0; i < list.size(); i++) {
Student stu = (Student)ois.readObject();
System.out.println(stu.toString());
}
ois.close();
}
}
2.2.5数据流
DataInputStream数据流入流
DataOutputStream数据流出流
案例:
public class TestDataStream {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:/a.txt");
DataInputStream dis = new DataInputStream(fis);//数据流
FileOutputStream fos = new FileOutputStream("d:/a.txt");
DataOutputStream dos = new DataOutputStream(fos);
//dos.writeUTF("数据");
//System.out.println(dis.readUTF());
dos.writeInt(49);
int num = dis.readInt();
System.out.println(num);
}
}
(提一个异常 EOFE – EOF:end of file 读到文件末尾)
2.3字符流
2.3.1字符抽象类
Reader:字符输入流
- public int read(){}。
- public int read(char[] c){}。
- public int read(char[] b,int off,int len){}。
Writer:字符输出流
- public void write(int n){}。
- public void write(String str){}。
- public void write(char[] c){}。
2.3.2字符集和字符编码
ASCII --0-127
ISO8859-1 — 128-255 能够表示的符号 256个
中文:
GB2312 GBK GB18030 BIG5
ANSI不是编码,微软为了让各地的用户感觉操作系统无差异 —ANSI
欧洲标准化组织:
UNICODE:万国码
UTF-8 UTF-16 UTF-32
UTF-16:不管你是什么字,我都编程16位
UTF-32:固定长度为32位
UTF-8:可变长的编码
utf-8编码规则:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9NciU1G-1658564796557)(E:/学习/java一阶段-qf线下/课程/20220720-day23-IO流/笔记/images/image-20220720150454092.png)]
1字节utf:128个字符—ASCII
2字节:11
3字节:16 — 中文编码 20000-40000 19968-40869
4字节:21
案例:用字节流去读取UTF-8编码的中文
中—0800 < 4e2d <FFFF
public class TestEncode {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:/a.txt");
// 以 中 字为例子
//中--100111000101101 4e2d
//1110 0100--228 10 111000-184 10 101101-173
System.out.println(fis.read()); // 228
System.out.println(fis.read()); // 184
System.out.println(fis.read()); // 173
System.out.println(fis.read()); // -1
fis.close();
}
}
2.3.3文件字符流
FileReader extends InputStreamReader 文件字符输入流
FileWriter extends OutputStreamWriter 文件字符输出流
public class TestReader {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:/a.txt");
int data;
while((data=fr.read())!=-1) {//读的时候要拿到本地编码
System.out.print((char)data);
}
}
}
2.3.4字符转换流
InputStreamReader extends Reader 字符输入转换流(字节流转换字符流)
OutputStreamWriter extends Writer 字符输出转换流(字节流转换字符流)
应用场景:获取到的流是字节流,但是要去做字符操作
注意:使用转换流都加编码格式
用转换流解决乱码的问题
public class TestInReader {
public static void main(String[] args) throws Exception {
//转换流----字节流转字符流
FileInputStream fis = new FileInputStream("d:/a.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/b.txt"));
int length;
char[] buf = new char[8];
while((length=isr.read(buf))!=-1) {//读的时候要拿到本地编码
System.out.print(new String(buf,0,length));
osw.write(buf, 0, length);
}
//注意:字符流是有缓存的
osw.flush();
osw.close();
}
}
2.3.5缓冲字符流
BufferedReader extends Reader 带有缓冲区的字符输入流
BufferedWriter extends Writer 带有缓冲区的字符输出流
public class TestBuffer {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("d:/a.txt"),"utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/c.txt",true),"utf-8"));
String str = "";
while((str=br.readLine())!=null) {
System.out.println(str);
bw.write(str);
//bw.write("\n");
bw.newLine();
}
bw.close();
br.close();
}
}
2.4各种流…
2.4.1打印流
注意:打印流只有一个方向,就是程序到文件
PrintStream - 字节打印流
PrintWriter - 字符打印流
PrintStream vs PrintWriter
PrintStream :可以将字节流转换为打印流
PrintWriter :可以将字节流/字符流转换为打印流
重定向:重新定义系统标准输入输出流的方向
系统标准的输入流(方向:控制台->程序)
System.setIn() -重定向 :(方向:文件->程序)
系统标准的输出流:(方向:程序->控制台)
System.setOut-重定向:(方向:程序->文件)
案例:
public class TestPrintWriter {
public static void main(String[] args) throws Exception {
//1创建打印流
PrintWriter pw=new PrintWriter("d:\\print.txt");
//2打印
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
//3关闭
pw.close();
System.out.println("执行完毕");
}
}
2.4.2随机访问流
RandomAccessFile随机访问流
含义:认为文件是一个大型的byte数组,底层有一个隐藏的指针,可以从指针的位置进行读取或者写入
模式:r-读 rw-读写
2.4.3内存流
ByteArrayInputStream 内存输入流
ByteArrayOutputStream 内存输出流
方向:程序 <----> 内存
应用场景:数据不重要但频繁使用,就将数据存到内存流中
注意:内存流是关不掉的
2.5总结
IO流大致可以分为字节流和字符流,这两种流又分为输入和输出,每个流的操作都大相径庭,学习时可以触类旁通,举一反三。