扩展 InputStreamReader 无法正常工作
Extending InputStreamReader does not work correctly
我这样扩展 InputStreamReader
public class AsteriskInputStreamReader extends InputStreamReader {
boolean ast;
AsteriskInputStreamReader(InputStream is) {
super(is);
}
@Override
public int read() throws IOException {
ast = !ast;
if (ast) return '*';
return super.read();
}
}
它必须在从原始 InputStream
获得的每个符号后添加 '*' 符号。
但是当我这样使用它时
InputStreamReader in = new AsteriskInputStreamReader(new FileInputStream("text.txt"));
int c;
while((c = in.read()) != -1){
System.out.print((char)c);
}
仅在文件中的最后一行 下才能正常工作。
前几行仅输出为一个“*”,没有任何文本。
为什么?
还有第二个问题。
当我用它创建 BufferedInputStream
并尝试获取文件的第一行时
BufferedReader reader = new BufferedReader(in);
System.out.println(reader.readLine());
我得到文件的第一行没有任何'*'。
获得我想要的内容的正确方法是什么:为 InputStreamReader
创建包装器,它将在原始输入的所有符号后添加星号?
第一部分的答案似乎是您正在写出回车符-return 字符。尝试通过将 System.out.print((char)c);
行替换为
来从输出中跳过它们
if (c != '\r') {
System.out.print((char) c);
}
对于第二部分,您还需要在 AsteriskInputStreamReader
class.
中覆盖 InputStreamReader
方法 read(char[] cbuf, int offset, int length)
而不是子类化 InputStreamReader
, create a separate Reader
that you can chain with other readers, so you can also apply it to readers that are not backed by InputStream
。
try (BufferedReader reader = new BufferedReader(
new AsteriskReader(
new InputStreamReader(
new FileInputStream("text.txt"))))) {
// ...
}
格式化以强调链。
它不适用于 BufferedReader
is that it doesn't call the read()
method that you overwrote, it calls one of the overloads that takes a buffer (read(char[] cbuf)
, read(char[] cbuf, int off, int len)
, or read(CharBuffer target)
) 的原因。
要实现要链接的 Reader
,子类 FilterReader
。
class AsteriskReader extends FilterReader {
private boolean ast;
private boolean astMarked;
public AsteriskReader(Reader in) {
super(in);
}
@Override
public int read() throws IOException {
// TODO Add handling of EOF
ast = !ast;
if (ast) return '*';
return super.read();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
// TODO Implement this, i.e. only read half number of characters from
// underlying reader, then inject '*' characters between all the
// chars actually read.
// Special handling for odd value of len.
int charsRead = super.read(cbuf, off, len);
return charsRead;
}
@Override
public long skip(long n) throws IOException {
// TODO Fix this to handle odd value of n.
long actualSkipped = super.skip(n / 2);
return actualSkipped * 2;
}
@Override
public void mark(int readAheadLimit) throws IOException {
super.mark((readAheadLimit + 1) / 2); // Underlying reader only needs to remember half
this.astMarked = this.ast;
}
@Override
public void reset() throws IOException {
super.reset();
this.ast = this.astMarked;
}
}
我这样扩展 InputStreamReader
public class AsteriskInputStreamReader extends InputStreamReader {
boolean ast;
AsteriskInputStreamReader(InputStream is) {
super(is);
}
@Override
public int read() throws IOException {
ast = !ast;
if (ast) return '*';
return super.read();
}
}
它必须在从原始 InputStream
获得的每个符号后添加 '*' 符号。
但是当我这样使用它时
InputStreamReader in = new AsteriskInputStreamReader(new FileInputStream("text.txt"));
int c;
while((c = in.read()) != -1){
System.out.print((char)c);
}
仅在文件中的最后一行 下才能正常工作。 前几行仅输出为一个“*”,没有任何文本。 为什么?
还有第二个问题。
当我用它创建 BufferedInputStream
并尝试获取文件的第一行时
BufferedReader reader = new BufferedReader(in);
System.out.println(reader.readLine());
我得到文件的第一行没有任何'*'。
获得我想要的内容的正确方法是什么:为 InputStreamReader
创建包装器,它将在原始输入的所有符号后添加星号?
第一部分的答案似乎是您正在写出回车符-return 字符。尝试通过将 System.out.print((char)c);
行替换为
if (c != '\r') {
System.out.print((char) c);
}
对于第二部分,您还需要在 AsteriskInputStreamReader
class.
InputStreamReader
方法 read(char[] cbuf, int offset, int length)
而不是子类化 InputStreamReader
, create a separate Reader
that you can chain with other readers, so you can also apply it to readers that are not backed by InputStream
。
try (BufferedReader reader = new BufferedReader(
new AsteriskReader(
new InputStreamReader(
new FileInputStream("text.txt"))))) {
// ...
}
格式化以强调链。
它不适用于 BufferedReader
is that it doesn't call the read()
method that you overwrote, it calls one of the overloads that takes a buffer (read(char[] cbuf)
, read(char[] cbuf, int off, int len)
, or read(CharBuffer target)
) 的原因。
要实现要链接的 Reader
,子类 FilterReader
。
class AsteriskReader extends FilterReader {
private boolean ast;
private boolean astMarked;
public AsteriskReader(Reader in) {
super(in);
}
@Override
public int read() throws IOException {
// TODO Add handling of EOF
ast = !ast;
if (ast) return '*';
return super.read();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
// TODO Implement this, i.e. only read half number of characters from
// underlying reader, then inject '*' characters between all the
// chars actually read.
// Special handling for odd value of len.
int charsRead = super.read(cbuf, off, len);
return charsRead;
}
@Override
public long skip(long n) throws IOException {
// TODO Fix this to handle odd value of n.
long actualSkipped = super.skip(n / 2);
return actualSkipped * 2;
}
@Override
public void mark(int readAheadLimit) throws IOException {
super.mark((readAheadLimit + 1) / 2); // Underlying reader only needs to remember half
this.astMarked = this.ast;
}
@Override
public void reset() throws IOException {
super.reset();
this.ast = this.astMarked;
}
}