【问题标题】:How to implement a custom FilterReader?如何实现自定义FilterReader?
【发布时间】:2016-07-06 13:02:54
【问题描述】:

我正在尝试实现自定义 FilterReader 类。该课程应该改变它所读的内容(不管如何)。我遇到的问题是转换后的字符串比读取到 char 缓冲区中的原始字符串长,所以当我尝试将新字符串塞入缓冲区时,我得到一个 ArrayIndexOutOfBoundsException

这是我的自定义 FilterReader 类的 read() 方法:

@Override
public int read(char[] cbuf, int off, int len) throws IOException {
    int result = in.read(cbuf, off, len);

    if( result != -1 ){
        String str = new String(cbuf, off, len);
        str = someStringTranformationMethod(str);

        //cbuf = new char[str.length()];

        str.getChars(0, str.length(), cbuf, 0);

        result = str.length();
    }

    return result;
}

我想我可以通过为 cbuf 重新分配一个新的字符缓冲区来解决它,这是我在注释行中尝试的。但是,这似乎根本不起作用,因为我的阅读器输出是原始(未转换的)字符串。

我有一种感觉,我在这里完全倒退了,但是在网上找到这些东西的任何好例子并不容易。我发现的所有自定义 FilterReaders 刚刚对字符进行了一些基本的大写/小写,其中新字符串的长度与原始字符串的长度相同。

那么我将如何使用字符串转换函数来实现这一点,该函数会产生比原始字符串更长的字符串?

【问题讨论】:

  • 如果 str.lengths 在转换前后的商有一个上限,则读取可以相应地减小长度,因此转换后的字符仍然可以放入缓冲区。
  • 作为(更复杂的)替代方案, someStringTranformationMethod 必须知道其最大输出长度并缓存多余的字符,以便在下一次调用时转发。在这种情况下,转换器应该提供一种方法来通知调用者有关待处理数据的长度,以便指示没有额外读取的调用。 (这是为了避免缓存数据的无限积累。)
  • 根据len的值,你能知道结果字符串的长度吗?如果是这样,您不能计算要从源流中读取的字符数,这将为您提供len 字符输出?
  • @WeaponsGrade 即使该信息可用,但对于请求一个字符但转换为两个字符的情况没有帮助。
  • @StefanHaustein 在您的情况下,您返回单个字符,是的,您必须缓冲额外的字符。毕竟它是一个流,因此暗示在返回 -1 之前还有更多字符可用。

标签: java bufferedreader filereader streamreader reader


【解决方案1】:

您需要使您的实现有状态并跟踪“剩余”字符:

private String str = "";
private int pos = 0;

public int read(char[] cbuf, int off, int len) throws IOException {
  if (pos == str.length()) {
    // No leftovers from a previous call available, need to actully read more
    int result = in.read(cbuf, off, len);
    if( result <= 0 ){
      return -1;
    }
    str = new String(cbuf, off, result);
    str = someStringTranformationMethod(str);
    pos = 0;
  }

  // Return as much as we have available, but not more than len
  int available = Math.min(str.length() - pos, len);     
  str.getChars(pos, pos + available, cbuf, off);
  pos += available;
  return available;
}

请注意,如果尚未到达流的末尾,read() 只需读取 (at least) 一个字符。此实现利用了这一点。

【讨论】:

    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多