Java基础--IO流04(IO流中的其他流,编码)

操作对象的流

ObjectOutputStream

  1. 被操作的对象需要实现Serializable(标记接口),该类可以将Java对象的基本数据类型和图形写入OutputStream,可以使用ObjectInputStream读取对象,通过在流中使用文件可以实现对象的持久存储;
  2. 构造函数:ObjectOutputStream(OutputStream out);
  3. 常用方法:
    write×××(××× obj);
    ×××:基本数据类型或Object;
  4. 注意:
    write(int val)与writeInt(int val)的区别:前者仅读一个int的最低8位,后者写入一个32位的int值;

ObjectInputStream

ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化;
1. 构造函数:
ObjectInpuStream(InputStream in)
2. 常用方法:
××× read×××();×××基本数据类型或Object;
3. 注意:static修饰的成员变量不能被序列化;
4. transient关键字;对于非static修饰的成员如果不想被序列化可用该关键字修饰;

import java.io.*;
class ObjectStreamDemo {
    public static void main(String[] args) throws Exception{
        //writeObj();
        readObj();
    }
    public static void readObj()throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
        Person p = (Person)ois.readObject();
        System.out.println(p);
        ois.close();
    }
    public static void writeObj()throws IOException{
        ObjectOutputStream oos = 
            new ObjectOutputStream(new FileOutputStream("obj.txt"));
        oos.writeObject(new Person("lisi0",399,"kr"));
        oos.close();
    }
}
import java.io.*;
class Person implements Serializable{
    public static final long serialVersionUID = 42L;//自定义序列号ID
    private String name;
    transient int age;//非静态成员如果不想被序列化,可以用关键字transient修饰;
    static String country = "cn";//静态成员不能被序列化。
    Person(String name,int age,String country){
        this.name = name;
        this.age = age;
        this.country = country;
    }
    public String toString(){
        return name+":"+age+":"+country;
    }
}

管道流

输入输出可以之间进行连接,通过结合线程使用;

PipedOutputStream

  1. 构造函数:
    • PipedOutputStream();可以将PipedOutputStream连接到PipedInputStream来创建通信管道。PipedOutputStream作为发送端;
    • PipedOutputStream(PipedInputStream snk);参数中需传入一个管道输入流;
    • 若是空参数的构造函数则需要通过connect()方法来获取一个管道输入流,用法:
      connect(PipedInputStream snk);

PipedInputStream

  1. 概述:管道输入流应连接到管道输出流,管道输入流提供要写入管道输出流的所有数据字节,通常数据由某个线程从PipedInpuStream对象读取,并由其他线程将其写入到相应的PipedOutputStream,若为单线程容易死锁线程;
  2. 构造函数:
    • PipedInpuStream(PipedOutputStream src);构造函数无参可用connect(PipedOutputStream src)使此管道输入流连接到管道输出流
import java.io.*;
class Read implements Runnable{
    private PipedInputStream in;
    Read(PipedInputStream in){
        this.in = in;
    }
    public void run(){
        try{
            byte[] buf = new byte[1024];
            System.out.println("读取前。。没有数据阻塞");
            int len = in.read(buf);
            System.out.println("读到数据。。阻塞结束");
            String s= new String(buf,0,len);
            System.out.println(s);
            in.close();
        }catch (IOException e){
            throw new RuntimeException("管道读取流失败");
        }
    }
}
class Write implements Runnable{
    private PipedOutputStream out;
    Write(PipedOutputStream out){
        this.out = out;
    }
    public void run(){
        try{
            System.out.println("开始写入数据,等待6秒后。");
            Thread.sleep(6000);
            out.write("piped lai la".getBytes());
            out.close();
        }catch (Exception e){
            throw new RuntimeException("管道输出流失败");
        }
    }
}
class  PipedStreamDemo{
    public static void main(String[] args) throws IOException{
        PipedInputStream in = new PipedInputStream();
        PipedOutputStream out = new PipedOutputStream();
        in.connect(out);
        Read r = new Read(in);
        Write w = new Write(out);
        new Thread(r).start();
        new Thread(w).start();
    }
}

RandomAccessFile

  1. 随机访问文件,自身具备读写的方法;
    通过skipBytes(int x);seek(int x);来达到随机访问;
    此类的实例支持对随机访问文件的读取和写入;
  2. 特点:

    • 该类不算是IO体系中的子类而是直接继承Object;但他是IO包中的成员,因为它具备读和写的功能,内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置;
    • 其实完成读写的原理就是内部封装了字节输入流和输出流,通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读(r);读写(rw)等;
    • 如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常;
    • 如果模式为只读rw,操作的文件不存在,会自动创建,如果存在则不会覆盖;
  3. 构造方法:

    • RandomAccessFile(File file,String mode);
    • RandomAccessFile(String name,String mode);
      file-指定文件;
      name-系统文件名;
      mode-访问模式;
  4. 该类常用方法:

    • gerFilePointer();返回此文件的当前偏移量;
    • length();返回此文件的长度;
    • read();该功能与InputStream一样;
    • read×××;×××-基本数据类型;
    • readLine();读一行;
    • seek(long pos);设置指针偏移量;
    • setLength(long newLength);设置文件长度;
    • write(byte[] b)/(byte[] b,int off,int len)/(int b)该方法与OutputStream方法一样;
    • write×××(××× ~);×××基本数据类型;
    • skipBytes(int n);跳过指定的字节数;

注:该类的常用方式:通过seek()偏移指针,结合多线程实现分段数据同时读写,实际应用:迅雷下载;

class RandomAccessFileDemo {
    public static void main(String[] args) throws IOException{
        //writeFile_2();
        //readFile();
        //System.out.println(Integer.toBinaryString(258));
    }
    public static void readFile()throws IOException{
        RandomAccessFile raf = new RandomAccessFile("ran.txt","r"); 
        //调整对象中指针。
        //raf.seek(8*1);
        //跳过指定的字节数
        raf.skipBytes(8);
        byte[] buf = new byte[4];
        raf.read(buf);
        String name = new String(buf);
        int age = raf.readInt();
        System.out.println("name="+name);
        System.out.println("age="+age);
        raf.close();
    }
    public static void writeFile_2()throws IOException{
        RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
        raf.seek(8*0);
        raf.write("周期".getBytes());
        raf.writeInt(103);
        raf.close();
    }
    public static void writeFile()throws IOException{
        RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
        raf.write("李四".getBytes());
        raf.writeInt(97);
        raf.write("王五".getBytes());
        raf.writeInt(99);
        raf.close();
    }
}

操作基本数据类型流

DataInputStream

  1. 构造函数:
    • DataInputStream(InputStream in)使用指定的底层输入流,创建一个DataInputStream;
  2. 常用方法:
    • read(byte[] b)/(byte[] b,int off,int len)
    • read×××();×××基本数据类型;
    • skipBytes(int n);
    • readUTF();读取一个有UTF-8修改版格式编码的字符串;
    • readUTF(DataInput in);从in中读取由writeUTF写入的数据;

DataOutputStream

  1. 构造方法:
    • DataOutputStream(OutputStream out);创建一个新的数据输出流,将数据写入指定基础输出流;
  2. 常用方法:
    • write(byte[] b,int off,int len);
    • write(int b);
    • write×××(×××~);×××-基本数据类型;
    • writeChars(String s);将字符串按字符顺序写入基础输出流;
    • flush();
    • size();返回到目前为止写入此数据输出流的字节数;
    • writeUTF(String str);以与机器无关方式使UTF-8修改版编码将一个字符串写入基础输出流。

注:writeUTF();写的数据,只能用readUTF()方法读;
注:写入的不同的类型的数据时,读取也要按该顺序读取,否则会出现乱码,因为不同的数据类型的长度不同;

import java.io.*;
class DataStreamDemo {
    public static void main(String[] args) throws IOException{
        //writeData();
        //readData();
        //writeUTFDemo();
//      OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
//      osw.write("你好");
//      osw.close();
//      readUTFDemo();
    }
    public static void readUTFDemo()throws IOException{
        DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));
        String s = dis.readUTF();
        System.out.println(s);
        dis.close();
    }
    public static void writeUTFDemo()throws IOException{
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
        dos.writeUTF("你好");
        dos.close();
    }
    public static void readData()throws IOException{
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
        int num = dis.readInt();
        boolean b = dis.readBoolean();
        double d = dis.readDouble();
        System.out.println("num="+num);
        System.out.println("b="+b);
        System.out.println("d="+d);
        dis.close();
    }
    public static void writeData()throws IOException{
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
        dos.writeInt(234);
        dos.writeBoolean(true);
        dos.writeDouble(9887.543);
        dos.close();
        ObjectOutputStream oos = null;
        oos.writeObject(new O());   
    }
}

操作字节数组

ByteArrayInputStream

  1. 构造函数:
    • ByteArrayInputStream(byte[] buf);
    • ByteArrayInputStream(byte[] buf,int offset,int length);创建ByteArrayInputStream,使用buf作为其缓冲区数组;
  2. 常用方法:
    • available();返回可从输入流读取的剩余字节数;
    • read();
    • read(byte[] b,int off,int len);

ByteArrayOutputStream

  1. 构造函数:
    • ByteArrayOutputStream();创建一个新的byte数组输出流;
    • ByteArrayOutputStream(int size);创建一个新的byte数组输出流,它具有指定大小的缓冲区容量(内部封装缓冲数组);
  2. 常用方法:
    • size();返回缓冲区的当前大小;
    • toByteArray();创建一个新分配的byte数组;
    • toString();使用平台默认字符集,将缓冲区内容转换为字符串;
    • write(int b);
    • write(byte[] b,int off,int len);
    • writeTo(OutputStream out);将此byte数组输出流的全部内容写入到指定的输出流参数中;
import java.io.*;
class ByteArrayStream {
    public static void main(String[] args) {
        //数据源。
        ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());
        //数据目的
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int by = 0;
        while((by=bis.read())!=-1){
            bos.write(by);
        }
        System.out.println(bos.size());
        System.out.println(bos.toString());
    //  bos.writeTo(new FileOutputStream("a.txt"));
    }
}

操作字符数组

如果操作的数据都是字符则使用字符数组的流;该流使用方式与操作字节数组一样;

CharArrayReader

  1. 构造函数:
    • CharArrayReader(char[] buf);
    • CharArrayReader(char[] buf,int offset,int length);
  2. 常用方法:
    • read();读取单个字符;
    • read(char[] b,int off,int len);将字符读入数组的某一部分;

CharArrayWriter

  1. 构造函数:
    • CharArrayWriter();创建一个新的CharArrayWriter;
    • CharArrayWriter(int initialSize);创建一个指定大小的CharArrayWriter;
  2. 常用方法:
    • append(char c);将指定字符添加到此writer;
    • flush();刷新流到缓冲区;
    • size();返回缓冲区的当前大小;
    • toCharArray();返回输入数据的副本;
    • toString();将输入数据转换为你字符串;
    • write(char[] c,int off,int len);将字符写入缓冲区;
    • write(int c);将一个字符写入缓冲区;
    • write(String str,int off,int len);将字符串某一部分写入缓冲区;
    • writeTo(Write out);将缓冲区的内容写入另一个字符流;

操作字符串

StringReader

  1. 构造函数:
    • StringReader(String s);其源为一个字符串的字符流,创建一个新字符串,reader;
  2. 常用方法:
    • read();读取单个字符;
    • read(char[] cbuf,int off,int len);将字符读入数组的某一个部分;

StringWrite

  1. 构造函数:

    • StringWrite();使用默认初始化字符串缓冲区大小创建一个新的字符串writer;
    • StringWrite(int initialSize);使用指定初始字符串缓冲区大小创建一个新字符串 writer;
  2. 常用方法:

    • append(char c)/(CharSequence csq);将指定字符(或字符序列)添加到此 writer
    • flush();刷新该流的缓冲;
    • getBuffer();返回该字符串缓冲区本身;
    • toString();以字符串的形式返回该缓冲区的当前值;
    • write(char[] cbuf,int off,int len);写入字符数组的某一部分;
    • write(int c);写入单个字符;
    • write(String str);写入一个字符串;
    • write(String str,int off,int len);写入字符串的某一部分;

编码表

  1. 可以指定编码的流:转换流,打印流;
  2. 最常用:
    • InputStreamReader
    • OutputStreamWriter
  3. 只能打印,不能读取:
    • PrintStream
    • PrintWriter

常见编码表

  1. ASCII:美国标准信息交换码,用一个字节的7位可以表示;
  2. ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示;
  3. GB2312:中文编码表;
  4. GBK:中文编码表升级;
  5. Unicode:国际标准码;
  6. UTF-8:最多三个字节表示一个字符;

编码

字符串变成字符数组
String——byte[]:str.getBytes(String charsetName);字符串String方法;charsetName-指定编码表的字符串名称;

解码

byte[]——String:new String(byte[],charsetName);
注:如果中文字符串用“GBK”编码,用“ISO8859-1”解码,会出现乱码(因为不识别),将解码后的乱码再用“ISO8859-1”编码回去,则与“GBK”编码相同(因为不识别,编码未被改变,再用“GBK”解码,则结果为原中文字符串,如果该字符用“UTF-8”去解码,再编码,则编码将发生变化与原“GBK”编码不同,用“GBK”去解码时,结果不是原中文字符串,因为“UTF-8”页识别中文,用“UTF-8”解码再编码后,将按照“UTF-8”编码表中的字符对原解出的乱码进行编码,则结果发生变化,所以只有不识别中文的编码表才能进行解码再编码后,结果不变);
这里写图片描述

import java.util.*;
class  EncodeDemo{
    public static void main(String[] args)throws Exception {
        String s = "哈哈";
        byte[] b1 = s.getBytes("GBK");
        System.out.println(Arrays.toString(b1));
        String s1 = new String(b1,"utf-8");
        System.out.println("s1="+s1);
        //对s1进行iso8859-1编码。
        byte[] b2 = s1.getBytes("utf-8");
        System.out.println(Arrays.toString(b2));
        String s2 = new String(b2,"gbk");
        System.out.println("s2="+s2);
    }
}


import java.io.*;
class EncodeStream {
    public static void main(String[] args) throws IOException {
            //writeText();
            readText();
    }
    public static void readText()throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"gbk");
        char[] buf = new char[10];
        int len = isr.read(buf);
        String str = new String(buf,0,len);
        System.out.println(str);
        isr.close();
    }
    public static void writeText()throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
        osw.write("你好");
        osw.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值