JAVA的IO类

IO

● File类是java.io包中很重要的一个类;

● File类的对象可以表示文件,还可以表示目录,在程序中一个File类对象可以代 表一个文件或目录;

● File对象可以对文件或目录的属性进行操作,如:文件名、最后修改日期、文件 大小等;

● File对象无法操作文件的具体数据,即不能直接对文件进行读/写操作。

  1. 创建文件或目录:createNewFile(),mkdir(),mkdirs()

  2. 删除文件或目录:delete(),deleteOnExit()

  3. 判断文件或目录是否存在:exists()

  4. 获取文件或目录名称:getName()

  5. 获取文件路径:getPath()

  6. 获取文件绝对路径:getAbsolutePath()

  7. 获取文件大小:length()

  8. 判断是否为文件或目录:isFile(),isDirectory()

  9. 列出目录下的文件或目录:list(),listFiles()

  10. 修改文件或目录名称:renameTo()

  11. 判断文件或目录是否可读、可写、可执行:canRead(),canWrite(),canExecute()

  12. 设置文件或目录的可读、可写、可执行权限:setReadable(),setWritable(),setExecutable()

● 输入输出(I/O) 把电脑硬盘上的数据读到程序中,称为输入,即input,进行数据 的read 操作从程序往外部设备写数据,称为输出,即output,进行数据的write 操作

字节流与字符流

●从数据流编码格式上划分为

● 字节流

读取时以字节为单位

可以读取任意文件

● 字符

读取时以字符为单位

只能读文本文件

输入流与输出流

● 流按着数据的传输方向分为:

● 输入流:往程序中读叫输入流。

● 输出流:从程序中往外写叫输出流。

● InputStream和OutputStream的子类都是字节流 可以读写二进制文 件,主要处理音频、图片、歌曲、字节流,处理单元 为1个字节。

● Reader和Writer的子类都是字符流 主要处理字符或字符串,字符流处 理单元为1个字符。 字节流将读取到的字节数据,去指定的编码表中获取 对应文字字符。

字节流与字符流

● 字节流中常用类

字节输入流 FileInputStream

字节输出流 FileOutputStream

● 字符流中常用类

字符输入流 FileReader

字符输出流 FileWrit

●InputStream的基本方法 
    //读取一个字节并以整数的形式返回(0~255),如果返回-1已到输入流的末尾。 
    int read() throws IOException 
    //读取一系列字节并存储到一个数组buffer, 返回实际读取的字节数,如果读取前已到输入流的 末尾返回-1 
    int read(byte[] buffer) throws IOException //关闭流释放内存资源 
    void close() throws IOException 
● OutputStream的基本方法 
    //向输出流中写入一个字节数据,该字节数据为参数b的低8位 
    void write(int b) throws IOException 
    //将一个字节类型的数组中的从指定位置(off)开始的 len个字节写入到输出流 
    void write(byte[] b, int off, int len) throws IOException 
    //关闭流释放内存资源 
    void close() throws IOExceptio

节点流与处理流

● 根据封装类型不同流又分为

节点流 处理流

● 节点流:

如果流封装的是某种特定的数据源,如文件、字符串、字符串数组等,

直接封装数据(最基础去读数据的流)

则称为节点流。

● 处理流:

如果流封装的是其它流对象,称为处理流。 处理流提供了缓冲功能,

封装的是一个节点流对象,可以提供缓冲功能,称为处理流/包装流,缓冲字节输入流,默认缓冲区大小是8192个字节,可以自定义缓冲区大小;

提高读写效率,同时增加了一些新的方法;

总结:

  1. 一些常用的方法包括:

    1. InputStream和OutputStream:

    • read():从输入流中读取数据。

    • write():向输出流中写入数据。

    需要额外注意的地方:

    • 使用InputStream和OutputStream时,需要在使用完后关闭流,以释放资源。

    1. Reader和Writer:

    • read():从字符输入流中读取数据。

    • write():向字符输出流中写入数据。

    需要额外注意的地方:

    • Reader和Writer是面向字符的输入输出流,适用于处理文本文件。

    1. BufferedReader和BufferedWriter:

    • readLine():从缓冲字符输入流中读取一行数据。

    • write():向缓冲字符输出流中写入数据。

    需要额外注意的地方:

    • 使用BufferedReader和BufferedWriter可以提高读写效率,特别是对于大文件。

    1. DataInputStream和DataOutputStream:

    • readInt():读取一个整数。

    • writeInt():写入一个整数。

    需要额外注意的地方:

    • DataInputStream和DataOutputStream可以用于读写基本数据类型和字符串。

    1. ObjectInputStream和ObjectOutputStream:

    • readObject():从对象输入流中读取对象。

    • writeObject():将对象写入对象输出流。

    需要额外注意的地方:

    • 注意对象的序列化和反序列化操作,需要实现Serializable接口。

    1. FileReader和FileWriter:

    • read():从字符流中读取数据。

    • write():向字符流中写入数据。

    需要额外注意的地方:

    • FileReader和FileWriter适用于处理文本文件,但不推荐用于处理二进制文件。

    1. RandomAccessFile:

    • seek():设置文件指针位置。

    • read():从文件中读取数据。

    • write():向文件中写入数据。

    需要额外注意的地方:

    • RandomAccessFile可以随机访问文件,但要注意指针位置的控制。

    1. ByteArrayInputStream和ByteArrayOutputStream:

    • read():从字节数组输入流中读取数据。

    • write():向字节数组输出流中写入数据。

    需要额外注意的地方:

    • ByteArrayInputStream和ByteArrayOutputStream适用于操作内存中的字节数组,不涉及文件操作。

这些类和方法是Java IO中常用的类和方法,用于处理文件和流的输入输出操作。

  1. FileInputStream和FileOutputStream示例:

// 读取文件内容并输出到控制台
FileInputStream fis = new FileInputStream("input.txt");
int data;
while ((data = fis.read()) != -1) {
    System.out.print((char) data);
}
fis.close();
​
// 将字符串写入文件
FileOutputStream fos = new FileOutputStream("output.txt");
String str = "Hello, World!";
fos.write(str.getBytes());
fos.close();
  1. BufferedReader和BufferedWriter示例:

// 从文件中读取内容并输出到控制台
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}
br.close();
​
// 将字符串写入文件
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"));
String str = "Hello, World!";
bw.write(str);
bw.close();

序列化,反序列化

在Java中,序列化是指将对象转换为字节流的过程,这样可以方便地将对象保存到文件中、在网络上传输等操作。而反序列化则是将字节流转换回对象的过程。

要实现序列化,需要在类的定义中实现Serializable接口,这是一个空的接口,只是用来标记类可以被序列化。接着使用ObjectOutputStream类将对象写入字节流中,可以使用 FileOutputStream 将字节流写入文件中。反序列化的过程则是使用ObjectInputStream类从字节流中读取对象,可以使用FileInputStream从文件中读取字节流。

下面是一个简单的序列化与反序列化示例:

import java.io.*;
​
class Student implements Serializable {
    private String name;
    private int age;
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
​
public class SerializationExample {
    public static void main(String[] args) {
        Student student = new Student("Alice", 20);
​
        try {
            FileOutputStream fileOut = new FileOutputStream("student.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(student);
            out.close();
            fileOut.close();
            System.out.println("Serialized data is saved in student.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }
​
        Student deserializedStudent = null;
​
        try {
            FileInputStream fileIn = new FileInputStream("student.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            deserializedStudent = (Student) in.readObject();
            in.close();
            fileIn.close();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } catch (ClassNotFoundException e) {
            System.out.println("Student class not found");
            e.printStackTrace();
            return;
        }
​
        System.out.println("Deserialized Student...");
        System.out.println("Name: " + deserializedStudent.name);
        System.out.println("Age: " + deserializedStudent.age);
    }
}

在上面的示例中,我们定义了一个Student类实现了Serializable接口,我们对Student对象进行了序列化,并将其保存在student.ser文件中。然后我们从文件中读取Student对象,并进行反序列化操作,输出反序列化后的Student对象的属性。

在JAVA中,如果一个类需要被序列化到文件中,

那么这个类需要实现Serializable接口。实现Serializable接口后,该类会自动为该类生成一个序列化编号,即serialVersionUID。这个serialVersionUID是用于在反序列化时验证类的版本一致性的,确保序列化和反序列化的类版本一致。

需要注意的地方有:

  1. 序列化编号一旦生成,就不能再被修改。如果修改了类的结构,如添加、删除或修改字段等,会导致旧的序列化数据无法正确反序列化。

  2. 如果不显式指定serialVersionUID,则JAVA会根据类的结构自动生成serialVersionUID。建议显式指定serialVersionUID,以确保序列化和反序列化的兼容性。

  3. 当类的serialVersionUID和序列化数据中存储的serialVersionUID不一致时,会抛出InvalidClassException异常,导致反序列化失败。

  4. 如果希望在类的结构发生变化时不影响反序列化的能力,可以使用Externalizable接口代替Serializable接口,并在writeExternal和readExternal方法中手动控制序列化和反序列化的过程。

在Java中进行序列化和反序列化时,有一些需要额外注意的地方,以确保顺利地实现对象的序列化和反序列化:

  1. 版本控制:在进行序列化时,需要注意给类添加serialVersionUID,这是一个版本号,用于实现类的版本控制。当类结构发生变化时,通过修改serialVersionUID可以避免反序列化失败。

  2. transient关键字:如果类的某个字段不需要被序列化,可以使用transient关键字修饰该字段,序列化时不会将该字段写入输出流。

  3. 对象引用:对象引用是指类中的字段引用其他类的对象,在序列化时,如果有对象引用存在,需要确保所引用的对象也是可序列化的,否则会导致序列化失败。

  4. 单例类序列化:如果需要对单例类进行序列化,可以通过实现readResolve()方法来确保反序列化时返回同一实例。

  5. 父类序列化:如果类有父类,父类也需要实现Serializable接口,以确保父类的字段也能被序列化。

  6. 序列化性能:在进行序列化操作时,可以考虑使用更高效的序列化库,如Kryo、Protobuf等,以提升序列化的性能。

  7. 安全性:在进行反序列化操作时,需要注意安全性,避免恶意对象的反序列化攻击,可以对反序列化的输入进行校验或使用安全的序列化库。

通过注意以上这些方面,可以确保在Java中进行序列化和反序列化操作时能够安全、高效地实现对象的持久化和传输。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值