IO流-其他

1、IO流-对象序列化

需求:想要将封装了数据的对象进行持久化。当写入的对象很多,对象会按照顺序排列,也称之为对象的序列化

1、先有对象

2、往硬盘上写数据进行持久化需要IO技术。输出流。FileOutputStream

3、在字节输出流的api中找到一个子类ObjectOutputStream

4、在基础流对象上使用额外功能。

方法:writeObject(Object obj); //将指定对象写入ObjectOutputStream,对象的类、类的签名、以及类的所有超类型的非瞬态和非静态字段的值都将被写入。

注意:类需要实现Serializable接口才能启动其序列化功能

这个接口没有方法,叫做标记接口。

package IO_other;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException {
    writeObj();
    }

    private static void writeObj() throws IOException {
        Person p = new Person("leo", 24);
        FileOutputStream fos = new FileOutputStream("F:\\javatest\\obj.object");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p);
        oos.close();
    }
}

2、对象反序列化-ObjectInputStream

有一个对应的对象,叫ObjectinputStream用于读取存储对象的文件

package IO_other;

import java.io.*;

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    //writeObj();
        readObj();
    }

    private static void readObj() throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream("F:\\javatest\\obj.object");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object obj = ois.readObject();
        System.out.println(obj);
    }

    private static void writeObj() throws IOException {
        Person p = new Person("leo", 24);
        FileOutputStream fos = new FileOutputStream("F:\\javatest\\obj.object");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p);
        oos.close();
    }
}

前提:得有Person.class,没有这个都是白扯,得发class文件和object文件都发过来。

如果接收者加载的该对象的类的serialVersionUID与对应的发送者的类的版本号不同,则反序列化则会导致InvalidClassException异常。

3、序列化接口-Serilizable的作用

没有方法,不需要覆盖,是一个标记接口,为了启动一个序列化功能。

唯一作用:给每一个需要序列化的类都分配一个序列版本号。UID。

这个版本号和该类相关联,这就是这个接口的作用。

版本号的作用:验证用的。在序列化时,会将这个序列号也以同保存在文件中。在反序列化时,会读取这个序列号和本类的序列号进行匹配,如果不匹配,会抛出异常。

有默认UID,但是强烈建议所有可序列化类都显式声明serialVersionUID值,原因是计算默认的会因为编译器的不同可能千差万别

ANY-ACCESS-MODIFIER static final long seriaVersionUID = 42L;

package IO_other;

import java.io.Serializable;

public class Person implements Serializable{
    public static final long seriaVersionUID = 42L;
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name = " + name + ",age = " + age + "]";
    }
}

3、瞬态关键字transient

静态数据是不会被序列化的,因为在静态区的方法区中,不在对象中。

对于一个非静态的数据也不想序列化(比如用户名的密码),那么就需要一个关键字来修饰,就是这个transient。

4、printStream&printWriter打印流

缺点:没有读,只有写

字节流和字符流已经掌握了很多对象。

需要关注:

1、IO流的基础流对象。直接调用底层资源操作数据的对象。File开头的流对象。

2、根据IO流的学习规律。后面出现的流对象无非是在增加一些额外功能。

继续提供一些功能。

需求:写一个数据(整数)到文件中。

package IO_other;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class printStreamDemo {
    //需求:写一个整数,到目的地整数的表现形式不变。
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File("F:\\javatest\\tempfile\\int.txt"));
        //fos.write(353); //00000000 00000000 00000001 01100001 在字节流的write方法只将一个整数的最低字节写入到目的地中。不满足需求。
        fos.write(Integer.toString(353).getBytes());  //这个解决方法可以,将整数转成字符串再写入到目的地
        fos.close();
    }
}

之前学习过输出语句,发现要输出的内容都是原样不变的体现出来。


输出语句的对象为printStream

package IO_other;

import java.io.*;

public class printStreamDemo {
    //需求:写一个整数,到目的地整数的表现形式不变。
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\javatest\\tempfile\\ini.txt");
        PrintStream ps = new PrintStream(fos);
        ps.print(97);
        ps.close();
    }
}

这个对象提供了很多打印的方法,好处在于可以保证数据值的表现形式。

printWriter为字符打印流。

package IO_other;

import java.io.*;

public class printWriterDemo {
    /*
    读取键盘录入,将录入的数据转称大写保存到文件中
     */
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter("F:\\javatest\\tempfile\\testPrintWriter.txt");
        String line = null;
        while ((line = br.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            out.println(line.toUpperCase());
            out.flush();
        }
        out.close();
    }
}
package IO_other;

import java.io.*;

public class printWriterDemo {
    /*
    读取键盘录入,将录入的数据转称大写保存到文件中
     */
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out,true);  //自动刷新
        String line = null;
        while ((line = br.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            out.println(line.toUpperCase());
            //out.flush();
        }
        out.close();
    }
}

想要将数据打印到 文件中,并自动刷新

PrintWriter out = new PrintWriter(new FileWriter("tempfile.txt"),true);


5、基本类型数据流-dataoutputStream&datainputStream

另一个需求:保证数据的值的字节原样性不变

例如:写一个整数,源为四个字节,希望目的也是四个字节。

需要一个可以读也可以写的操作基本类型数值的对象

DataoutputStream-数据输入流(用于读取)

DataOutputStream-数据输出流

package IO_other;

import java.io.*;

public class dataStreamDemo {
    public static void main(String[] args) throws IOException {
        //writedata();
        readdata();
    }

    private static void readdata() throws IOException {
        FileInputStream fis = new FileInputStream("F:\\javatest\\datastream.txt");
        DataInputStream dis = new DataInputStream(fis);
        int count = dis.readInt();
        System.out.println(count);
        dis.close();
    }

    private static void writedata() throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\javatest\\datastream.txt");
        //需要额外功能吗。需要,可以写一个基本数值的原字节不变
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeInt(97); //00000000 00000000 00000000 01100001 三个空白一个a
        dos.close();
    }
}

6、用于操作数组和字符串的流对象

类 ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个byte数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()和toString()获取数据。

源和目的都是内存的流对象

字节流:ByteArrayInputStream  BytearrayoutputStream

字符流:chararrayreader chararraywriter   stringreader stringwriter

原理:通过流的read,write方法对数组以及字符串进行操作。

关闭这些流都是无效的,因为本来就是在内存中操作,并未调用系统资源,不需要抛出IO异常。

package IO_other;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;

public class ByteArrayStreamDemo {
    public static void main(String[] args) {
        //源和目的都是内存的读写过程
        //源
        ByteArrayInputStream bis = new ByteArrayInputStream("abcde".getBytes()); //用流的读写思想操作数组中的数据
        //目的
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); //内部有一个可自动增长的数组
        //不断读写
        int ch = 0;
        while ((ch = bis.read()) != -1) {
            bos.write(ch);
        }
        //因为没有调用底层资源,所以不需要关闭,即使调用了close也没有任何效果,不会抛出IO异常。
        System.out.println(bos.toString());
    }
}

7、IO流-RandomAccessFile

需求:对文件进行读或者写的操作,不从头开始,想从哪里读/写,就从哪里读/写。

本身不是流对象,此类的实例支持对随机访问文件的读取和写入。

只能操作文件。

这个对象既能读,又能写。

package IO_other;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class randomaccessFiledemo {
    public static void main(String[] args) throws IOException {
        //randomaccessfile
        //1、实现随机访问
        //2、操作的是随机文件
        //3、既可以读,又可以写
        //4、内部维护了用于存储数据的byte数组
        //5、提供了一个对数组操作的文件指针
        //6、文件指针可以通过getFilePointer方法读取,通过seek方法设置
        //7、随机读写,数据需要有规律
        writeFile();
    }

    private static void writeFile() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("F:\\javatest\\randomaccessfile.txt","rw");
/*        //写一些字符信息
        raf.write("张三".getBytes());
        raf.writeInt(97); //保证字节的原样性
        raf.write("李四".getBytes());
        raf.writeInt(99); //保证字节的原样性*/
        raf.seek(8);   //从第八个字节开始写
        raf.write("刘栋".getBytes());
        raf.writeInt(102);
        System.out.println(raf.getFilePointer()); //打印指针位置
        raf.close();
    }
}

可以结合多线程实现数据的同时写入,可以用于多线程的下载

随机读:

package IO_other;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class randomaccessFiledemo {
    public static void main(String[] args) throws IOException {
        //randomaccessfile
        //1、实现随机访问
        //2、操作的是随机文件
        //3、既可以读,又可以写
        //4、内部维护了用于存储数据的byte数组
        //5、提供了一个对数组操作的文件指针
        //6、文件指针可以通过getFilePointer方法读取,通过seek方法设置
        //7、随机读写,数据需要有规律
        //writeFile();
        readFile();
    }

    private static void readFile() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("F:\\javatest\\randomaccessfile.txt","r");
        //改变其指针的位置,想读谁就读谁。
        raf.seek(8);
        byte[] buf = new byte[4];
        raf.read(buf);
        String name = new String(buf);
        System.out.println("name = " + name);
        int age = raf.readInt();
        System.out.println("age = " + age);
    }

    private static void writeFile() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("F:\\javatest\\randomaccessfile.txt","rw");
/*        //写一些字符信息
        raf.write("张三".getBytes());
        raf.writeInt(97); //保证字节的原样性
        raf.write("李四".getBytes());
        raf.writeInt(99); //保证字节的原样性*/
        raf.seek(8);   //从第八个字节开始写
        raf.write("刘栋".getBytes());
        raf.writeInt(102);
        System.out.println(raf.getFilePointer()); //打印指针位置
        raf.close();
    }
}

局限性:

1、只能操作文件

优势:

把数据存储到数组中看,IO包中的一个工具类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值