java学习第二十二天之重写read()、readLine(),行号,properties

readLine():调用了read()方法,从缓存区中获取数据存储到readLine自己的缓冲区中,它会判断行终止符,只存储 行结束符 前的数据。
if(ch==’\r’)
continue;

模拟一个BufferReader

Writer
|–TextWriter
|–MediaWriter
在对数据写入操作过程中,希望提升效率
要对操作文本的对象提升效率,使用缓冲区技术
Writer
|–TextWriter
|–BufferedTextWriter
|–MediaWriter
|–BufferedMediaWriter
|–AudioWriter
|–BufferedAudioWriter
这样的体系,为了增加一些功能,而通过产生子类来完成,会导致集成体系变得很臃肿
重新思考体系的设计问题,都是在写的方法进行效率的提升
为什么不将该功能进行单独的封装呢?要提升哪个具体对象,将哪个具体对象交给该功能不就可以了吗?

class BufferedWriter extends Writer
{
    BufferedWriter(TextWriter w){}
    BufferedWriter(writer w){}
    BufferedWriter(MediaWriter w){}
}

TextWriter tw=new TextWriter();
BufferedWriter bufw=new BufferedWriter();
//tw.write();
bufw.write();
解决:可以给对象提供额外的功能,比继承这种凡是更灵活
起个名字:装饰设计模式(Wrapper,Decotator)
装饰类与被装饰类都所属于同一个体系,同时装饰类中持有被装饰类的引用
IO的properties特点:
1、Hashtable的子类,map集合中的方法都可以用
2、该集合没有泛型,键值都是字符串
3、它是一个持久化的属性集,键值都可以存储到集合中,也可以存储到持久化的设备上。键值的来源也可以是持久化的设备。


IO流的规律总结:
1、明确数据源。数据汇(数据目的)
其实就是在明确要使用的IO体系。InputStream OutputStream Reader Writer
需求中操作的是源:意味着是写
OutputStream Writer
操作的数据是否是纯文本数据?
是,字符流
否,字节流
是并且是源。Reader
是并且也是目的 Writer

通过前两个明确,明确了具体要使用的体系
接下来应该明确具体的体系要使用哪个对象

源设备:
硬盘:能操作File的流对象都是 。File开头
键盘:System.in
内存:数组
网络:socket流
目的设备:
硬盘:能操作File的流对象都是 。File开头
键盘:System.in
内存:数组
网络:socket流
到了第三步名曲我就可以找到具体的流对象了

4.需要额外的功能吗?
需要高效吗?缓冲区,buffered开头
需要编码吗?
需要

package cn.mybuffer.demo;

import java.io.IOException;
import java.io.Reader;
//读取一个字符的方法,而且是高效的  重写read()方法
public class MyBufferedReader  extends Reader{
//  1、持有一个流对象
    private Reader reader;
//  因为是缓冲区对象,所以内部必须维护了数组
    private char[]  buffer=new char[1024];

//  定义脚标
    private int index=0;
//  定义变量,记录数组中元素的个数
    private int count=0;
//  一初始化就必须明确被缓冲的对象
    public MyBufferedReader(Reader reader) {
        super();
        this.reader = reader;
    }


    /**
     * @throws IOException 
     * 
     */
    private int myRead() throws IOException {
//      通过被缓冲流对象的方法,就可以将设备上的数据存储到数组中
        if(count==0){
            count=reader.read(buffer);
            index=0;
        }

        if(count<0){
            return -1;
        }

        char ch=buffer[index];
        index++;//脚标每取一次自增
        count--;//既然取出一个,数组的数量要减少,一旦减到0,就再从设备上获取一批数据存储到数组中
        return ch;
    }

    /**
     *读取一行文本
     * @throws IOException 
     */
    public String myReadLine() throws IOException{

//      定义临时缓冲区,用于存储一行文本
        StringBuilder stringBuilder=new StringBuilder();
//      不断的调用myRead方法从缓冲区中取出数据
        int ch=0;
        while((ch=myRead())!=-1){
//          在存储前要判断行终止符
            if(ch=='\r'){
                continue;
            }
            if(ch=='\n'){
                return stringBuilder.toString();
            }
//          对读到的字符进行临时存储
            stringBuilder.append((char)ch);         
        }

//      如果文本结尾处有数据,但是没有行结束符
//      数据已被读到,并存储到stringBulider中,只要判断stringBuilder的长度即可
        if(stringBuilder.length()!=0){
            return stringBuilder.toString();
        }
        return null;
    }

//  定义一个缓冲区的关闭方法
    public void myclose() throws IOException {
//      其实就是在关闭被缓冲区的流对象
        reader.close();
    }


/* (non-Javadoc)
 * @see java.io.Reader#close()
 */
@Override
public void close() throws IOException {
}


/* (non-Javadoc)
 * @see java.io.Reader#read(char[], int, int)
 */
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
    return 0;
}
}
package cn.mybuffer.demo;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MyBufferedReaderDemo {
    /**
    * @param args
     * @throws IOException 
    */
    public static void main(String[] args) throws IOException {
        FileReader fileReader=new FileReader("D:\\java\\workspace\\Stage2\\src\\cn\\iolearn\\demo\\tempfile\\fos.txt");
    /*  
        BufferedReader bufferedReader=new BufferedReader(fileReader);
        String line=null;
        while((line=bufferedReader.readLine())!=null){
            System.out.println(line);
        }
    */
//      调用重写的myReadLine方法
        MyBufferedReader bufferedReader=new MyBufferedReader(fileReader);
//      调用重写的获取行号的方法
        MyLineNumberReader myLineNumberReader=new MyLineNumberReader(fileReader);
        String line=null;
        while((line=bufferedReader.myReadLine())!=null){
            System.out.println(myLineNumberReader.getLineNumber()+":"+line);//为什么行号没有自增?
        }



    }
}
package cn.mybuffer.demo;

import java.io.IOException;
import java.io.Reader;
//自定义获取行号的方法
public class MyLineNumberReader extends MyBufferedReader{

//  定义一个计数器
    private int lineNumber=0;

    public MyLineNumberReader(Reader reader) {
        super(reader);
    }
/**
 * 
 * @throws IOException 
 * @覆盖父类的读一行的方法
 */
    public String myReadLine() throws IOException {
        lineNumber++;
        return super.myReadLine();
    }
    public int getLineNumber() {
        return lineNumber;
    }

    public void setLineNumber(int lineNumber) {
        this.lineNumber = lineNumber;
    }


}
package cn.mybuffer.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {
    /**
    * @param 演示properties的特有方法
     * @throws IOException 
    */
    public static void main(String[] args) throws IOException {
//      methodDemo();
//      methodDemo2();
        methodDemo3();
    }

    /**
     * @throws IOException 
     * 
     */
    private static void methodDemo3() throws IOException {
        File configFile=new File("D:\\java\\workspace\\Stage2\\src\\cn\\iolearn\\demo\\tempfile\\info.properties");
//      读取流中的数据
        Properties properties=new Properties();
//      定义读取流和数据文件关联
        FileInputStream fileInputStream=new FileInputStream(configFile);
        properties.load(fileInputStream);
        properties.setProperty("向往", "45");
//      要将改完的数据持久化
        FileOutputStream fileOutputStream=new FileOutputStream(configFile);
        properties.store(fileOutputStream, "");
        fileOutputStream.close();

    }

    private static void methodDemo2() throws IOException {

        Properties properties=new Properties();
        properties.setProperty("张三", "25");
        properties.setProperty("李四", "20");
        properties.setProperty("王五", "30");
//      将集合中的数据持久化存储到设备上
//      需要输出流对象
        FileOutputStream fileOutputStream=new FileOutputStream("D:\\java\\workspace\\Stage2\\src\\cn\\iolearn\\demo\\tempfile\\info.properties");
//      使用properties的store方法
        properties.store(fileOutputStream, "mydemoo,personinfo");
        fileOutputStream.close();
    }

    private static void methodDemo() {

//      Properties的基本存取
//      创建一个properties
        Properties properties=new Properties();
        properties.setProperty("张三", "25");
        properties.setProperty("李四", "20");
        properties.setProperty("王五", "30");

        /*Set<String> set=properties.stringPropertyNames();
        for (String name : set) {
            String value=properties.getProperty(name);
            System.out.println(name+"\t"+value);
        }*/

        properties.list(System.out);
    }
}
package cn.mybuffer.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class TestDemo {
    /**
    * @param args
     * @throws IOException 
    */  
    public static void main(String[] args) throws IOException {
    /*    
//      需求:定义一个功能,记录程序运行的次数。满足5次后,给出提示,试用次数已到,请注册!
        思路:
        1、需要计数器
        2、计数器的值生命周期要比应用程序的周期要长,需要对计数器的值进行持久化
        3、count=1,里面存储的应该是键值方式,map集合,要和设备上的数据关联,需要IO技术
        集合+IO=Properties
    */  
        boolean b=checkOut();
        if(b)
            run();
    }

    /**
     * @return
     * @throws IOException 
     */
/*  
    public static boolean checkOut() {      
        int count=0;
        count++;
        System.out.println("count="+count);
        return false;
    }
    */
    public static boolean checkOut() throws IOException {
        int count=0;
        boolean isRun=true;
//      1、将配置文件封装成File对象,因为要判断文件是否存在
        File configFile=new File("D:\\java\\workspace\\Stage2\\src\\cn\\iolearn\\demo\\tempfile\\count.properties");
        if(!configFile.exists()){//如果不存在,就创建
            configFile.createNewFile();
        }
        Properties properties=new Properties();//用于存储配置文件中的数据
//      定义流对象
        FileInputStream fileInputStream= new FileInputStream(configFile);
//      将流中的数据加载到集合中
        properties.load(fileInputStream);
//      获取键对应的次数
        String value=properties.getProperty("count");
        if(value != null){
            count=Integer.parseInt(value);
            if (count>=5) {
                System.out.println("使用次数已到!");
                isRun=false;
            }
        }
        count++;//对取出的次数自增
//      将键count,和自增后的重新存储到集合中
        properties.setProperty("count", Integer.toString(count));
//      将集合中的数据存储到配置文件中
        FileOutputStream fileOutputStream=new FileOutputStream(configFile);
        properties.store(fileOutputStream, "");
        fileOutputStream.close();
        fileInputStream.close();
        return isRun;
    }
    public static void run(){
        System.out.println("软件运行!");
    }
}
package cn.mybuffer.demo;

public class TestDemo1 {
    /**
    * @param args
    * 需求1:通过键盘录入的数据,将数据保存到一个文件中
    * 
    * 
    * 明确一:有源吗?有    有目的吗?  有
    *   源:InputStream  Reader
    *   目的:OutputStream    Writer
    * 明确二:是纯文本数据吗? 是
    *   源:Reader
    *   目的:Writer
    * 明确三:具体设备
    *   源设备:System.in
    *   目的设备:硬盘
    * 
    * InputStrean is=System.in;
    * FileWriter =fw=new FileWriter("a.txt");'
    * 
    * 将读取的字节存储到数组read(byte[])
    * 将字节数组转成字符数组
    * 通过fw.write(string)写入到文件中
    * 
    * 但是麻烦。因为明确源是Reader。需要将字节流转成字符流,这样操作文字就方便了
    * 
    * 明确四:需要功能吗?
    * 需要,转换  。 字节--->字符  InputStreamReader
    * InputStreamReader isr=new InputStreamReader(System.in);
    * FileWriter fw= new FileWriter("a.txt");
    * 一次读取一个字节
    * 将读到的字节写入
    * 当然也可以定义字符数组缓冲区
    * 
    * 需要其他功能吗?
    * 需要,高效。Buffered
    * 
    * BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
    * BufferedWriter bufw=new BufferedWriter(new FileWriter("a.txt"));
    * 
    * line=bufw.readLine();
    *bufw.write(string);
    *bufw.flush();
    *
    *
    *
    *
    *需求二:读取文本文件中的数据,将其打印到控制台上
    * 明确一:有源吗?有    有目的吗?  有
    *   源:InputStream  Reader
    *   目的:OutputStream    Writer
    * 
    * 明确二:是纯文本
    *   源:Reader
    *   目的:Writer
    * 明确三:明确设备
    *   源设备:硬盘:File XXX
    *   目的设备:显示器:System.out
    * 
    * FileReader fr=new FileReader("a.txt");
    * fr读取数据到数组中
    * 使用PrintStream直接调用println方法就可以打印了。如果使用OutputStream可以调用writer方法就可以将数据写到显示器上
    * 
    * 麻烦:
    * 因为源都是字符数据。可以通过字符流操作,将字符转成字节再给显示器
    * 需要额外的功能吗?
    * 需要转换  字符--->字节
    * OutputStreamWriter osw=new OutputStreamWriter(System.out);
    * 
    * 还需要额外功能吗?
    * 需要高效
    * BufferedReader bufr=new BufferedReader(new FileReader("a.txt"));
    * BbufferedWriter bufw=new BuffferedWriter(new OutputStreamWriter(System.out));
    * 
    *
    */
    public static void main(String[] args) {

    }
}
package cn.mybuffer.demo;


public class WrapperDemo {
    /**
    * @param args
    */
    public static void main(String[] args) {
        Person person=new Person();
        NewPerson child=new NewPerson(person);
        child.eat();
        System.out.println("-----------------");
        Men men=new Men();
        men.eat();
        SubMan subMan=new SubMan();
        subMan.eat();
        System.out.println("--------------------");
        NewPerson newPerson=new NewPerson(men);
        newPerson.eat();
    }
}


class Person{
    void eat(){
        System.out.println("吃饭");
    }
}
/*
class SubPerson extends Person{
    void eat(){
        System.out.println("开胃菜");
        super.eat();
        System.out.println("甜点");
    }
}
*/

class NewPerson extends Person{
    private Person person;
    /**
     * 
     */
    public NewPerson(Person p) {
        this.person=p;
    }
    void eat(){
        System.out.println("开胃菜");
        person.eat();
        System.out.println("甜点");
    }
}

class Men extends Person{
    void eat(){
        System.out.println("喝酒!");
    }
}

class SubMan extends Men{
    void eat(){
        System.out.println("开胃菜");
        super.eat();
        System.out.println("甜点");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值