zoukankan      html  css  js  c++  java
  • Java IO(四)

       对象序列化

       对象序列化又叫对象的持久化,对象的串行化(或反串行化)

       当使用Serializable接口实现序列化操作时,如果一个对象中的某个属性不希望被序列化,则可以使用transient关键字进行声明。

     static修饰的静态属性也不能被序列化,序列化的只是堆内存中对象的属性。

    ANY-ACCESS-MODIFIER(任意的访问修饰符) static final long serialVersionUID = 42L;

       语句的作用:给类定义一个固定标识,为了序列化方便,新的类还能操作曾经被序列化的对象。

       举例说之,示例代码如下:

       序列化的Person类:

    import java.io.Serializable;
    
    public class Person implements Serializable {
        /*
         * 给类定义一个固定标识,为了序列化方便,新的类还能操作曾经被序列化的对象。
         */
        public static final long serialVersionUID = 42L;
        private String name;
        transient int age;//transient保证其值在堆内存中存在,不被序列化到文件。
        static String country = "cn";//静态不能序列化
        public Person(String name, int age, String country) {
            this.name = name;
            this.age = age;
            this.country = country;
        }
        public String toString() {
            return name + "::" + age+":" + country;
        }
        
    }

       序列化Person类的代码:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    public class ObjectStreamDemo {
    
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            //writeObj();
            readObj();
        }
        
        public static void readObj() throws IOException, ClassNotFoundException {
            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();
        }
    
    }

       

       管道流

       管道流的主要作用是可以进行两个线程间的通信。反正管道流结合的是多线程技术,可以查看JDK帮助文档。

       示例代码如下:

    import java.io.IOException;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    
    class Read implements Runnable {
        private PipedInputStream in;
        
        Read(PipedInputStream in) {
            this.in = in;
        }
        @Override
        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;
        }
        @Override
        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("管道输出流失败");
            }
        }
        
        
    }
    public 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

       该类不算是IO体系中子类,而是直接继承自Object。但是它是IO包中的成员,因为它具备读和写的功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针的位置。同时可以通过seek改变指针的位置。其实完成读写的原理就是内部封装了字节流输入流和输出流

       通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读r,读写rw等。

    • 如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。
    • 如果模式为rw,操作的文件不存在,会自动创建,如果存在则不会覆盖(会修改文件)。

       示例代码如下:

    import java.io.IOException;
    import java.io.RandomAccessFile;
    
    public class RandomAccessFileDemo {
    
        public static void main(String[] args) throws IOException {
            //writeFile();
            writeFile_2();
            //readFile();
            //System.out.println(Integer.toBinaryString(258));
        }
        
        public static void readFile() throws IOException {
            RandomAccessFile raf = new RandomAccessFile("ran.txt", "r");
            //raf.write("haha".getBytes());
            
            /*
             * 调整对象中的指针
             */
            //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();
        }
    
    }

       图解原理:

       DataOutputStream与DataInputStream

       可以用于操作基本数据类型的数据的流对象。

       示例代码:

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    
    public class DataStreamDemo {
    
        public static void main(String[] args) throws IOException {
            //writeData();
            //readData();
            //writeUTFDemo();
            /*
            OutputStreamWriter osw = new OutputStreamWriter(
                    new FileOutputStream("D:\java\lib\wo\gbk.txt"), "gbk");
            osw.write("你好");
            osw.close();
            */
            readUTFDemo();
        }
        
        public static void readUTFDemo() throws IOException {
            DataInputStream dis = new DataInputStream(
                    new FileInputStream("D:\java\lib\wo\utf.txt"));
            String s = dis.readUTF();
            System.out.println(s);
            dis.close();
        }
        
        public static void writeUTFDemo() throws IOException {
            DataOutputStream dos = new DataOutputStream(
                    new FileOutputStream("D:\java\lib\wo\utfdata.txt"));
            dos.writeUTF("你好");
            dos.close();
        }
        
        public static void readData() throws IOException {
            DataInputStream dis = new DataInputStream(new FileInputStream("D:\java\lib\wo\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("D:\java\lib\wo\data.txt"));
            dos.writeInt(234);
            dos.writeBoolean(true);
            dos.writeDouble(9887.543);
            dos.close();
        }
    
    }

       内存操作流

       ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。

       ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该数据对象已经内部封装了可变长度的字节数组。这就是数据目的地。

       在流操作规律讲解时:

       源设备:

    1. 键盘:System.in
    2. 硬盘:FileStream
    3. 内存:ArrayStream

       目的设备:

    1. 控制台:System.out
    2. 硬盘:FileStream
    3. 内存:ArrayStream

       用流的读写思想来操作数组。

       示例代码如下:

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    
    public class ByteArrayDemo {
    
        public static void main(String[] args) {
            //数据源
            ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEF".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"));
        }
    
    }

       字符编码

       示例代码如下:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    
    public 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-8.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-8.txt"), "UTF-8");
            osw.write("你好");
            osw.close();
        }
    
    }

       图解原理:

       编码:字符串变成字节数组。String--->byte[];   str.getBytes(charsetName);

       解码:字节数组变成字符串。byte[]--->String;   new String(byte[], charsetName);

       示例代码如下:

    import java.io.UnsupportedEncodingException;
    import java.util.Arrays;
    
    public class EncodeStream1 {
    
        public static void main(String[] args) throws UnsupportedEncodingException {
            /*
            String s = "你好";
            byte[] b1 = s.getBytes("gbk");
            System.out.println(Arrays.toString(b1));
            String s1 = new String(b1, "iso8859-1");
            System.out.println("s1="+s1);
            
            // 对s1进行iso8859-1编码
            byte[] b2 = s1.getBytes("iso8859-1");
            System.out.println(Arrays.toString(b2));
            String s2 = new String(b2, "gbk");
            System.out.println("s2="+s2);
            */
            
            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进行utf-8编码
             */
            byte[] b2 = s1.getBytes("utf-8");
            System.out.println(Arrays.toString(b2));
            String s2 = new String(b2, "gbk");
            System.out.println("s2="+s2);
            
        }
    }

       图解原理1:

    图解原理2:

       应用:

       

       一个非常特殊的例子:新建一个文本文档,输入"联通"二字,保存并退出,再次打开此文本文档时,会显示乱码!!!

       分析:

       

       综合练习:有五个学生,每个学生有3门课的成绩,从键盘输入以上数据(包括姓名,三门可成绩),输入的格式:如:zhangsan,30,40,60计算出总成绩,并把学生的信息和计算出的总分数按高低顺序存放在磁盘文件"stud.txt"中。

       分析:

    1. 描述学生对象。
    2. 定义一个可以操作学生对象的工具类。   

       思路:

    1. 通过获取键盘录入的一行数据,并将该行中的信息取出封装成学生对象。
    2. 因为学生对象有很多,那么就需要存储,使用到集合。因为要对学生的总分进行排序,所以可以使用TreeSet。
    3. 将集合的信息写入到一个文件中。

       代码:

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Set;
    import java.util.TreeSet;
    
    class Student implements Comparable<Student> {
        private String name;
        private int ma, cn, en;
        private int sum;
        
        public Student(String name, int ma, int cn, int en) {
            this.name = name;
            this.ma = ma;
            this.cn = cn;
            this.en = en;
            sum = ma + cn + en;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getMa() {
            return ma;
        }
    
        public void setMa(int ma) {
            this.ma = ma;
        }
    
        public int getCn() {
            return cn;
        }
    
        public void setCn(int cn) {
            this.cn = cn;
        }
    
        public int getEn() {
            return en;
        }
    
        public void setEn(int en) {
            this.en = en;
        }
    
        public int getSum() {
            return sum;
        }
    
        public void setSum(int sum) {
            this.sum = sum;
        }
        
        public int hashCode() {
            return name.hashCode() + sum * 78;
        } 
        
        public boolean equals(Object obj) {
            if(!(obj instanceof Student))
                throw new ClassCastException("类型不匹配");
            Student s = (Student) obj;
            return this.name.equals(s.name) && this.sum == s.sum;
        }
        
        public String toString() {
            return "student["+name+", "+ma+", "+cn+", "+en+"]";
        }
    
        @Override
        public int compareTo(Student s) {
            int num = new Integer(this.sum).compareTo(new Integer(s.sum));
            if(num == 0)
                return this.name.compareTo(s.name);
            return num;
        }
    }
    class StudentInfoTool {
        
        public static Set<Student> getStudents() throws IOException {
            return getStudents(null);
        }
        
        public static Set<Student> getStudents(Comparator<Student> cmp) throws IOException {
            BufferedReader bufr = new BufferedReader(
                    new InputStreamReader(System.in));
            
            String line = null;
            Set<Student> stus = null;
            if(cmp == null)
                stus = new TreeSet<Student>();
            else
                stus = new TreeSet<Student>(cmp); 
            while((line = bufr.readLine()) != null){
                if("over".equals(line))
                    break;
                String[] info = line.split(",");
                Student stu = new Student(info[0], Integer.parseInt(info[1]),
                                                   Integer.parseInt(info[2]),
                                                   Integer.parseInt(info[3]));
                stus.add(stu);
            }
            bufr.close();
            return stus;
        }
        
        public static void write2File(Set<Student> stus) throws IOException {
            BufferedWriter bufw = new BufferedWriter(
                    new FileWriter("stuinfo.txt"));
            for(Student stu : stus) {
                bufw.write(stu.toString() + "	");
                bufw.write(stu.getSum() + "");//分数变为字符串再写进去,因为写入int值,只是写入的最后1个字节
                bufw.newLine();
                bufw.flush();
            }
            bufw.close();
        }
    }
    
    public class Test {
    
        public static void main(String[] args) throws IOException {
            
            Comparator<Student> cmp = Collections.reverseOrder();//反转Student类中的默认排序
            
            Set<Student> stus = StudentInfoTool.getStudents(cmp);
            StudentInfoTool.write2File(stus);
        }
    
    }
    View Code

      

  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/yerenyuan/p/5276909.html
Copyright © 2011-2022 走看看