Day13 JavaSE IO原理及流的引入(下)

JavaSE IO原理及流的引入(下)

3 转换流

转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

InputStreamReader和OutputStreamWriter

字节流中的数据都是字符时,转成字符流操作更高效。

构造方法:(需要和InputStream/OutStream”套接“)

InputStreamReader(FileInputStream in, String charsetName);

以下案例展示输入/输出转换流的使用:

package com.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * 转换流可以把字节流转换为字符流
 * 当字节流中的数据都是字符时,使用转换流转换为字符流处理效率更高!
 */
public class Test7 {
    public static void main(String[] args) throws Exception{
        //所有文件都有编码格式
        //对我们来说,txt和Java文件一般来讲有三种编码
        //ISO8859-1,西欧编码,是纯粹的英文编码,不适应汉字
        //GBK和UTF-8,这两种编码是适用于中文和英文
        //我们一般使用UTF-8
        testInputStreamReader();
        testOutputStreamWriter();
    }

    /**
     * 转换输入流
     * InputStreamReader
     */
    public static void testInputStreamReader() throws Exception{
        FileInputStream in = new FileInputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ddd.txt");

        //把字节流转换为字符流
        InputStreamReader is = new InputStreamReader(in,"UTF-8");

        char[] c = new char[100];
        int len = 0;
        while ((len = is.read(c))!=-1){
            System.out.println(new String(c,0,len));
        }
        is.close();
        in.close();
    }

    /**
     * 转换输出流
     * @throws Exception
     */
    public static void testOutputStreamWriter() throws Exception{
        FileOutputStream out = new FileOutputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ddd.txt");

        OutputStreamWriter os = new OutputStreamWriter(out,"UTF-8");

        os.write("你好!");
        os.flush();
        os.close();
        out.close();
    }
}

注:用法和文件流类似,但是转换流注明了编码,编码一定要正确,否则会乱码录入/输出。

4 标准输入/输出流

System.inSystem.out分别代表了系统标准的输入和输出设备。

默认输入设备时键盘,输出设备是显示器。

4.1 标准输入/输出流案例展示:

package com.io;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 标准输入/输出流
 */
public class Demo04 {
    public static void main(String[] args) throws Exception{
        testSystemIn();
    }

    /**
     * 标准的输入流
     * @throws Exception
     */
    public static void testSystemIn() throws Exception{
        //创建一个接受键盘输入数据的输入流
        InputStreamReader is = new InputStreamReader(System.in);

        //把输入流放到缓冲流里
        BufferedReader br = new BufferedReader(is);

        String str = "";//定义一个临时接受数据的字符串
        while ((str = br.readLine()) != null){
            System.out.println(str);
        }
        br.close();
        is.close();
    }
}
/*运行结果:
输入: 你好
输出: 你好
*/

4.2 练习:把控制台输入内容写到指定txt文件中,接受到over时,结束。

话不多说,直接看代码~

package com.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;

public class Demo05 {
    public static void main(String[] args) throws Exception{
        write2TXT();
    }

    /**
     * 把控制台输入内容写入指定txt文件中,接收到over时,程序结束
     */
    public static void write2TXT() throws Exception{

        //创建一个接受键盘输入数据的输入流
        InputStreamReader is = new InputStreamReader(System.in);

        //把输入流放到缓冲流中
        BufferedReader br = new BufferedReader(is);

        //定义输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/eee.txt"));

        String line = "";
        while ((line = br.readLine())!=null){
            //读取到的每一行都写入txt文件中
            if (line.equals("over")){
                break;
            }
            bw.write(line);
        }
        bw.flush();
        bw.close();
        br.close();
        is.close();
    }
}

运行结果:

控制台输入:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cTFmuphm-1583830111781)(/Users/demut/Desktop/截图/Java Targetu/JavaDay13/控制台输入.png)]

文件中显示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZinuceE-1583830111782)(/Users/demut/Desktop/截图/Java Targetu/JavaDay13/文件中显示.png)]

5 打印流(了解)

在整个IO包中,打印流是输出信息最方便的类。

PrintStream(字节打印流)和PrintWriter(字符打印流)提供了一系列重载的print和println方法,用于多种数据类型的输出。

  • PrintStream和PrintWriter的输出不会抛出异常

  • PrintStream和PrintWriter又自动flush功能

  • System.out返回的是PrintStream的实例

6 数据流(了解)

为了方便地操作Java语言的基本数据类型的数据,可以使用数据流。

数据流有两个类:(用于读取和写出基本类型的数据)

DataInputStreamDataOutputStream

分别套接在InputStreamOutputStream节点流上

案例展示:

package com.io;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * 数据流,专门用来做基本数据类型的读写
 */
public class Test8 {
    public static void main(String[] args) throws Exception{
        testDataOutputStream();
        testDataInputStream();
    }

    /**
     * 数据输出流
     * 用数据输出流写到文件中的基本数据类型数据均为乱码,不能直接辨认
     * -->需要数据输入流来读取!
     * @throws Exception
     */
    public static void testDataOutputStream() throws Exception{
        DataOutputStream out = new DataOutputStream(new FileOutputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/fff.txt"));

        out.writeBoolean(true); //乱码
        out.writeDouble(1.222d); //乱码
        out.writeInt(100); //乱码
        out.flush();
        out.close();
    }

    /**
     * 数据输入流
     * 用数据输入流来读取数据输出流写到文件中的数据时,要保证使用和当时写数据时的数据类型一致来读取。
     * 例:写时writeDouble,读时readDouble
     * @throws Exception
     */
    public static void testDataInputStream() throws Exception{
        DataInputStream in = new DataInputStream(new FileInputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/fff.txt"));
        System.out.println(in.readDouble()); //只有读double时是正常的
        in.close();
    }
}

7 对象流

ObjectInputStreamObjectOutputStream

==用于存储和读取对象的处理流。==它的强大之处在于可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

例如:将person对象存入硬盘:

1. 硬盘存储的基础是什么?二进制。那就需要把对象转化为二进制的字节流,把这个流保存到电脑上。

2. 把这个对象通过网络传到另一台机器上,网络的通信基础是什么?二进制。则需把对象转化为二进制的数据流,把这个流通过网络进行传输,接受者要使用该对象,则将流转化为对象。

正是因为保存对象到硬盘(对象的持久化)和对象的网络传输,需要做这两件事,就产生了对象的输入/输出流。

序列化:用ObjectOutputStream类将一个Java对象写入IO流中。

反序列化:用ObjectInputStream类从IO流中恢复该Java对象。

ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量。

– 对象的序列化与反序列化

为了让某个类可序列化,该类必须实现以下两个接口之一:SerializableExternalizable

若某个类实现了Serializable接口,该类的对象就是可序列化的。

序列化:

  • 创建一个ObjectOutputStream
  • 调用ObjectOutputStream对象的writeObject(对象)方法输出可序列化对象。注意写出一次,操作flush()

反序列化:

  • 创建一个ObjectInputSteam
  • 调用readObject()方法读取流中的对象

强调如果某个类的字段不是基本数据类型或String类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的Field的类也不能序列化。

案例展示:

package com.io;

import java.io.Serializable;

/**
 * 可以序列化与反序列化的对象
 */
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    String name;
    int age;
}
package com.io;

import java.io.*;

/**
 * 系列化与反序列化
 * 注意: 对象的序列化与反序列化使用的类要严格一致,包名,类名,类机构等所有都要一致
 */
public class Test9 {
    public static void main(String[] args) throws Exception{
        testSerialize();
        testDeserialize();
    }

    /**
     * 对象的序列化
     */
    public static void testSerialize() throws Exception{
        //定义对象输出流,把对象的序列化之后的流放到指定文件中
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ggg.txt"));

        Person p = new Person();
        p.name = "张三";
        p.age = 11;

        out.writeObject(p);
        out.flush();
        out.close();
    }

    /**
     * 对象的反序列化
     */
    public static void testDeserialize() throws Exception{
        //创建对象输入流对象,从指定的文件中把对象序列化后的流读取出来
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ggg.txt"));

        Object obj = in.readObject();

        Person p = (Person)obj;
        System.out.println(p.name);
        System.out.println(p.age);

        in.close();
    }
}
/*运行结果:
张三
11
*/

再次强调: 对象的序列化与反序列化使用的类要严格一致,包名,类名,类机构等所有都要一致。

8 随机存取流

RandomAccessFile类支持==“随机访问”==的方式,程序可以直接跳到文件的任意地方来读、写文件。

RandomAccessFile类对象包含一个记录指针,用以标示当前读写处的位置。

RandomAccessFile类对象可以自由移动记录指针:

    • long getFilePointer():获取文件记录指针的当前位置
    • void seek(long pos):将文件记录指针定位到pos位置

RandomAccessFile类

  • 构造器:
    • public RandomAccessFile(File file, String mode)
    • public RandomAccessFile(String name, String mode)
  • 创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式:
    • r: 以只读方式打开
    • rw:打开以便读取和写入
    • rwd:打开以便读取和写入:同步文件内容的更新
    • rws:打开以便读取和写入:同步文件内容和元数据的更新

案例展示:

package com.io;

import java.io.RandomAccessFile;

/**
 * 文件的随机读写
 * 程序可以直接跳到文件的任意地方来读、写文件
 */
public class Test10 {
    public static void main(String[] args) throws Exception{
        testRandomAccessFileRead();
        testRandomAccessFileWrite();
    }
    /**
     * 随机读文件
     */
    public static void testRandomAccessFileRead() throws Exception{
        //RandomAccessFile的构造有两个参数:
        // 参数1是读写文件的路径
        // 参数2是指定的访问模式
        RandomAccessFile ra = new RandomAccessFile("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/hhh.txt", "r");

        ra.seek(0);//设置读取文件内容的起始点--> 随机读取的来源,可通过设置的起始点,从文件的任意位置读取

        byte[] b = new byte[1024];
        int len = 0;

        while ((len = ra.read(b))!=-1){
            System.out.println(new String(b,0,len));
        }
        ra.close();
    }

    /**
     * 随机写入文件
     */
    public static void testRandomAccessFileWrite()throws Exception{
        RandomAccessFile ra = new RandomAccessFile("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/hhh.txt","rw");

//        ra.seek(0);//设置写的起始点,0代表从开头写
        //注意:若从文件开头或者中间的某个位置开始写,就会用所写内容覆盖掉等长的原有内容
        ra.seek(ra.length());//设置写的起始点,代表从文件的最后结尾写-->文件的追加
        ra.write("你好".getBytes());
        ra.close();
    }
}

注:注意seek()的用法。

流的基本应用小结

  • 流是用来处理数据的。

  • 处理数据时,一定要明确数据源!

    • 数据源可以是文件,也可以是键盘
    • 数据目的地可以是文件、显示器或其他设备
  • 流只是帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

  • 字节流-缓冲流(重点)

    • 输入流InputStream–FileInputStream–BufferedInputStream
    • 输出流OutputStream–FileOutputStream–BufferedOutputStream
  • 字符流-缓冲流(重点)

    • 输入流Reader–FileReader–BufferedReader
    • 输出流Writer–FileWriter–BufferedWriter
  • 转换流

    • InputStreamReader和OutputStreamWriter
  • 对象流

    • ObjectInputStream和ObjectOutputStream(难点)
    • 序列化
    • 反序列化
  • 随机存取流RandomAccessFile(掌握读取、写入)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值