码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员 - IO流(下)

时间:2015-08-21 01:45:53      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

用于操作字节数组的流对象
ByteArrayInputStream:在构造的时候需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造时,不用定义数据目的地,
因为该对象中已经封装流一个可变长度的字节数组,该数组就为数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭,
而且其不会产生IO异常。
这种方法是用流的思想操作数组。
注意:用于操作字符数组和操作字符串的流对象,基本与ByteArrayStream相同,详见说明书。

import java.io.*;
class EByteArrayDemo{
    public static void main(String[] args){
        ByteArrayInputStream bis = //数据源
            new ByteArrayInputStream("ABCDEFD".getBytes());
        ByteArrayOutputStream bos = //数据目的地
            new ByteArrayOutputStream ();
        int by = 0 ;
        while ((by=bis.read())!=-1){//将源数据长度赋予by,并判断是执行到文件末尾
            bos.write(by);            //将输入流中的字节数组存入输出流中的字节数组
        }
        System.out.println(bos.size());       //打印输出流的长度
        System.out.println(bos.toString());      //打印输出流的字符串形式
    }
}

//DataStream可以用于操作基本数据类型的流对象。
//局限性,使用时必须按照文件的类型,依次取出。

import java.io.*;
class EDataStreamDemo
{
    public static void main(String[] args) throws IOException
    {
        writeData();
        readData();
    }
    public static void readData() throws IOException
    {
        DataInputStream dis =
            new DataInputStream (new FileInputStream("d:\\demodata.txt"));
        //该方法必须按存入的顺序取出。
        int num = dis.readInt();        //读取整数
        boolean b = dis.readBoolean();    //读取Boolean类型数据
        double d = dis.readDouble();    //读取Double类型数据
        String utf = dis.readUTF();        //读取UTF编码数据
        System.out.println("num="+num);
        System.out.println("b="+b);
        System.out.println("d="+d);
        System.out.println("UTF="+utf);
        dis.close();
    }
    public static void writeData() throws IOException
    {
        DataOutputStream dos =
            new DataOutputStream(new FileOutputStream("d:\\demodata.txt"));
        dos.writeInt(234);
        dos.writeBoolean(true);
        dos.writeDouble(4323.355);
        dos.writeUTF("你好");
        dos.close();
    }
}

管道流
PipedInputStream PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
思路:
1.创建Read类,覆写run方法,在run方法中实现文件读取并存储到s字符串中并打印出来。
2.创建Write类,覆写run方法,在run方法中实现文件的写入
3.分别创建输入和输出线程然后开启。

import java.io.*;
class EPipedStreamDemo{
    public static void main(String[] args) throws IOException{
        PipedInputStream in = new PipedInputStream();    //定义输入流
        PipedOutputStream out = new PipedOutputStream();//定义输出流
        in.connect(out);                //将输出流与输入流连接
        Read r = new Read(in);            //建立输入流的Read对象    
        Write w = new Write (out);        //建立输出流的Write对象
        (new Thread(r)).start();        //分别建立输入流和输出流的线程并开启
        (new Thread(w)).start();
    }
}
class Read implements Runnable{            //定义Read类实现Runnable接口
    private PipedInputStream in;        
    Read(PipedInputStream in){            //将输入流传入
        this.in = in;
    }
    public void run(){                            //在run方法中覆写读取操作
        try{
            byte [] byt = new byte[1024];        //定义字节数组
            int len = in.read(byt);                //将读取的内容写入字节数组
            String s = new String(byt ,0 ,len);    //将字节数组转为字符串    
            System.out.println(s);                //打印读取的数据
            in.close();
        }
        catch (IOException e){                    //定义IO异常的处理方法
            throw new RuntimeException("管道读取流运行失败");
        }
    }
}
class Write implements Runnable{        //定义Write实现Runnable接口
    private PipedOutputStream out;                
    Write(PipedOutputStream out){        //将输出流传入
        this.out = out ;
    }
    public void run(){                    //在run方法中覆写写入操作
        try{
            out.write("piped lai la".getBytes());//写入字符串的字节数据
            out.close();
        }
        catch (IOException e){            //定义IO异常处理方法
            throw new RuntimeException("管道输出流运行失败");
        }
    }
}

操作对象的流
ObjectInputStrea ObjectOutputStream

需求:
实现操作对象流对对象的永久存储和数据读取。
思路:
1.定义Person类封装属性
2.定义对象输出流与目标文件关联,并向其写入Person对象数据
3.定义对象输入流与目标文件关联,并读取其中存储的Person对象数据

import java.io.*;
class Person implements Serializable{ //注意实现接口
    private String name;                //定义成员变量
    private int age;
    Person (String name ,int age){        //定义构造函数
        this.name = name;
        this.age = age;
    }
    public String toString(){            //覆写toString方法
        return name+":"+age;
    }
}
class  EObjectStreamDemo{
    public static void main(String[] args) throws Exception{
        writeObj();                        //调用写入对象方法
        readObj();                        //调用读取对象方法
    }
    public static void readObj() throws Exception{    //定义读取对象方法
        ObjectInputStream ois =                        //将对象输出流与文件相关联
            new ObjectInputStream(new FileInputStream("d:\\person.txt"));
        Person p =(Person)ois.readObject();    //依次读取文件中的对象数据,注意强转为Person对象
        System.out.println(p);                //在控制台上打印对象
        ois.close();
    }
    public static void writeObj() throws Exception{    //定义写入对象方法
        ObjectOutputStream oos =                    //将输出流与文件相关联
            new ObjectOutputStream(new FileOutputStream("d:\\person.txt"));
        oos.writeObject(new Person("lili",39));        //输出新对象
        oos.close();
    }
}

RandomAccessFile:随机读取流
该类不算是IO体系的子类,而是直接继承自Object
但是他是IO包中的成员,因为他具备读写功能。
可以通过getFilePointer获取指针位置。
同时可以seek改变指针的位置
其完成读写的原理就是在内部封装流字节输入流和输出流。
通过构造函数可以看出,本类只能操作文件,及固定模式
模式: r 只读 :不会创建文件,只会读取已存在文件,如果文件不存在就会报异常。
rw 读写:该对象的构造函数要操作的文件不存在,会自动创建;如果存在不会覆盖。

import java.io.*;
class ERandomDemo{
    public static void main(String[] args) throws IOException{
        //writeR();
        writeRR();
        readR();
    }
    public static void readR() throws IOException{
        //关联文件和随机读取流,模式处写"r",表示只读
        RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","r");
        byte[] byt = new byte[4];//设置的姓名4个字节,年龄4个字节,所以设置4个字节的数组
        //调整指针位置,只能往后移动
        raf.seek(8);
        //跳过指定的字节数
        //raf.skipByte(int n);
        raf.read(byt);            //将数据写入字节数组
        String name = new String(byt);
        int age = raf.readInt();//读取整数操作
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        raf.close();
    }
    //重点掌握,该方法通过同时多线程分别输入不同位段,实现多线程输入(类似迅雷等下载软件的方法)
    //仅该方法可以实现多线程多端输入。
    public static void writeRR() throws IOException{
        RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","rw");
        raf.seek(8*2);
        raf.write("周期".getBytes());
        raf.writeInt(33);
        raf.close();
    }
    public static void writeR() throws IOException{
        RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","rw");
        raf.write("mik1".getBytes());
        //注意,使用writeInt(),而不用write()
        //因为write()写入时只会使用1个字节,数字过大时会出现数据丢失
        //writeInt()写入时占用4个字节。注意:1个中文2个字节
        raf.writeInt(31);
        raf.write("mik2".getBytes());
        raf.writeInt(32);
        raf.write("mik3".getBytes());
        raf.writeInt(33);
        raf.close();
    }
}

转换流的编码表
编码:字符串变成字节数组
String-->byte[]: str.getBytes(charsetName)
解码:字节数组变成子符数组
byte[]-->String: new String(byte[],charsetName)
注意:1.GBK码的中文用utf-8解码后源码会变。因为他们都识别中文且中文码不同,
一种识别中文的码表转成不识别中文的码表就不会出现这种能情况。
2.GBK码的"联通"字符符合utf-8的编码形式。

import java.io.*;
import java.util.*;
class  FTransDemo{
    public static void main(String[] args) throws IOException{
        writeTran();
        readTran();
    }
    public static void writeTran() throws IOException{
        BufferedWriter  bfws =         //定义转换输出流与文件关联
            new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\demotrans.txt"),"GBK"));
        bfws.write("你好");             //写入"你好"
        bfws.close();
    }
    public static void readTran() throws IOException{
        BufferedReader  bfrs =        //定义转换输入流与文件关联
            new BufferedReader(new InputStreamReader(new FileInputStream("d:\\demotrans.txt")/*,"utf-8"*/));
        char [] byt = new char [1024];//定义字符数组
        int len =0;
        while((len=bfrs.read(byt))!=-1){//将缓冲区内的数据写入字符数组,并判断是否已到文件末尾
            String s1 = new String(byt,0,len);//将字符数组转换为字符串
            //打印按照指定码表的编码
            System.out.println(Arrays.toString(s1.getBytes("GBK")));
            System.out.println(Arrays.toString(s1.getBytes("utf-8")));
            System.out.println(s1);
        }
        bfrs.close();
    }
}

IO流应用实例

需求:有5个学生,每个学生有3门课的成绩
从键盘中输入以上数据(包括姓名,3门课的成绩)
输入格式如:张三,30,40,60,计算出总成绩
并把学生信息和计算出的总分高低顺序存放在磁盘文件中"stud.txt"中
1.描述学生对象
2.定义一个可操作的学生对象工具类。
思想:
1.通过键盘获取一行数据,并将该行中的信息取出封装成学生对象。
2.因为学生有很多,那么久需要存储,使用到集合,因为要对学生的总分排序
所以用TreeSet存储。
3.将集合的信息写入到一个文件中。

import java.io.*;
import java.util.*;
public class StudentSort {

    public static void main(String[] args) throws NumberFormatException, IOException {
        // TODO Auto-generated method stub
        TreeSet<Student> stuSet = (TreeSet<Student>) StudentInfo.getStudent();
        for (Student s : stuSet){
            System.out.println(s+","+s.getSum());
        }
    }
}
class Student implements Comparable<Student>{
    private String name;                //定义学生的属性
    private int  math,cn,en;            
    private int sum;
    Student (String name, int math,int cn,int en){//定义构造函数
        this.name = name;
        this.math = math;
        this.cn = cn;
        this.en = en;
        sum = math + cn + en;
    }
    public int compareTo(Student s){        //覆写排序方法,为先判断总分,再判断名字
        int num = new Integer(s.sum).compareTo(new Integer(this.sum));
        if(num==0)
            return s.name.compareTo(this.name);
        return num;        
    }
    public int hashCode(){                    //覆写hashcode获取方式
        return name.hashCode()+sum*78;
    }
    public boolean equals (Object obj){    //覆写比较方法,定义姓名总分均相同的对象为同一对象
        if(!(obj instanceof Student))    //判断比较对象是否为学生类型
            throw new ClassCastException("类型不匹配");
        Student s = (Student) obj;        //将比较对象向下转型为Student
        return this.name.equals(s.name) && this.sum==s.sum;
    }
    public String toString(){            //覆写头String方法
        return "student  "+name+":"+math+","+cn+","+en;
    }
    public String getName(){
        return name;
    }
    public int getSum(){
        return sum;
    }
}
class StudentInfo{
    public static Set<Student> getStudent() throws NumberFormatException, IOException{
        BufferedReader bufr =    //将输入流与键盘关联
            new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        TreeSet stuSet = new TreeSet();
        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]));
            stuSet.add(stu);
        }
        return stuSet;    //返回学生的集合
    }
}

在控制台上输入

技术分享

输出结果

技术分享

黑马程序员 - IO流(下)

标签:

原文地址:http://www.cnblogs.com/myblog-cl/p/4746655.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!