IO流4(IO中的其他流、编码)

来源:互联网 发布:淘宝店不刷信誉可以吗 编辑:程序博客网 时间:2024/05/21 11:00

一、操作对象流


ObjectInputStream

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


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;    }}

二、 管道流

      PipedInputStream和PipedOutputStream:输入输出可以直接进行连接,通过结合线程使用。

示例:

import java.io.PipedInputStream;import java.io.PipedOutputStream;public class PipedStream{public static void main(String[] args) throws Exception {PipedInputStream input = new PipedInputStream();PipedOutputStream output = new PipedOutputStream();input.connect(output);  new Thread(new Input(input)).start();new Thread(new Output(output)).start();}}class Input implements Runnable{private PipedInputStream in; Input(PipedInputStream in){this.in = in;}public void run(){try{byte[] buf = new byte[1024];int len = in.read(buf);String s = new String(buf,0,len);System.out.println( "s=" + s);  in.close();} catch(Exception e){e.printStackTrace();}}}class Output implements Runnable{private PipedOutputStream out; Output(PipedOutputStream out){this.out = out;}public void run(){try{out.write( "hi,管道来了!" .getBytes());out.close();} catch(Exception e){e.printStackTrace();}  }}



RandomAccessFile

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

     

       特点:

                1.该类不算是IO体系中的子类而是直接继承Object;但他是IO包中的成员,因为它具备读和写的功能,内部封装了一个数             组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置;

                2.其实完成读写的原理就是内部封装了字节输入流和输出流,通过构造函数可以看出,该类只能操作文件,而且操作文件还                    有模式:只读(r);读写(rw)等;

                3.如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常;

                4. 如果模式为只读rw,操作的文件不存在,会自动创建,如果存在则不会覆盖;

 

      构造方法:

               RandomAccessFile(File fileString mode)

               RandomAccessFile(String nameString mode) 
               file-指定文件; 
               name-系统文件名; 
               mode-访问模式;

 

      该类常用方法:

               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与DataOutputStream

DataInputStream

示例:
import java.io.DataInputStream;import java.io.FileInputStream;import java.io.IOException;public class DataStreamDemo{public static void main(String[] args) throws IOException {readData();}public static void readData() throws IOException {DataInputStream dis = new DataInputStream(newFileInputStream("data.txt" )); String str = dis.readUTF(); System.out.println(str);dis.close();}}




DataOutputStream

示例:
import java.io.DataOutputStream;import java.io.FileOutputStream;import java.io.IOException;public class DataStreamDemo{public static void main(String[] args) throws IOException {writeData();}public static void writeData() throws IOException {DataOutputStream dos = new DataOutputStream(newFileOutputStream("data.txt" )); dos.writeUTF( "您好");dos.close();}}




四、操作字节数组

          ByteArrayInputStream与ByteArrayOutputStream

          关闭字节数组输出输出流无效,因为它们没有调用底层资源,所有的操作都是在内存中完成的。

示例:
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;public class ByteArrayStreamDemo{public static void main(String[] args) throws IOException {ByteArrayInputStream bis = new ByteArrayInputStream("abcdef".getBytes());ByteArrayOutputStream bos = new ByteArrayOutputStream();int ch = 0;while((ch = bis.read()) != -1){bos.write(ch);}System.out.println(bos.toString());}}




五、编码表
          
          1.编码表的由来
                     计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
                     就将各个国家的文字用数字来表示,并一一对应,形成一张表,这就是编码表。

          2.常见的编码表

                     ASCII:美国标准信息交换码,用一个字节的7位可以表示。
                     ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。
                     GB2312:中国的中文编码表。
                     GBK:中国的中文编码表升级,融合了更多的中文文字符号。
                     Unicode:国际标准码,融合了多种文字。
                     所有文字都用两个字节来表示,Java语言使用的就是unicode
                     UTF-8:最多用三个字节来表示一个字符。

          

         3.编码

                 

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

           

         4.解码

                   byte[]——Stringnew 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();    }}

练习:
          在java中,字符串“abcd”与字符串“ab您好”的长度是一样,都是四个字符。
          但对应的字节数不同,一个汉字占两个字节。
          定义一个方法,按照最大的字节数来取子串。
          如:对于“ab你好”,如果取三个字节,那么子串就是ab与“你”字的半个。
          那么半个就要舍弃。如果取四个字节就是“ab你”,取五个字节还是“ab你”。
import java.io.IOException;public class Test{public static void main(String[] args) throws IOException {String str = "ab你好cd谢谢" ;int len = str.getBytes("gbk" ).length;for(int x = 1; x < len; x++){System.out.println( "截取的" + (x + 1) + "个节结果是:" +cutStringByByte(str,x+1));}}public static String cutStringByByte(String str,int len) throws IOException {byte[] buf = str.getBytes("gbk" );int count = 0;for(int x = len - 1; x >= 0; x--){//gbk编码的值两个字节值一般都为负,记录连续的负数个数,如果为奇数,则舍弃if(buf[x] < 0)count++;elsebreak;}if(count % 2 == 0){return new String(buf,0,len,"gbk");} else{return new String(buf,0,len-1,"gbk");}} }




0 0
原创粉丝点击