黑马程序员技术交流社区

标题: 自定义字符输入流的包装 让程序通过这个包装类读取某个文本文件 [打印本页]

作者: 晚上没饭吃    时间: 2015-8-15 01:32
标题: 自定义字符输入流的包装 让程序通过这个包装类读取某个文本文件
思路:
    1.首先是字符的,输入的包装类,底层自然是一个一个读取字符.那么该
    包装类中必然要有read()方法.
    2.对于read()的数据如何让其具备一行一行的数据记录呢?必须要有一个
    变量,这个变量如何去定义,怎么样这个变量才会变化呢?
    3.每次一行的读取数据,那么可以在包装类中定义一个StringBuilder用来
    接受数据,当读到行末尾的时候,就返回这个StringBuilder的字符串.
   
  总结:
          1.java中读取的一行一行数据,也是依靠底层一个一个读取,然后根据\n来判断读取到行末尾,再一次性返回.
          2.对于判断结束标记,我们在自定义返回数据的时候,就需要给定一个可以让其结
          束的标记(null 或者 -1 等等).
          3.对于StringBuilder,其中接受的数据,并没用换行操作(因为底层中,一次一个字节读取,对于\r\n只是一个判断依据,并没有存储起来),因此我们需要手动,对于行结尾要添加"\r\n"以便输出时候识别换行.
         
  思考:
          java中,一次读取一行是提高了效率的操作.但是,一次读取一行其底层也是一个一个读取的操作.那么,怎么样能够证明,貌似一样的操作手法一次一行就效率更高呢?
         
          查阅api发现,如果没有定义缓冲区,每次读取后,都要将数据从字节转换成字符数据而后返回,这样会效率极低.
        个人认为:
        不管是字节流还是字符流,底层都是在读取字节.只是字符流加入了一个可以让我们识别的一个编码表.如果一次读一个字符,先存储起来,等到读到行末尾再一次输出.
        那么效率应该是提高在"数据返回"这个关键点上.而在底层读取啊,还有转换呀,
        这些方面是没有提高效率的.
* */
public class Demo06 {
        public static void main(String[] args) throws IOException {
                File fi = new File("c:\\stu.txt");
                String s = LineFile(fi);
               
                System.out.println(s);
        }

        public static String LineFile(File fi) throws IOException {
                MyLineReader mr = new MyLineReader(new FileReader(fi));
                String s = null;
                StringBuilder sb = new StringBuilder(); //为了让程序拥有自主控制输出,因此创建.
                mr.setLen(0);  //设置开始行号.
                while((s = mr.MyreadLine())!= null)
                {
                        sb.append( mr.getLen() + ":" + s + "\r\n");
                }
                return sb.toString(); //将数据返回,让客户拥有输出权利.
        }
}


class MyLineReader
{       
        private int len;  //自定义行数变量
        private Reader fi; //读取数据流.
        public MyLineReader(Reader fi)
        {
                this.fi = fi;
        }
        public String MyreadLine() throws IOException
        {
                len ++; //读取一行之后,len自增.
                StringBuilder sb = new StringBuilder(); //将数据存储起来.
                int i = 0;
                while((i = fi.read())!= -1)
                {
                        if(i == '\r')  
                                continue;
                        if(i == '\n') //当独到行标记时候,将数据全部返回.
                                return sb.toString();
                        sb.append((char)i); //没有到达行标记就继续读取.
                }
                if(sb.length() != 0) //StringBuilder的长度不为0,就继续返回数据.
                        return sb.toString();
                return null; //否则返回空.因为调用方法时候,是依靠返回是不是null来判断,是不是应该结束.
        }
        public int getLen() { //get,set方法,用来获取行号和设置行号.
                return len;
        }
        public void setLen(int len) {
                this.len = len;
        }       
}








欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2