java文件管理操作

本文详细介绍了Java中对文件和目录的管理,包括File类的使用,如创建、删除、属性获取等操作。同时,讲解了IO流的基本概念,如输入流、输出流、字节流和字符流,并展示了FileReader、FileWriter、FileInputStream和FileOutputStream的使用。此外,还涵盖了对象的序列化和反序列化,以及标准输入输出的相关知识。
摘要由CSDN通过智能技术生成

一、文件管理

1.1 概述

java中,对文件和目录使用java.io.File类来管理。

主要是针对文件或目录进行管理,包括属性信息的查看、文件或目录的删除、文件或目录的创建。

1.2 File类

  1. File 类:文件、目录的一个抽象封装

  2. 文件路径分隔符:

    • windows:使用 \ 分割,java 中要使用\\ ,分割属性;(不区分大小写)
    • Unix 系统:/ 分割(区分大小写)
  3. 获取当前系统的分割符:

    //获取分割属性
    File.pathSeparator;
    File.pathSeparatorChar;
    //分割符
    File.separator;
    File.separatorChar;
    
  4. 获取路径和名称

    • 相对路径:参考一个坐标,与这个坐标的路径

      . 代表当前目录
      ..返回上一层
      ../test 上一层目录下面的 test 目录
      注意,现在拷贝的时候,尽量使用绝对路径来做,以后到框架阶段,用相对路径来做
      
    • 绝对路径:从磁盘的跟目录一直到你的文件

      //获取绝对路径
      public String getAbsolutePath()
      //获取文件路径
      public File getAbsoluteFile()
      //获取文件路径
      public String getPath()
      //获取上级目录文件
      public File getParentFile()
      //获取上级目录路径
      public String getParent()
      
  5. 构造方法

    //直接使用路径创建文件 pathname 可以是文件也可以是目录
    public File(String pathname)
    //从目录对象下创建文件对象
    public File(File parent, String child)
    //目录路径和文件路径分开传
    public File(String parent, String child)
    
    
    //第一种构造方法
    //磁盘上的文件夹(目录)
    //File file=new File("d:/aa");
    //磁盘上的文件
    //File file=new File("d:/aa/hello.txt");
    //第二种构造方法
    //File file=new File("d:/aa","bb");
    //File file=new File("d:/aa","hello.txt");
    //第三种构造方法
    //File dir=new File("d:/aa");
    //File file=new File(dir,"hello.txt");
    
    
  6. 方法

    //创建新文件
    public boolean createNewFile()
    //判断是否为目录
    public boolean isDirectory() 
    //判断是否为文件
    public boolean isFile()
    //删除文件
    public boolean delete()
    //判断文件是否存在
    public boolean exists()
    //创建文件目录
    public boolean mkdir()
    //创建多个目录
    public boolean mkdirs() 
    //获取当前层级的文件名
    public String[] list() 
    //重命名(可以做拷贝)
    public boolean renameTo(File dest)
    

1.2.1 创建文件

createNewFile()方法

//创建一个新的空文件
//如果文件不存在,就创建一个新的空文件,并返回true
//如果文件存在,则直接返回false,不会创建新的文件
try {
boolean b = file.createNewFile();
System.out.println("b = " + b);
} catch (IOException e) {
e.printStackTrace();
}

1.2.2 创建目录

mkdir()

mkdirs()

//创建目录的方法
//如果目录不存在,则创建目录并返回true,如果目录存在,则不创建,返回false
//mkdir的方法,只能创建当前一级目录,如果上级目录不存在,则创建失败,返回false
File dir=new File("d:/aa/yy/mm");
//boolean b = dir.mkdir();
//mkdirs方法,如果父目录不存在,会一并创建出来
boolean b = dir.mkdirs();
System.out.println("b = " + b);

1.2.3 文件删除

delete()

public class TestDelete {
    public static void main(String[] args) throws IOException,InterruptedException {
        //如果删除成功,返回true,否则返回false
        //File file=new File("d:/aa/hello.txt");
        // file.createNewFile();
        // boolean delete = file.delete();
        //创建一个临时文件
        File tempFile = File.createTempFile("order_", ".txt");
        //当虚拟机退出时,删除文件
        tempFile.deleteOnExit();
        System.out.println(tempFile.getAbsolutePath());
    }
}

1.2.4 删除目录

在删除目录时,要求目录中没有其它的文件和文件夹,是一个空目录。

如果目录下面还有文件,使用循环删除文件处理

File dir=new File("d:/aa/yy");
//获取目录下的所有文件
File[] files = dir.listFiles();
for (File file : files) {
//System.out.println(file.getName());//获取文件名
file.delete();
}
boolean delete = dir.delete();
System.out.println("delete = " + delete);

如果目录下面还有目录,则需要使用递归方式删除目录处理

public static void deleteDir(File dir){
    if (dir.isDirectory()) {
        File[] files = dir.listFiles();
        for (File file : files) {
            //判断两种情况,一种file是文件,一种file是目录
            if (file.isFile()) {//判断是不是文件 file.isDirectory()判断是不是目录
               file.delete();
    		} else {
    			deleteDir(file);//递归完成删除
   	 		}
    	}
    }
    dir.delete();//删除空目录
}
 

1.2.5 其他方法

  1. 获取文件名

    String name = file.getName();
    System.out.println("file name:"+name);
    
    
  2. 获取目录名

    String parent = file.getParent();
    System.out.println("parent = " + parent);
    //获取hello.txt所在的目录
    File parentFile = file.getParentFile();
    System.out.println(parentFile.getName());
    
  3. 获取文件大小

    long length = file.length();
    System.out.println("length = " + length);
    
  4. 设置文件只读

    file.setWritable(false);
    
  5. 测试应用程序对文件是否可执行\可读\可写

    boolean b = file.canExecute();
    System.out.println("b = " + b);
    boolean b1 = file.canRead();
    System.out.println("b1 = " + b1);
    boolean b2 = file.canWrite();
    System.out.println("b2 = " + b2);
    
  6. 获取文件路径操作

    //获取的是在File类构造方法中给出的路径
    String path = file.getPath();
    System.out.println("path = " + path);
    //获取绝对路径
    String path1=file.getAbsolutePath();
    System.out.println("path1 = " + path1);
    //精准获取绝对路径方式,可去除在构造时给的相对路径的.
    String path2=file.getCanonicalPath();
    System.out.println("path2 = " + path2);
    
  7. 获取文件最后修改时间戳

    long l = file.lastModified();
    System.out.println(l);
    
  8. 获取磁盘空间操作

    //获取磁盘分区总容量
    long totalSpace = file.getTotalSpace();
    System.out.println("totalSpace = " + totalSpace);
    //获取可用分区大小
    long freeSpace = file.getFreeSpace();
    System.out.println("freeSpace = " + freeSpace);
    //获取JVM可用空间大小
    long usableSpace = file.getUsableSpace();
    System.out.println("usableSpace = " + usableSpace);
    
    
  9. 获取所有磁盘分区

    File[] disks = File.listRoots();
    for (File disk : disks) {
    	System.out.println(disk);
    }
    
    
  10. 对文件进行重命名

    //可以将文件命名到其他目录或盘符下
    //可以实现文件剪切工作
    //boolean b = file.renameTo(new File("c:/hello_1.txt"));
    //System.out.println("b = " + b);
    
  11. 获取文件是否可隐藏

    boolean hidden = file.isHidden();
    System.out.println("hidden = " + hidden);
    

二、IO流

2.1 简介

是一串连续不断的数据集合,对于程序中数据的输入和输出,都是以数据流的方式进行操作。

Input流:输入流(读流)

Outpub流:输出流(写流)

站在当前正在运行的程序的角度,来看数据是输入还是输出

请添加图片描述

2.2 IO流分类

  • 按流的方向划分:输入流、输出流
  • 按处理数据单位划分:字节流、字符流
  • 按功能不同:节点流、处理流

2.3 四个主要流的API

  • InputStream: 面向字节的输入流
  • OutputStream: 面向字节的输出流
  • Reader: 面向字符的输入流
  • Writer: 面向字符的输出流

请添加图片描述

2.4 文件操作流

FileReader、FileWriter、FileInputStream、FileOutputStream

2.4.1 FileWriter

字符流实现原理:字节流+编码表

字符集:unicode字符集 UTF-8、UTF-16、UTF-32、GB2312、GBK、GB18030

使用FileWriter将字符串写入磁盘文本文件

执行方式1:

FileWriter writer=new FileWriter("d:/aa/hello.txt");
writer.write("欢迎使用java系统");
//writer.flush();
writer.write("\n");
writer.write("hello world");
//writer.flush();
writer.close();

执行方式2:

使用try with resource

try (FileWriter writer = new FileWriter("d:/aa/hello.txt")) {
for (int i = 0; i < 10000; i++) {
	writer.write(i + "\t");
}
} catch (IOException e) {
	e.printStackTrace();
}

常用构造方法

请添加图片描述

写数据的五种方法

请添加图片描述

2.4.2 BufferedWriter

FileWriter writer=new FileWriter("d:/aa/buffer.txt");
BufferedWriter bufferedWriter=new BufferedWriter(writer);
bufferedWriter.write("hello buffer");
//bufferedWriter.write("\r\n");
bufferedWriter.newLine();
bufferedWriter.write("new line content");
bufferedWriter.close();

BufferedWriter和FileWriter的区别

  • FileWriter内部有8192个字节缓冲区
  • BufferedWriter内部有8192个字符(16384个字节)
  • FileWriter效率低,每次来一个字符,要查一次码表,BufferedWriter,缓冲区字符存满或者close、flush之后,才会进行查码表.
  • 使用BufferedWriter可以指定缓冲区大小
  • 如果频繁去写文件,最好使用BufferedWriter处理,如果只写一次,FileWriter就可以使用。

2.4.3 FileReade

//每次读取一个字符,返回读取到的字符
int read;
while ((read = reader.read())!=-1) {//没有达到文件尾
	System.out.print((char) read);
}

char[] chars=new char[1024];
//将字符存入数组中,并返回一共读取到多少个字符
int len = reader.read(chars);
//System.out.println(read);
String str=new String(chars,0,len);
System.out.println(str);
char[] chars=new char[1024];
//读取指定长度
int len = reader.read(chars, 0, 20);
System.out.println(len);
String str=new String(chars,0,len);
System.out.println(str);

2.4.4 BufferedReader

FileReader reader=new FileReader("d:/aa/buffer.txt");
BufferedReader bufferedReader=new BufferedReader(reader);
String str;
while ((str=bufferedReader.readLine())!=null){
	System.out.println(str);
}
bufferedReader.close();

2.4.5 文本文件复制的几种方式

public static void copy(File srcFile, File destFile) throws IOException {
        FileReader reader = new FileReader(srcFile);
        FileWriter writer = new FileWriter(destFile);
        int c;
        char[] chars = new char[1024];
        while ((c = reader.read(chars)) != -1) {
        	writer.write(chars, 0, c);
        }
        reader.close();
        writer.close();
}

public static void copyBuffer(String srcFile, String destFile) throws IOException {
        FileReader reader = new FileReader(srcFile);
        FileWriter writer = new FileWriter(destFile);
        BufferedReader bufferedReader = new BufferedReader(reader);
        BufferedWriter bufferedWriter = new BufferedWriter(writer);
        String str;
        while ((str = bufferedReader.readLine()) != null) {
            bufferedWriter.write(str);
            bufferedWriter.newLine();
        }
        bufferedReader.close();
        bufferedWriter.close();
}

public static void copyFile(String srcFile, String destFile) {
        try (FileReader reader = new FileReader(srcFile);
        FileWriter writer = new FileWriter(destFile);) {
        	reader.transferTo(writer);//对文件复制的操作 jdk10版本后新增
        } catch (IOException e) {
        	e.printStackTrace();
    }
}

三、文件字节流

InputStream、OutputStream

FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream

public class TestCopy {
    public static void main(String[] args) throws IOException {
        copyBuffer(new File("C:" + File.separator +"Users\\Administrator\\Desktop\\resource\\nacos-server-2.0.4.zip"), new File("d:/aa/nacos-server-2.0.4.zip"));
        }
    
    public static void copy(File srcFile, File destFile) throws IOException{
            long t1 = System.currentTimeMillis();
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);
            int x;
            while ((x = fis.read()) != -1) {
            fos.write(x);
            }
            fis.close();
            fos.close();
            long t2 = System.currentTimeMillis();
            System.out.println(t2 - t1);
        }
    
        public static void copyBuffer(File srcFile, File destFile) throws IOException {
            long t1 = System.currentTimeMillis();
            FileInputStream fis = new FileInputStream(srcFile);
            FileOutputStream fos = new FileOutputStream(destFile);
            BufferedInputStream bis=new BufferedInputStream(fis);
            BufferedOutputStream bos=new BufferedOutputStream(fos);
            byte[] bytes = new byte[1024];
            int x;
            while ((x = bis.read(bytes)) != -1) {
            	bos.write(bytes, 0, x);
            }
            bis.close();
            bos.close();
            long t2 = System.currentTimeMillis();
            System.out.println(t2 - t1);
    }
}

四、对象的序列化与反序列化

4.1 对象的序列化

4.1.1 简介

把在内存当中的数据,要远程传输到网络上或者保存到硬盘上,需要将java对象转换为字节序列,可以转换成可传输的文件流

4.1.2 对象序列化的使用

ObjectOutputStream完成对象序列化操作 把java对象转换成文件

为什么要使用序列化?

  • 在分布式系统中,数据的共享都需要实现序列化(redis)
  • 服务的钝化,把我们不常用的对象存储到磁盘中,节约内存开销
  • 使用 json 传输的时候

什么样的对象可以被序列化

  • Serializable
  • Externalizable

要求:必须实现序列化接口 Serializable

序列化代码

public class Student implements Serializable {
    private String name;
    private String gender;
    private int age;
    private String address;
    //构造方法
    //getter and setter
}
public static void main(String[] args) throws IOException {
    Student student=new Student("李白","男",22,"北京");
    FileOutputStream fos=new FileOutputStream("d:/aa/stu.xxx");
    ObjectOutputStream oos=new ObjectOutputStream(fos);
    oos.writeObject(student);
    oos.close();
}

4.2 对象反序列化

把字节序列重新恢复为java对象的过程。(磁盘文件的数据恢复为java对象)

4.2.1 对象反序列化使用

ObjectInputStream完成对象反序列化操作

4.2.2 关于serialVersionUID

每次调用ObjectOutputStream来完成序列化时,都会有一个序列化编号,如果没有显式地生成,系统会自动生成一个。在做反序列化,系统会重新生成一个新的版本号,和之前的去比较,就会出现版本号不一致的错误。所以为了避免出现这种问题,一般都会显示地为序列化声明一个版本号。

local class incompatible: stream classdesc serialVersionUID =
185946447685475229, local class serialVersionUID = 8090034645353830909

调整idea2021.3.3在没有序列化版本号时,提示警告

请添加图片描述

反序列化代码

FileInputStream fis=new FileInputStream("d:/aa/stu.xxx");
ObjectInputStream ois=new ObjectInputStream(fis);
Student student =(Student) ois.readObject();
System.out.println(student);
ois.close();

4.3 序列化注意的问题

  • 要序列化的对象,属性是一个引用类型,要求这处引用类型也是可序列化的,否则,这个对象不可以被序列化
  • 使用transient有选择的序列化
  • 对象的类名、属性名和属性值都会被序列化,方法、static属性、transient属性都不会被序列

4.4 使用Externalizable实现序列化

serializable使用的问题:

  • 序列化过程是递归,相对较缓慢
  • 对于需要禁止序列化的变量,需要使用transient关键字修饰,对于属性较多,又有一些不需要序列化的变量,整体操作较复杂
  • 无法控制字段的序列化和反序列化的方式
  • 序列化过程在处理对象时,不会调用构造方法,因此会造成构造方法内的逻辑缺失。

Externalizable:

是Serializable接口的子接口,如果要使用Externalizable来实现序列化,只需要让序列化类实现 Externalizable接口,并重写writeExternal和readExternal方法。可以实现自定义序列化过程。

Externalizable在序列化流程上,和Serializable是一样的。主要差别在于使用Externalizable可以重写 writeExternal和readExternal方法,精准控制。

Externalizable做反序列化时,会调用序列化类的构造方法,要求类中要有默认无参的构造方法。

Externalizable对于static属性和transient属性,没有Serializable的限制,都可以进行序列化。

4.4.1 序列化类
public class Emp implements Externalizable {
    private static final long serialVersionUID = -3582785108027188930L;
    private static String name;
    private transient String gender;
    private int age;
    public Emp(){
    	System.out.println("无参的构造方法");
    }
    public Emp(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    public String getName() {
    	return name;
    }
    public void setName(String name) {
    	this.name = name;
    }
    public String getGender() {
    	return gender;
    }
    public void setGender(String gender) {
    	this.gender = gender;
    }
    public int getAge() {
    	return age;
    }
    public void setAge(int age) {
    	this.age = age;
    }
    @Override
    public String toString() {
        return "Emp{" +
        "name='" + name + '\'' +
        ", gender='" + gender + '\'' +
        ", age=" + age +
        '}';
    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeUTF(gender);
        out.writeInt(age);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
        name=in.readUTF();
        gender=in.readUTF();
        age=in.readInt();
    }
}

4.4.2 序列化和反序列化操作
public class TestExternal {
    public static void main(String[] args) throws IOException,ClassNotFoundException {
        serialize();
        deserialize();
    }
    
    public static void serialize() throws IOException {
        Emp emp=new Emp("李白","男",22);
        /* emp.setName("李白");
        emp.setGender("男");
        emp.setAge(20);*/
        ObjectOutputStream oos=
        new ObjectOutputStream(new
        FileOutputStream("d:/aa/emp.yyy"));
        oos.writeObject(emp);
        oos.close();
    }
    
    public static void deserialize() throws IOException, ClassNotFoundException {
        ObjectInputStream ois=
        new ObjectInputStream(new FileInputStream("d:/aa/emp.yyy"));
        Emp emp=(Emp)ois.readObject();
        System.out.println(emp);
    }
}

五、标准输入输出

System.in:标准输入,默认是对应键盘

System.out:标准输出,默认是对应显示器

System.err:标准错误输出,默认是对应显示器

从键盘获取输入值的方法:

//从键盘接收参数
//方法一:
Scanner scanner=new Scanner(System.in);
//方法二:
InputStream inputStream=System.in;
InputStreamReader inputStreamReader=new InputStreamReader(inputStream);
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
System.out.println("请输入姓名");
String str=bufferedReader.readLine();
System.out.println("您的姓名是:");
System.out.println(str);

java输出及错误输出

PrintStream out = System.out;
out.println("hello");*/
/*System.err.println("错误输出");

格式化输出

double d=3456.7841;
System.out.printf("%10.2f",d);
String name="李白";
int age=20;
System.out.printf("你好,%s,你的年龄是:%d",name,age);

通过改变标准输入和标准输出流,完成文件的复制

//将标准输入和输出进行扭转的操作
FileInputStream fis=new FileInputStream("d:/aa/hello.txt");
System.setIn(fis);//重新分配“标准”输入流
FileOutputStream fos=new FileOutputStream("d:/aa/hhhh.txt");
System.setOut(new PrintStream(fos));//重新分配"标准"输出流
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str=br.readLine())!=null){
	System.out.println(str);
}
br.close();

六、ByteArrayInputStream和ByteArrayOutputStream

  • FileInputStream、FileOutputStream、FileReader、FileWriter是存储在硬盘上的

    硬盘上的资源java虚拟机是无权直接访问的,必须借助操作系统,java虚拟机借助完了之后要通知操作系统释放资源。

  • 我们可以把源头换成电脑上的一块内存,既然是一块内存那么java就可以直接访问,因为是java虚拟机的一块内存。不用关闭(释放)

  • 所有的东西都可以转成字节数组(字符串转成字节数组、任何一个数据(包括整数、包括浮点数、包括一个一个的对象都可以转成字节数组))

  • 字节数组就为二进制了,方便网络上进行传输

  • 文件可以无限制的往里面加内容,但是内存速度快、量小,所以字节数组不建议数据量特别大的操作

示例代码

public class TestByteArray {
    public static void main(String[] args) throws IOException {
        /*String str="abcdefg";
        byte[] bytes=str.getBytes(StandardCharsets.UTF_8);
        ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
        int i = bais.read();
        System.out.println((char)i);
        bais.mark(0);
        int i1 = bais.read();
        System.out.println((char)i1);
        int i2 = bais.read();
        System.out.println((char)i2);
        int i3 = bais.read();
        System.out.println((char)i3);
        bais.reset();
        int i4 = bais.read();
        System.out.println((char)i4);*/
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        while (baos.size()!=10){
        	baos.write(System.in.read());
        }
        byte[] b=baos.toByteArray();
        ByteArrayInputStream bais=new ByteArrayInputStream(b);
        int x;
        while ((x=bais.read())!=-1){
        	System.out.println(Character.toUpperCase((char)x));
        }
        /*//
        String s = baos.toString();//new String(b);
        System.out.println(s);*/
        /*for (byte b1 : b) {
        System.out.println((char)b1);
        }*/
    }
}

五、DataInputStream和DataOutputStream 数据流

在执行文件存取一个对象的数据成员时,如果只操作一个或几个属性,并且数据成员都是java的基本数据类型或字符串,则不需要使用到对象序列化技术。可以使用DataInputStream和DataOutputStream 来写入或读取数据操作。

写入和读取的时候,不用自行判断读入数据何时停止,只需要使用对应的方法(readUTF或readInt等等), 就可以能够正确读入数据类型。

写入的顺序和读取的顺序要保持一致。

数据流:提供了可以读/写任何数据类型的方法

  • DataInputStream 提供了 readXXX()方法
  • DataOutputStream 提供了 writeXX(obj)
public class TestData {
    public static void main(String[] args) throws IOException {
        /* DataOutputStream dos=new DataOutputStream(new
        FileOutputStream("d:/aa/x.xx"));
        Student student=new Student();
        student.setName("李白");
        student.setAge(20);
        dos.writeUTF(student.getName());
        dos.writeInt(student.getAge());
        dos.close();*/
        DataInputStream dis=new DataInputStream(new
        FileInputStream("d:/aa/x.xx"));
        String name = dis.readUTF();
        int age=dis.readInt();
        System.out.println(name+"\t"+age);
        dis.close();
    }
}

public static void read(String path) throws IOException {
    DataInputStream in = new DataInputStream(new FileInputStream(path));
    System.out.println(in.readInt());
    System.out.println(in.readUTF());
    in.close();
}

public static void write(String path) throws IOException {
    DataOutputStream out = new DataOutputStream(new FileOutputStream(path));
    out.writeInt(123123);
    out.writeUTF("你好,这里是上云教学课");
    out.close();
}
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小郑在努力ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值