zoukankan      html  css  js  c++  java
  • 如何用java有选择的输入多行文本

    java如何有选择的输入多行文本

    今天在做作业的时候碰到了一个问题:要用java做词频统计,但是这就犯难了,java如何有选择性的进行文件输入输出呢?

    查阅文档可知,inputStream类和outputStream类是字节流输入输出,而reader 类和writer 类则是直接Unicode码输入输出,我为了图省事,我最后使用了FileReader类的read方法进行文件读取。FileReader类中的read方法可以逐字符读取,返回类型为int,其实就是0~255的char 类型,只要进行强制类型转换,就可以得到读入的字符,当遇到文件尾的时候,该方法返回-1。因为是char类型,所以如果遇到中文字符,比如句号,就会按照两个char处理。

    接下来解决选择性输入的问题。思路很简单:

      1.如果现在所读取到的字符不是我们想要的,那么就一直向下读取,直到读取到我们想要的

      2.如果遇到了返回值为-1的情况,退出,表示文件读取完成(这一步一定要放在中间判断

      3.如果现在读取的是我们想要的,就一直读取,直到出现我们不需要的,退出,等待下一次读取。

    解释一下第二个为什么要在中间判断吧。

    因为如果放在三个判断的第一个,那么如果文件以无用的字符结尾,则最后一个单词输出后还会多余输出一个换行,因为return了一个空的StringBuffer,而输出语句用的是println。

    如果放在三个判断中的最后,那么如果文件以有用单词结尾,则最后一个单词无法输出,因为扫描到单词后紧接着就是read返回-1,此时就直接返回“字符串完成”,所以少最后一个单词

    第一次解决的时候,因为判断1的位置和判断3混在了一起,所以出现了最后一个单词不能输出的情况。

      错误写法我也写下来吧,以免以后再错:

    错误1——放在最前面:

    private String read() throws IOException{
            StringBuffer strBuf = new StringBuffer();
            int t=fileReader.read();
            if(t==-1) return "\$";

    错误2——放在最后:

    1 while(t!=-1&&isAlph((char)t)){
    2             strBuf.append((char) t);
    3             t=fileReader.read();
    4         }     
    5     if(t==-1) return "\$";
    6     return strBuf.toString();
    7 }

    正确做法:(完全代码,并且简化了不需要的流程)

     1 private String read() throws IOException{
     2         StringBuffer strBuf = new StringBuffer();
     3         int t=fileReader.read();
     4         if(t==-1) return "\$";
     5         while(t!=-1&&isAlph((char)t)){
     6             strBuf.append((char) t);
     7             t=fileReader.read();
     8         }
     9         return strBuf.toString();
    10     }

    因此,可以看到代码的细节也是不容忽视的,同一句话,不同位置,导致结果大相径庭。

    ======================================我是小清新的分割线=========================================

    2016.5.8更新

    嗯,好吧,我又来啦,这次的java之旅差不多就已经完成啦,现在让我们梳理一下这次学到的输入流的组合方式:

    除了上文中逐个字符进行输入的方法之外,对于有些问题,正则表达式可能更加好用。

    比如我们想逐行读取文本怎么办呢,我们会发现FileReader类中是没有这种方法的,因此我们需要把File类和其他输入流组合起来,自力更生。比如我们把File和Scanner类结合起来,熟悉控制台的小伙伴们一定很清楚,Scanner常用来进行控制台输入,并且Scanner可以一次读取一行,因此,我们就选它啦。

    因此我么可以愉快地一次一行进行操作啦

    定义如下:(in 和 out 分别是输入流和输出流)

    public Tree_T_Display(File fin,File fout) throws IOException {
            in = new Scanner(new FileInputStream(fin));
            out = new FileWriter(fout);
    }

    这样read()函数就可以这样定义啦:

    public String read()throws IOException{
            if(in.hasNext()){
                String s = in.nextLine();
                s=s.replaceAll(" ", "");//去掉空格
                return s;
            }
            return null;
        }

    这样一来,配合正则表达式,我们的代码量可以减少,并且在过滤数据方面也可以交给正则表达式去做。

    另外,正则表达式也提一下吧,在java的正则表达式我自己用过的有两种调用方法,一种是String类中的split,matches方法,注意split方法中匹配上的字符不会出现在新的字符串中,而matches方法中的正则必须和字符串完全匹配,否则就返回false。

    另外,正则中,+表示1~n个(n)不限制,*表示0~n个,和{1,}  {0,}分别等价。

    ^表示行开头,$表示行结尾,^在[]中表示“非”,取补集

    举例如下

    目标:匹配“单词”开头+“(”结尾的字符串:

    1 s.matches("^[a-zA-Z]+[^\(]$")

    匹配可能有特殊字符的单词,缩写等:

    1 s.matches("^[^ ]+$")

    这里就用到了^在[]中的情况,一个[]是一个可匹配的类,上面第二行作用是匹配一个“以非空格开头并且以之为结尾的字符串”

    pte String read() throws IOException{
    StringBuffer strBuf = new StringBuffer();
    int t=fileReader.read();
    if(t==-1) return "\$";
    while(t!=-1&&isAlph((char)t)){
    strBuf.append((char) t);
    t=fileReader.read();
    }
    //保留最大单词长度,为格式化输出做准备
    maxLen = maxLen < strBuf.length() ? strBuf.length() : maxLen;
    return strBuf.toString();
    }
  • 相关阅读:
    SpringBoot集成JWT
    MongoDB学习入门
    Docker入门笔记
    商品分类(递归子目录)接口开发笔记
    深入理解java虚拟机
    -XX:+HeapDumpOnOutOfMemoryError
    使用kettle报Invalid byte 1 of 1-byte UTF-8 sequence异常
    kettle学习笔记(四)——kettle输入步骤
    eclipse maven项目,如何导出使用的依赖jar包
    kettle学习笔记(二)——kettle基本使用
  • 原文地址:https://www.cnblogs.com/luruiyuan/p/5463374.html
Copyright © 2011-2022 走看看