假设您正在编写一个删除所有字符实例的阅读器(假设您正在删除“x”。)
你可以这样写:
public class ExampleReader extends FilterReader {
public ExampleReader(Reader in) {
super(in);
}
@Override
public int read() throws IOException {
int ch;
while ((ch = in.read()) != -1) {
if (ch != 'x') {
return ch;
}
}
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int charsRead = in.read(cbuf, off, len);
if (charsRead == -1) {
return -1;
}
// srcPos will always be >= dstPos
int charsRemoved = 0;
int srcEnd = off + charsRead;
for (int srcPos = off, dstPos = off; srcPos < srcEnd; srcPos++, dstPos++) {
char ch = cbuf[srcPos];
if (ch == 'x') {
dstPos--;
charsRemoved++;
} else {
cbuf[dstPos] = cbuf[srcPos];
}
}
return charsRead - charsRemoved;
}
}
在代码审查中,另一位开发人员声称,如果您返回小于len
,则根据返回值,您不应该在读取的切片之外写入任何字符。但是,文档中根本没有提到这一点 - 他们只是说len
传入的值是要读取的最大字符数。
我自己的观点是,如果你通过了len
,那么你就被允许写任何你想要的东西off..off+len
,如果你碰巧返回更少,那么你就不能保证数组其余部分的内容。同样,如果我打电话给读者,我不会假设返回的范围之外的数据对阅读是有意义的。
谁是对的?
(作为旁注,我实际实现的是行分隔符规范化,\r\n 和其他 \n。我确信在 Guava 中会有如此常见的东西,但它似乎不是。真的这么稀有的任务?)