【问题标题】:Remove or ignore character from reader从阅读器中删除或忽略字符
【发布时间】:2010-08-31 07:46:01
【问题描述】:

我正在将所有字符读入流中。我正在使用 inputStream.read 阅读它。这是 java.io.Reader 输入流。 读入缓冲区时如何忽略 @ 等特殊字符。

代码

private final void FillBuff() throws java.io.IOException
  {
     int i;
     if (maxNextCharInd == 4096)
        maxNextCharInd = nextCharInd = 0;

     try {
        if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
                                            4096 - maxNextCharInd)) == -1)
        {
           inputStream.close();
           throw new java.io.IOException();
        }
        else
           maxNextCharInd += i;
        return;
     }
     catch(java.io.IOException e) {
        if (bufpos != 0)
        {
           --bufpos;
           backup(0);
        }
        else
        {
           bufline[bufpos] = line;
           bufcolumn[bufpos] = column;
        }
        throw e;
     }
  }

【问题讨论】:

    标签: java


    【解决方案1】:

    您可以使用自定义FilterReader

    class YourFilterReader extends FilterReader{
        @Override
        public int read() throws IOException{
            int read;
            do{
                read = super.read();
            } while(read == '@');
    
            return read; 
        }
    
        @Override
        public int read(char[] cbuf, int off, int len) throws IOException{
            int read = super.read(cbuf, off, len);
    
            if (read == -1) {
                return -1;
            }
    
            int pos = off - 1;
            for (int readPos = off; readPos < off + read; readPos++) {
                if (read == '@') {
                    continue;
                } else {
                    pos++;
                }
    
                if (pos < readPos) {
                    cbuf[pos] = cbuf[readPos];
                }
            }
            return pos - off + 1;
        }
    }
    

    资源:

    关于同一主题:

    【讨论】:

    • 是的,一个新的装饰器是要走的路。
    • 只是一个注释。在第二种方法中,缺少参数。 ;)
    • 我认为循环中的第一行应该是if (cbuf[readPos] == '@') {。正在测试的 read 变量现在对于循环的每次迭代都保持不变。
    【解决方案2】:

    所有这些读取器、写入器和流都实现了 Decorator 模式。每个装饰器都会为底层实现添加额外的行为和功能。

    满足您需求的解决方案可能是 FilterReader:

    public class FilterReader implements Readable, Closeable {
      private Set<Character> blacklist = new HashSet<Character>();
      private Reader reader;      
    
      public FilterReader(Reader reader) {
        this.reader = reader;
      }
    
      public void addFilter(char filtered) {
        blacklist.add(filtered);
      }
    
      @Override
      public void close() throws IOException {reader.close();}
    
      @Override
      public int read(char[] charBuf) {
        char[] temp = new char[charBuf.length];
        int charsRead = reader.read(temp);
        int index = -1;
        if (!(charsRead == -1)) {
          for (char c:temp) {
            if (!blacklist.contains(c)) {
              charBuf[index] = c;
              index++;
             }
          }
        }
        return index;
      }
    
    }
    

    注意 - java.io.FilterReader 类是一个零功能的装饰器。您可以扩展它或忽略它并创建自己的装饰器(在这种情况下我更喜欢)。

    【讨论】:

    • 使用read(char[]) 方法,我认为您应该继续阅读,直到charBuf 已满。您的实现只是读取下一个 charbuf.length 元素中的有效元素。 Set 的整体实现很好——也许我会包含另一个带有 Set 参数的构造函数——但这在这里并不是那么重要。
    • 我会扩展java.io.FilterReader,将您的类保留为阅读器可能很有用,并明确表示它是为过滤输入字符流而创建的阅读器。并且多态性仍然可用。在您的情况下,您不能将您的类封装到另一个 Reader 中,因为它不是另一个 Reader。
    • Yikes - Reader 不是一个接口,而是一个抽象类。更改了实现...
    • BufferedReaderis-a Readerhas-a Reader。阅读器/编写器/输入流/输出流的关键在于您可以将它们全部封装。
    • @Colin - 我删除了这句愚蠢的句子,我想提出不同的观点:通常我们使用接口来实现这种模式,但不幸的是,SUN 决定实现一个抽象类而不是Reader 接口。
    【解决方案3】:

    您可以实现从 InputStream 派生的自己的输入流。然后重写 read 方法,以便它们从流中过滤掉一个特殊字符。

    【讨论】:

      【解决方案4】:
      private final void FillBuff() throws java.io.IOException
      {
       int i;
       if (maxNextCharInd == 4096)
          maxNextCharInd = nextCharInd = 0;
      
       try {
          Reader filterReader = new FilterReader(inputStream) {
              public int read() {
                  do {
                      result = super.read();
                  } while (specialCharacter(result));
                  return result;
              }
          };
          if ((i = filterReader.read(nextCharBuf, maxNextCharInd,
                                              4096 - maxNextCharInd)) == -1)
          {
             inputStream.close();
             throw new java.io.IOException();
          }
          else
             maxNextCharInd += i;
          return;
       }
       catch(java.io.IOException e) {
          if (bufpos != 0)
          {
             --bufpos;
             backup(0);
          }
          else
          {
             bufline[bufpos] = line;
             bufcolumn[bufpos] = column;
          }
          throw e;
       }
      }
      

      【讨论】:

      • 什么是specialCharacter方法?
      猜你喜欢
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-03
      • 2015-03-31
      • 2014-08-12
      相关资源
      最近更新 更多