黑马程序员-java基础之IO其他常用类2和编码

--------------------- android培训java培训、java学习型技术博客、期待与您交流! -------------------

序列化

概述:将已有对象进行本地持久化存储,存入硬盘中,存储后的对象可以进行网络传输,通过ObjectInputStreamObjectOutputStream进行操作。

常用方法

 ObjectInputStream

readObject()//读取ObjectInputStream中读取对象

ObjectOutputStream

   writeObject()//将对象写入ObjectOutputStream被写入的对象需要实现Serializable接口

操作步骤

Serializble接口

概述:类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。用于给类指定一个UID,该UID是通过类中的可序列化成员的数值签名运算出来的一个long型的值,只要成员中没有发生变化那么该值每次运算结果都一样,该值用于判断被序列化的对象和类文件是否兼容该接口中没有方法,像这样的接口我们一边称之为标记接口

自定义UID static final long SeriviableUID=42L

注意:静态成员变量,不会被序列化,对于非静态成员,可以通过transient关键字让其不能序列化。没有指定UID的值时,当类中的成员修改后之前序列化的对象无法读取

序列化对象

代码示例

import java.io.*; 

//创建Peason类,实现Serializable接口 

class Peason implements Serializable 

    //自定义serialVersionUID版本号 

    public final static long serialVersionUID=32L; 

     

    private String name; 

    transient private int age;    

    static String country="CN";//静态成员不能序列化 

     

    //构造函数 

    Peason(String name,int age,String id,String country) 

    { 

        this.name=name; 

        this.age=age; 

        this.country=country; 

    } 

    //复写toString方法 

    public String toString() 

    { 

        return name+":"+age+":"+country;  

    } 

 

//序列化测试类 

class ObjectStreamDemo  

    public static void main(String[] args)  

    { 

        //指定文件 

        File file =new File("3.txt"); 

        Peason p=new Peason("zhangsan",25); 

 

        //序列化指定对象 

        writeObj(p,file); 

 

        //反序列化 

        readObj(file); 

         

    } 

    //将指定对象序列化到指定文件中 

    public static void writeObj(Peason p,File file) 

    { 

        ObjectOutputStream oos=null;

                                                                                                                             try          {    

            //创建写入流对象,关流文件 

            oos=new ObjectOutputStream(new FileOutputStream(file)); 

            oos.writeObject(p);//写入对象数据 

        } 

        catch (IOException e) 

        { 

            throw new RuntimeException("对象写入失败"); 

        } 

        finally 

        { 

            try 

            { 

                if(oos!=null) 

                    oos.close(); 

            } 

            catch (IOException e) 

            { 

                throw new RuntimeException("关流失败"); 

            } 

        } 

    } 

 

    //读取指定文件中的对象,也称反序列化 

    public static void readObj(File file) 

    { 

        ObjectInputStream ois=null; 

        try 

        { 

            //创建读取流对象,关联文件 

            ois =new ObjectInputStream(new FileInputStream(file)); 

            //读取文件中的对象 

            Peason p=(Peason)ois.readObject(); 

            System.out.println(p); 

        } 

        catch (Exception e) 

        { 

            throw new RuntimeException("文件读取对象失败"); 

        } 

        finally 

        { 

            try 

            { 

                if(ois!=null) 

                    ois.close(); 

            } 

            catch (IOException e) 

            { 

                throw new RuntimeException("关流失败"); 

            } 

        } 

    } 

}                                                                                                                                      

管道流

概述:对应对象PipedInputStream PipedOutputStream

特点:管道流对应的输出和输入对象可以进行连接,不需要通过容器来进行临时存储,通常在使用这两个流时,需要加入多线程技术,也就是让读写同时进行。

在多线程内同时运行

代码示例

import java.io.*;  

class Read implements Runnable 

    private PipedInputStream in; 

    Read(PipedInputStream in) 

    { 

        this.in=in; 

    } 

    //覆盖run方法 

    public void run() 

    {  

        try 

        { 

            //用来存储读到的字节 

            byte[] by=new byte[1024]; 

            System.out.println("读取前。。没有数据阻塞"); 

            //读取流中数据 

            int len=in.read(by); 

            System.out.println("读到数据。。阻塞结束"); 

 

            //将字节数组转换为字符串打印输出 

            String s=new String(by,0,len); 

 

            System.out.println(s); 

        } 

        catch (IOException e) 

        { 

            throw new RuntimeException("读取数据失败"); 

        } 

        finally 

        { 

            try 

            { 

                if(in!=null) 

                    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("开始写入数据,等待3秒后。"); 

            Thread.sleep(3000); 

            //写入数据到管道流中 

            out.write("piped shi shem ma?".getBytes()); 

        } 

        catch (Exception e) 

        { 

              throw new RuntimeException("流写入失败");

        } 

        finally 

        { 

            try 

            { 

                if(out!=null) 

                    out.close();

                                                                                                                                    }

            catch (IOException e) 

            { 

                throw new RuntimeException("流关闭失败"); 

            } 

        } 

    }    

 

class PipedStreamDemo  

    public static void main(String[] args)  

    { 

        try

                                                                                                                            {

           //创建管道流对象,并关联 

           PipedInputStream in=new PipedInputStream(); 

           PipedOutputStream out=new PipedOutputStream(); 

           in.connect(out); 

 

            //启动线程 

           new Thread(new Read(in)).start(); 

           new Thread(new Write(out)).start(); 

         } 

         catch (IOException e) 

         { 

           throw new RuntimeException("管道流关联失败"); 

         }        

    } 

RandomAccessFile

概述:该对象并不是流体系中的一员,该对象中封装了字节输出流和字节输入流,还同时封装了一个字节数组缓冲区,通过内部指针来操作数组中的数据

特点:该对象只能操作文件,并且该对象可以进行读和写两种操作

构造方法

RandomAccessFile(File file,String mod)

当传入模式为只读r时,不会自动创建文件,当文件不存在时,会出现异常,当模式为读写rw时,文件不存在就会自动创建文件,文件存在不会覆盖

常用方法

  seek(long pos)//指定指针的位置,没有设定指针的情况下,默认是在文件开头处,可以使用seek进行随机访问。

  skipBytes()//跳过指定的字节数,只可往后跳,不可往前跳

  getFilePointer()//获取指针位置

利用以上方法可以可以完成对文件数据的随机访问,想读哪里就读哪里。实际开发中可用于多线程下载

代码演示

import java.io.*; 

class RandomAccessFileDemo

{  

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

    { 

        //指定文件 

       File file =new File("ran.txt"); 

 

        //写数据 

        writeFile(file); 

 

        //读数据 

        readFile(file); 

 

    } 

 

    //读取指定文件中的数据 

    public static void readFile(File file)throws IOException  

    { 

        //创建对象 

        RandomAccessFile raf=new RandomAccessFile(file,"r"); 

         

        //设置指针位置 

        raf.seek(8); 

 

        //设置跳过的字节数 

        //raf.skipBytes(8); 

 

        //读取四个字节存入 

        byte[] by=new byte[4]; 

        //读数据 

        raf.read(by); 

        //将存入数据的字节数组转换为字符串 

        String name=new String(by); 

        //根据写入规律,读取年龄,这里用到了读一个int方法 

        int age=raf.readInt(); 

         

       System.out.println("name="+name+"age="+age); 

 

        raf.close();//关流 

    } 

 

    //将数据写入指定文件中 

    public static void writeFile(File file)throws IOException  

    { 

        //创建对象 

        RandomAccessFile raf=new RandomAccessFile(file,"rw"); 

      

        raf.write("李四".getBytes());

        raf.writeInt(23);    

        raf.seek(8*0);//改变指针 

        raf.write("张三".getBytes()); 

        raf.writeInt(23); 

        raf.skipBytes(8*2);//改变指针 

        raf.write("王五".getBytes()); 

        raf.writeInt(35); 

 

        raf.close();//关流     

    } 

}                                                                                                                                      

                                                                                                                                

 

操作基本数据类型的流

概述:操作基本数据类型对象,DataOutputStreamDataInputStream ,这两个类型的对象,内包含了读写各种基本数据类型的方法

常用方法

  操作byte

     readbyte()

       writeByte()

  操作int

       readInr()

       writeInt()

  操作boolean

       readBoolean()

       writeBoolran()

  操作double

       readDouble()

       writeDouble()

  操作long

        readLong()

        writeLong()                                                                                                            

  指定编码为UTF-8修改版进行读写

readUTF()

        writeUTF()

代码演示

import java.io.*;

class DataStreamDemo

{

public static void main(String[] args)

{

    DataOutputStream dos =

                    new DataOutputStream(new FileOutputStream("c:\5.txt"));

    dos.writeInt(255);

    dos.writeBoolean(true);

    dos.writeDouble(245.22);                                                                                       

}

}

操作数组的流对象

包括:字节数组

      字符数组等

概述:对于操作数组的对象:共性该源是这些流,该目的也是这些流,因此这些流并没有调用系统资源,使用的是内存中的数组,也因此在使用时不需要close

以字节数组做代码示例

import java.io.*;

class ByteArraysDemo

{

public static void main(String[] args)

{

        ByteArrayInputStream bis = new ByteArrayInputStream("字节数组".getBytes());

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        int by=0

        while((by=bis.read())!=-1)

{

    bos.write(by);

}                                                                                                                           

        System.out.println(bos.size);

 

}

}

字符编码

概述:计算机只能识别二进制数据,为了方彪应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,这就是编码。

常见编码表

ASCII:美国标准信息交换码,使用的是1个字节的7位来表示该表中的字符

ISO8859-1:拉丁码表,使用一个字节的8位表示

GBK2312:中文编码表

GBK:GBK2312升级版,加入更多的中文字符,打头的是两个高位为1的两个字节编码为负数。

Unicode:国际编码表,融合多种文字,所有文字都用两个字节来表示

UTF-8Unicode的升级,对每一个字节都加入了标识头

编码:字符串String转成byte数组的过程,称为编码

解码:字节数组转成字符串的过程,称为解码

编解码注意事项

1、如果编码失败,解码就没意义了。

2、如果编码成功,解码出来的是乱码,,则需对乱码通过再次编码(用解错码的编码表),然后再通过正确的编码表解码。针对于服务器中的IOS8859-1

3、如果用的是GBK编码,UTF-8解码,此时通过再次编码后解码的方式,就不能成功了,因为UTF-8也支持中文,在UTF-8解的时候,会将对应的字节数改变,所以不会成功。

4中文的联通这两个字的二进制与UTF中的两个字节打头的相投,所以在文本文件中,如果单独写联通时,记事本会用UTF-8来进行解码,就会显示乱码

                                                                                                                                       

--------------------- android培训java培训、java学习型技术博客、期待与您交流! -------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值