美文网首页
Java中的IO框架流三

Java中的IO框架流三

作者: 征程_Journey | 来源:发表于2017-05-21 11:07 被阅读0次

    1      IO(三)No20

    1.1    Properties 属性集

    Properties属性集,主要用于操作配置属性,

    是以键值对的方式来保存属性,并且都是String类型

    继承自Hashtable类,所以是一个Map集合,具有Map接口中的所有方法,但是在保存和读取数据的时候不建议使用put和get方法,因为有可能会出现异常,建议使用Properties中特有的方法进行数据的存储

    常用方法:

    1、添加、获取

    setProperty(String key,String value):添加键值对

    getProperty(String key):通过键获取值《getProperty(Stringkey)

    getProperty(Stringkey,StringdefaultValue)》如果键不存在返回默认值

    2、保存、加载(配合IO流使用)

    store():将数据通过输出流写到指定文件中

    store(OutputStreamout,Stringcomments)

    store(Writerwriter,Stringcomments)参数二:代表注释

    load():通过输入流读取指定文件中的数据

    load(InputStreaminStream)load(Readerreader)

    3、遍历数据

    list():将集合中的所有数据输出到指定的流中(一般用于调试)

    list(PrintStreamout)list(PrintWriterout)

    stringPropertyNames():获取集合中键的集合(键的类型是String类型)

    1.1.1  示例程序

    publicclass Demo {

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

    Properties prop = newProperties();

    /*

    * Properties类继承于Hashtable类,所以可以使用put方法添加键值对,

    * 但是Properties类中的数据要求应该都是String类型,使用put方法返回可能会出问题

    * 官方建议使用setProperty()方法添加键值对

    */

    //               prop.put("textsize",18);

    //               prop.get("textsize");

    //保存值

    prop.setProperty("textsize","18");

    prop.setProperty("textcolor","red");

    //获取值

    String size =prop.getProperty("textsize");

    String color=prop.getProperty("textcolor");

    System.out.println(size);

    System.out.println(color);

    //将属性保存到磁盘上

    //Properties的作用是将数据持久化保存,实际上就是将数据保存在磁盘上

    //               prop.save(out, comments);

    FileOutputStream fos = new FileOutputStream("prop.properties");

    prop.store(fos, "注释");

    //从磁盘上读取属性数据

    Properties prop2 = newProperties();

    FileInputStream fis = newFileInputStream("prop.properties");

    prop2.load(fis);

    System.out.println(prop2);

    //遍历Properties集合(是Map集合)

    //list方法一般是用于调试用的

    prop2.list(System.out);

    //传统的遍历Map集合的方式,通过keyset方法获取键的集合,但是元素都是Object类型

    //               prop2.keySet();

    Set     keyset = prop2.stringPropertyNames();

    for (String key : keyset) {

    String value =prop2.getProperty(key);

    System.out.println(key+"..........."+value);

    }

    }

    }

    实例:写一个程序,要求用户只能打开5次,在第6次打开的时候就抛出异常提示“打开失败”

    publicclass Ex {

    public static void main(String[] args){

    System.out.println("程序开启.......");

    //检测使用的次数

    check();

    System.out.println("程序正常运行.......");

    System.out.println("程序结束.......");

    }

    private static void check() {

    /*

    * 思路:记录用户打开程序的次数,每次打开的时候都记一次,将次数保存在配置文件中,

    * 每次打开的时候读取上一次记录的次数,如果超出上限,就提示用户

    */

    //

    FileInputStream fis =null;

    FileOutputStream fos = null;

    try {

    Properties prop =new Properties();

    File file = newFile("prop_ex.properties");

    //要保证文件存在

    if(!file.exists()){

    file.createNewFile();

    }

    fis = new FileInputStream(file);

    //从文件中加载数据到Properties集合中

    prop.load(fis);

    //通过键获取值,如果键值对不存在,就返回指定的默认值

    int count=Integer.parseInt(prop.getProperty("count","0"));

    count ++;

    //判断打开的次数是否已经超过了上限

    if(count>5){

    throw newRuntimeException("适用用次数已经超过5次上限,请续费!.......");

    }else{

    //如果没有超过

    fos = newFileOutputStream(file);

    prop.setProperty("count",String.valueOf(count));

    prop.store(fos,"open count");

    }

    } catch (IOException e) {

    // TODO: handleexception

    }finally{

    if(fos != null){

    try {

    fos.close();

    fos= null;

    } catch(IOException e) {

    //TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    if(fis != null){

    try {

    fis.close();

    fis= null;

    } catch(IOException e) {

    //TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    }

    1.2    内存流

    数组流

    byte[] bytes ={97,98,99,100,101};//源字节数组

    ByteArrayInputStream bais =//在源数组上创建一个内存输入流

    newByteArrayInputStream(bytes);

    int n=0;

    byte[] buf = new byte[4];

    //读4个字节放到缓冲buf中,返回有效读取数

    while((n=bais.read(buf))!=-1){

    for(int i=0;i

    System.out.println(buf[i]);  //打印

    }

    }

    }

    //不需要关闭

    //创建一个内存输出流,可以通过它向内置的字节数组中写字节

    ByteArrayOutputStream baos=new ByteArrayOutputStream();

    baos.write(65);//往内置字节数组中写一个字节

    baos.write(66);

    baos.write(67);

    //从中拿出之前写的字节生成的数组

    byte[] array =baos.toByteArray();

    for(byte b : array){//遍历打印,用于验证

    System.out.println(b);

    }

    //源文件流

    FileInputStream fis = newFileInputStream("g:/output.txt");

    //目标内存输出流

    ByteArrayOutputStream baos=new  ByteArrayOutputStream();

    int n=0;

    byte[] buf = new byte[4];//缓冲数组创建

    //每次从文件读4个字节方法缓冲中,有效字节数赋给n,和-1比较判断是否读完

    while((n=fis.read(buf))!=-1){

    baos.write(buf,0,n);   //没有读完就将有效字节写到内存输出流

    }

    fis.close();//需要关闭

    //               baos.close();//不需要关闭

    byte[]array=baos.toByteArray();   //获取字节数组

    for (byte b : array) {//遍历,验证

    System.out.println((char)b);

    }

    FileInputStream fis =new FileInputStream(

    "g:/MySQL-connector-Java-5.1.7-bin.jar");

    ByteArrayOutputStream baos =new ByteArrayOutputStream();

    int n = 0;

    byte[] buf = newbyte[1024];//缓冲

    while ((n = fis.read(buf)) !=-1) {//从文件读1024字节,有效字节数赋值给n,和-1比较判断是否结束

    baos.write(buf, 0,n);//把有效字节写到内存输出流

    }

    fis.close();

    byte[] array =baos.toByteArray(); //用写进的字节生成数组

    //准备从这个字节数组中读字节

    ByteArrayInputStream bais =new ByteArrayInputStream(array);

    FileOutputStream fos = newFileOutputStream("g:/copy.jar");

    while ((n = bais.read(buf))!= -1) {//从数组读1024字节,有效字节数赋给n,和-1比较

    fos.write(buf, 0,n); //把有效字节写到copy.jar

    }

    fos.close();

    FileInputStream fis = newFileInputStream("g:/mysql-connector-java-5.1.7-bin.jar");

    ByteArrayOutputStream baos=new ByteArrayOutputStream();

    int n= 0;

    byte[] buf = new byte[1024];

    while((n=fis.read(buf))!=-1){//读源文件只进行一次

    baos.write(buf,0,n);

    }

    fis.close();

    byte[] array =baos.toByteArray();

    //把文件放到内存中,这些动作不重复进行,这些动作包含了对磁盘的操作

    //把内存中的内容拷贝到文件,重复进行

    for(int i=1;i<=100;i++){

    ByteArrayInputStreambais = new ByteArrayInputStream(array);

    FileOutputStream fos= new FileOutputStream("g:/100/"+i+".jar");

    //这里也要读100次,但是每次都是读内存数组,所以效率大大提高

    while((n=bais.read(buf))!=-1){

    fos.write(buf,0,n);

    }

    fos.close();

    }

    内存流(字节数组)节点流、字节流

    ByteArrayInputStream

    ByteArrayOutputStream

    构造方法:

    ByteArrayInputStream(byte[]bytes)创建一个内存流,可以从参数字节数组中读取字节

    常用方法:

    int read()

    int read(byte[] buf)

    不需要调用close()方法

    构造方法:

    ByteArrayOutputStream()创建一个内存输出流,无参数,可以往内置的字节数组中写字节

    常用方法:

    write(int b)

    write(byte[] buf,intoff,int len)

    不需要调用close()方法

    toByteArray()获得字节数组(之前写到其中的字节组成的字节数组)

    在文件小且不经常变更的情况下,可以用内存流先进行缓存,避免反复磁盘操作

    实例:

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

    //字节数组输出流

    //是以数组作为数据源,将数据写到数组中

    //当数组输出流被创建的时候内部会自动创建一个数组

    ByteArrayOutputStream baso =new ByteArrayOutputStream();

    //将数据写出到数组流内部的数组(内存)中

    baso.write("强风125".getBytes());

    //取出流中的字节数组

    byte[]buf  =baso.toByteArray();

    System.out.println(newString(buf));

    //在这里因为操作的是内存,所以不需要释放存放

    //               baso.close();

    //使用场景:从网上下载图片并显示在界面上

    //从内存数组中去数据

    ByteArrayInputStream bais =new ByteArrayInputStream(buf);

    byte[] cubf  = new byte[1024];

    bais.read(cubf);

    System.out.println(newString(cubf));

    //如果一个数组中的数据比较多,需要分批读取,那么使用数组流能简化我们的代码

    //比如:现在有一个字节数组大小为1000,每次读取300个字节,自到将数据读完

    }

    1.3    对象流

    对象流是一种处理流、字节流

    对象流

    ObjectInputStream

    readObject()

    ObjectOutputStream

    writeObject()

    注意事项:

    1、被对象流操作的对象必须先进行序列化(实现Serializable接口)

    1)需要在类中定义一个静态常量(序列值,static final longserialVersionUID)

    2)在数据序列化的时候不会对静态字段(static )和瞬态字段(transient)进行序列化

    2、一个文件只能存储一个对象

    实例:

    publicclass Demo {

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

    //               test1();

    //               writeObj();

    readObj();

    }

    private static void readObj() throwsIOException, ClassNotFoundException {

    FileInputStream fis = newFileInputStream("objdemo.object");

    ObjectInputStream ois = new ObjectInputStream(fis);

    //内部自动进行了反序列化

    Student stu =(Student)ois.readObject();

    System.out.println(stu);

    }

    private static void writeObj() throwsIOException {

    Student stu = new Student("小强", "男", 18);

    //对象流,用于直接操作对象

    FileOutputStream fos = newFileOutputStream("objdemo.object");

    ObjectOutputStream oos = newObjectOutputStream(fos);

    //将对象写出到指定设备

    //注意:对象流操作的对象必须进行序列化

    //序列化:只需要实现Serializable

    oos.writeObject(stu);

    oos.close();

    }

    private static void test1() throwsIOException, FileNotFoundException {

    Student stu = newStudent("小强","男", 18);

    FileWriter fw =  newFileWriter("object.txt");

    fw.write(stu.name+"|");

    fw.write(stu.gender+"|");

    fw.write(stu.age +"");

    fw.close();

    //从磁盘上读取对象的数据并生成对象

    BufferedReader br = new BufferedReader(newFileReader("object.txt"));

    String line = br.readLine();

    String[] strs = line.split("\\|");

    String name = strs[0];

    String gender = strs[1];

    int age = Integer.parseInt(strs[2]);

    Student stu2 = new Student(name, gender, age);

    System.out.println(stu2);

    }

    }

    classStudent implements Serializable/*标记接口*/{

    /**

    * 序列值,用于标记类的唯一性

    * 如果没有指定序列值,那么编译器会自动根据类中的成员来自动生成一个序列值

    * 建议:在序列化的时候最好要写上序列值

    */

    private static final long serialVersionUID= 10000L;

    /**

    * static 修饰的类成员不会被序列化

    */

    String name;

    String gender;

    transient int age;     //瞬态的(不会进行序列化)

    public Student(String name, Stringgender, int age) {

    this.name = name;

    this.gender = gender;

    this.age = age;

    }

    @Override

    public String toString() {

    return "Student[name=" + name + ", gender=" + gender + ", age=" + age

    +"]";

    }

    }

    1.3.1  ObjectOutputStream

    //文件的文件输出流

    FileOutputStream fos = newFileOutputStream("g:/obj");

    //用对象输出流去处理、装饰fos文件输出流

    ObjectOutputStream oos = newObjectOutputStream(fos);

    oos.writeObject("1000phone");//写一个字符串对象到流中

    oos.close();

    //对象流装饰文件流

    ObjectOutputStream oos = newObjectOutputStream(

    newFileOutputStream("g:/elephant"));

    //初始化对象

    Elephant mike = newElephant("Mike", 1000);

    oos.writeObject(mike);    //把大象塞进去

    oos.close();

    构造方法:ObjectOutputStream(OutputStream os)参数是它要处理、装饰的流,增加了写对象的功能

    writeObject(Objectobj)

    1.3.2  ObjectInputStream

    ObjectInputStream ois= //用对象流装饰文件流

    newObjectInputStream(new FileInputStream("g:/obj"));

    String str =(String)ois.readObject();   //读一个对象

    System.out.println("从obj文件中拿出来了:"+str);

    ois.close();

    ObjectInputStream ois= new ObjectInputStream(

    newFileInputStream("g:/elephant"));

    //把大象从流中拖出来,拿到的是Object类型,强转为大象类型

    Elephant e =(Elephant)ois.readObject();

    System.out.println(e.getName()+"   "+e.getWeight());

    ois.close();

    构造方法:ObjectInputStream(InputStream is)参数是它要处理、装饰的流,增加了读对象的功能

    Object readObject()

    对象流读写,写的和读的类型一定要一致。

    对象流读写的对象必须要可序列化,必须实现Serializable接口,这个接口无抽象方法。

    用途:信息的存储、信息在网络上的传递、信息在组件间传递

    1.4    输出流(打印流)

    PrintWriterpw = new PrintWriter(

    newFileOutputStream("g:/answer.txt",true));

    //由于构造方法第二个参数为true ,println会自动刷缓存

    pw.println("1000phone");//打印1000phone到文件中并换行

    pw.println("Android");//打印android到文件中并换行

    pw.println("java");//打印java到文件中并换行

    pw.close();

    PrintWriter输出流、字符流、处理流

    构造方法:

    PrintWriter(OutputStreamos,boolean autoFlush)第一个参数是所要装饰的字节输出流,第二个参数是表示是否自动刷缓存

    PrintWriter(Writerwriter,boolean autoFlush)装饰字符流

    PrintWriter(Stringpath,String csn)在以第一个参数为路径的文件上建立打印流,字符集由第二个参数指定

    println()打印并且换行,在autoFlush为true时,会自动刷缓存

    PrintStream用法和PrintWriter差不多,构造方法少一点

    实例

    publicstatic void main(String[] args) throws IOException {

    // 打印流(只有输出流)PrintStream(字节打印流)  PrintWriter (字符打印流)

    //               PrintStream ps = new PrintStream(newFileOutputStream("print.txt"));

    PrintStream ps = newPrintStream("print.txt");

    /*ps.print(true);

    ps.print("中");

    ps.print("f");*/

    ps.print(18);    //编码

    ps.write(97);    //字面值

    ps.close();

    }

    1.5    数据流

    DataOutputStream dos= //用数据流装饰文件流

    newDataOutputStream(new FileOutputStream("g:/answer.txt"));

    dos.writeInt(101);//向数据流中写100

    dos.writeInt(100);

    dos.writeInt(70);

    dos.writeInt(66);

    dos.close();//关闭处理会自动关闭所装饰的流

    DataInputStream dis =new DataInputStream(

    new FileInputStream("g:/answer.txt"));

    int a=dis.readInt();//用数据流装饰文件流

    System.out.println(a);

    System.out.println(dis.readInt());//打印读出的int数据

    System.out.println(dis.readInt());

    System.out.println(dis.readInt());

    dis.close();

    DataOutputStream数据输出流,字节流、处理流

    DataOutputStream(OutputStreamos)构造方法参数为它所装饰的字节输出流,添加了写基本类型数据的功能

    writeInt(int i)

    writeXXX(xxx i)

    DataInputStream数据输入流

    DataInputStream(InputStreamis)构造方法参数为它所装饰的字节输入流,添加了读基本数据类型的功能

    int readInt()

    xxx readXXX()

    实例:

    publicstatic void main(String[] args) throws IOException {

    //数据流(过滤流)

    FileOutputStream fos = newFileOutputStream("data.txt");

    DataOutputStream oos = newDataOutputStream(fos);

    oos.writeByte(100);

    oos.writeChar('中');

    oos.writeShort(1000);

    oos.writeInt(1022);

    oos.writeLong(12025);

    oos.writeFloat(12.2f);

    oos.writeDouble(15.4524);

    oos.writeBoolean(true);

    oos.close();

    //读取数据

    FileInputStream fis = new FileInputStream("data.txt");

    DataInputStream dis = new DataInputStream(fis);

    System.out.println(dis.readByte());

    System.out.println(dis.readChar());

    System.out.println(dis.readShort());

    System.out.println(dis.readInt());

    System.out.println(dis.readLong());

    System.out.println(dis.readFloat());

    System.out.println(dis.readDouble());

    dis.close();

    }

    1.6    装饰模式

    装饰模式:

    1、把被装饰者通过构造方法传入装饰者

    2、被装饰者和装饰者具有相同的方法(方法名、返回、参数)、具有相同的接口或父类

    3、被装饰者以属性的形式存在于装饰者中

    1.7    随机访问文件

    RandomAccessFile raf= new RandomAccessFile("g:/answer.txt", "rw");

    raf.write(65);//A|

    raf.write(66);//AB|

    raf.seek(0);//将游标一下子跳到第一个位置|AB

    raf.write(67);

    raf.write(68);

    raf.close();

    RandomAccessFile raf=new RandomAccessFile("g:/answer.txt", "r");

    System.out.println(raf.read());

    System.out.println(raf.read());

    raf.seek(0);  //游标放到最前

    System.out.println(raf.read());

    System.out.println(raf.read());

    raf.close();

    RandomAccessFile随机访问文件,不是InputStream、OutputStream、Reader、Writer中的任一个子类

    RandomAcceessFile(Stringpath,String mode)

    构造方法第一个参数表示文件路径,第二个参数打开模式,如果是"rw"表示可读可写,如果是"r"表示只读

    seek(int pos)定位,游标可以随便向前向后跳,只要不超出范围(Stream、Reader、Writer只能往后不能往前)

    相关文章

      网友评论

          本文标题: Java中的IO框架流三

          本文链接:https://www.haomeiwen.com/subject/wsvmxxtx.html