IO流中的其它流

目  录

 1.数据输入输出流(DataInputStream/DataOutputStream)

2.内存操作流

3.打印流

打印流的特点

4.随机访问流(RandomAccessFile)

RandomAccessFile的最大特点是能读能写.

5.序列化流和反序列化流

标记接口

什么时候需要用到序列化和反序列化呢?

实现Serializable接口, 为什么还要显示指定serialVersionUID的值?

6.Properties

Properties的特殊功能

7.顺序流(SequenceInputStream)


 1.数据输入输出流(DataInputStream/DataOutputStream)

特点: 可以写基本数据类型,可以读取基本数据类型

案例演示:    数据输入输出流的使用

public class MyTest {
    public static void main(String[] args) throws IOException {
        
        DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));

        //你怎么写的就怎么读,顺序不要乱

        //读出
        boolean b = in.readBoolean();
        double v = in.readDouble();
        long l = in.readLong();
        String s = in.readUTF();
        System.out.println(b);
        System.out.println(v);
        System.out.println(l);
        System.out.println(s);

        in.close();

    }

    private static void writeData() throws IOException {
        DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
        //写入

        out.writeBoolean(true);
        out.writeDouble(3.52);
        out.writeLong(6000);
        out.writeUTF("你好");

        out.close();
    }
}

2.内存操作流

内存操作流,并不直接读写文件,只是在内存中进行读取.可操作的对象如下!

  • 操作字节数组  (ByteArrayOutputStream/ByteArrayInputStream)此类实现了一个输出流,其中的数据被写入一个 byte 数组. 缓冲区会随着数据的不断写入而自动增长.  可使用 toByteArray () 和 toString () 获取数据.  关闭 ByteArrayOutputStream 无效.  ByteArrayOutputStream 自己在内存中维护了一个字节数组,充当缓冲区,你可以往他维护的字节数组中,不断的去写入数据,然后在把数据统一取出来.
  • 操作字符数组  (CharArrayWrite/CharArrayReader)
  • 操作字符串   (StringWriter/StringReader)

构造方法: public ByteArrayOutputStream();

案例演示:    内存操作流的使用

public class MyTest{
    public static void main(String[] args) throws IOException {

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        bos.write("爱生活".getBytes());
        bos.write("爱Java".getBytes());
        bos.write("好好学习".getBytes());
        bos.write("天天向上".getBytes());

        //我要取出 ByteArrayOutputStream 他自己维护的那个字节数组

        byte[] bytes = bos.toByteArray();
        String s = new String(bytes);
        System.out.println(s);
        String s1 = bos.toString();
        System.out.println(s1);


         /*  ByteArrayInputStream( byte[] buf)
        创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。*/

        byte[] bytes = "包含一个内部缓冲区,该缓冲区包含从流中读取的字节".getBytes();

        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        byte[] bytes1 = new byte[1024];
        int len = in.read(bytes1);
        System.out.println(len);
        String s = new String(bytes1, 0, len);
        System.out.println(s);


    }
}

3.打印流

打印流可分为字节流打印流(PrintStream)和字符打印流(PrintWriter).

打印流的特点

  • 打印流只能操作目的地,不能操作数据源(不能进行读取数据)
  • 可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型
  • 如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
  • 这个流可以直接对文件进行操作(可以直接操作文件的流: 就是构造方法的参数可以传递文件或者文件路径)

补充:通过以下构造创建对象能够启动自动刷新,然后调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新

  • public PrintWriter(OutputStream out,  boolean autoFlush)     启动 自动刷新
  • public PrintWriter(Writer out,  boolean autoFlush)                  启动自动刷新

案例演示:    PrintWriter作为Writer的子类使用

public class MyTest {
    public static void main(String[] args) throws FileNotFoundException {

        //字节打印流
        PrintStream ps = new PrintStream(new File("bb.txt"));
        ps.println("abc");
        ps.println(false);
        ps.println(3.5);
        ps.close();

        //字节打印流  System.out 获取的是字节打印流

        //“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出
        PrintStream out = System.out;
        out.println(200);
        out.println(true);
        out.println(false);

        System.out.println("hello");


        /*  PrintWriter(OutputStream out, boolean autoFlush)
        通过现有的 OutputStream 创建新的 PrintWriter。*/
        //   PrintWriter pw = new PrintWriter(new File("cc.txt"));

        PrintWriter pw = new PrintWriter(new FileOutputStream("dd.txt"), true);
        pw.println("aaaa");
        pw.println("bbbbb");
        pw.println("ccccc");
        //pw.write("abc"); 自动刷新,对这个方法没有用

        pw.close();


    }
}

4.随机访问流(RandomAccessFile)

RandomAccessFile的最大特点是能读能写.

        实际上RandomAccessFile类不属于流,是Object类的子类.但它融合了InputStream和OutputStream的功能,便支持对随机访问文件的读取和写入.RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针.

public class MyTest3 {
    public static void main(String[] args) throws IOException {
        
        RandomAccessFile in = new RandomAccessFile("demo.txt", "rw");
        double v = in.readDouble();
        //获取文件指针的位置
        long filePointer = in.getFilePointer(); //8
        System.out.println(filePointer);
        
        //设置这个指针位置
        in.seek(13);
        String s2 = in.readUTF();
        System.out.println(s2);
        

        //复制文件
        RandomAccessFile in2 = new RandomAccessFile("许巍 - 蓝莲花.mp3", "rw");
        RandomAccessFile out = new RandomAccessFile("C:\\Users\\ShenMouMou\\Desktop\\蓝莲花.mp3", "rw");

        String pointer = new BufferedReader(new FileReader("config.txt")).readLine();
        long pos = Long.parseLong(pointer);
        in.seek(pos);
        out.seek(pos);

}

    private static void writeData() throws IOException {
        RandomAccessFile out = new RandomAccessFile("demo.txt", "rw");
        out.writeDouble(3.5);
        out.writeBoolean(true);
        out.writeInt(100);
        out.writeUTF("你好");
        out.close();
    }


}


5.序列化流和反序列化流

  • 序列化流:    ObjectOutputStream. 所谓的序列化就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能被序列化.
  • 反序列化流:    ObjectInputStream. 反序列化就是把文件中存储的对象以流的方式还原成对象.

标记接口

        一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口. 像Serializable接口这样的接口中如果没有方法,那么这样的接口我们将其称之为标记接口(用来给类打标记的,相当于猪肉身上盖个章啦!)

什么时候需要用到序列化和反序列化呢?

        当我们只在本地JVM里运行下Java实例, 这个时候是不需要什么序列化和反序列化的, 但当我们需要将内存中的对象持久化到磁盘, 数据库中时,当我们需要与浏览器进行交互进行网络传输时, 这个时候就需要序列化和反序列化了.只要我们对内存中的对象进行持久化或网络传输, 这个时候都需要序列化和反序列化.

注意: 使用transient关键字声明不需要序列化的成员变量.并且静态变量也不会序列化,因为序列化是针对对象而言的, 而static属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.

实现Serializable接口, 为什么还要显示指定serialVersionUID的值?

        如果不显示指定serialVersionUID, JVM在序列化时会根据属性自动生成一个serialVersionUID, 然后与属性一起序列化, 再进行持久化或网络传输. 在反序列化时, JVM会再根据属性自动生成一个新版serialVersionUID, 然后将这个新版serialVersionUID与序列化时生成的旧版serialVersionUID进行比较, 如果相同则反序列化成功, 否则报错.如果显示指定了serialVersionUID, JVM在序列化和反序列化时仍然都会生成一个serialVersionUID, 但值为我们显示指定的值, 这样在反序列化时新旧版本的serialVersionUID就一致了.在实际开发中, 不显示指定serialVersionUID的情况会导致什么问题? 如果我们的类写完后不再修改, 那当然不会有问题, 但这在实际开发中是不可能的, 我们的类会不断迭代, 一旦类被修改了, 那旧对象反序列化就会报错. 所以在实际开发中, 我们都会显示指定一个serialVersionUID, 值是多少无所谓, 只要不变就行.

6.Properties

        Properties 类表示了一个持久的属性集. Properties 可保存在流中或从流中加载.属性列表中每个键及其对应值都是一个字符串. Properties父类是Hashtable, 属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型.

Properties的特殊功能

  • public Object setProperty(String key,String value)
  • public String getProperty(String key)
  • public Set<String> stringPropertyNames() 
  • public void load(Reader reader)                                  读取键值对数据把数据存储到Properties中
  • public void store(Writer writer, String comments)        把Properties集合中的键值对数据写入到文件中, comments注释
public class MyTest {
    public static void main(String[] args) throws IOException {

        // Properties 默认约定好 键和值的泛型是String
        Properties properties = new Properties();
 
        properties.setProperty("username", "张三");
        properties.setProperty("password", "123456");
        properties.setProperty("email", "gagabang@163.com");
        properties.store(new FileWriter("myUser.properties"), null);

        //键和值是用=号隔开的
        properties.load(new FileReader("myUser.properties"));
        System.out.println(properties);
        String username = properties.getProperty("username");
        System.out.println(username);

    }
}

7.顺序流(SequenceInputStream)

        SequenceInputStream 表示其他输入流的逻辑串联. 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止.

构造方法

  • SequenceInputStream(InputStream s1, InputStream s2) ;     通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2), 以提供从此 SequenceInputStream 读取的字节.
  • SequenceInputStream(Enumeration<? extends InputStream> e) ;    通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数.

(小编也在努力学习更多哟!以后再慢慢分享的啦!)

希望对友友们有所帮助!!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

naoguaziteng

谢谢友友的打赏!一起努力吧

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

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

打赏作者

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

抵扣说明:

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

余额充值