I have java.io.Reader
as input parameter to the method.
This reader reads file, like "abc\def\jhk"
;
I need to return from the method an other java.io.Reader
, which skips reading "\"
chars. So the final file should be: "abcdefjhk"
.
private Reader convertToFilteredReader(Reader reader) {
Reader filteredReader = null;
// some code here
return filteredReader;
}
I have made this task by converting Reader
to String
, calling String.replace('\', '')
and then converting this String
into Reader
. But I don't like this solution because of double converting (Reader -> String -> Reader)
.
Give this a try. Disclaimer: only superficially tested. Comments show how this is simple to reuse.
import java.io.StringReader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
/**
* Subclasses should implement isExcluded to determine which characters will be
* 'swallowed' by the Reader
*
* @author g00se
* @version 1.0
*/
public abstract class ExclusionReader extends FilterReader {
private char[] singleCharBuf = { 0 };
public ExclusionReader(Reader in) {
super(in);
}
// Testing only
public static void main(String[] args) throws IOException {
Reader downstream = args.length < 1 ? new StringReader("abc\\def\\ghi")
: Files.newBufferedReader(Path.of(args[0]));
try (Reader in = new BackslashExcludingReader(downstream);
Writer out = new OutputStreamWriter(System.out)) {
in.transferTo(out);
}
}
public abstract boolean isExcluded(int codePoint);
@Override
public int read() throws IOException {
int result = read(singleCharBuf, 0, 1);
return result > -1 ? singleCharBuf[0] : result;
}
@Override
public int read(char[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(char[] buf, int off, int len) throws IOException {
if (len <= 0) {
if (len < 0) {
throw new IndexOutOfBoundsException();
} else if ((off < 0) || (off > buf.length)) {
throw new IndexOutOfBoundsException();
}
return 0;
}
int charsCopied = 0;
int c = -1;
while ((charsCopied + off) < len && (c = in.read()) > -1) {
if (!isExcluded(c)) {
buf[off + charsCopied] = (char) c;
charsCopied++;
}
}
int returnVal = charsCopied;
if (charsCopied == 0) {
returnVal = Math.min(charsCopied, c);
}
return returnVal;
}
// What YOU need
static class BackslashExcludingReader extends ExclusionReader {
public BackslashExcludingReader(Reader in) {
super(in);
}
@Override
public boolean isExcluded(int codePoint) {
return codePoint == '\\';
}
}
}