下面列出了java.io.Reader#mark ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* @return the token if one was found, the empty string if no data was
* available to read or <code>null</code> if data other than a
* token was found
*/
static String readToken(Reader input) throws IOException {
StringBuilder result = new StringBuilder();
skipLws(input);
input.mark(1);
int c = input.read();
while (c != -1 && isToken(c)) {
result.append((char) c);
input.mark(1);
c = input.read();
}
// Use mark(1)/reset() rather than skip(-1) since skip() is a NOP
// once the end of the String has been reached.
input.reset();
if (c != -1 && result.length() == 0) {
return null;
} else {
return result.toString();
}
}
private static boolean isCFENCODED(Reader _inFile) throws IOException {
CharArrayWriter buffer = new CharArrayWriter(CFENCODE_HEADER_LEN);
_inFile.mark(CFENCODE_HEADER_LEN);
for (int i = 0; i < CFENCODE_HEADER_LEN; i++) {
buffer.write(_inFile.read());
}
if (buffer.toString().equals(CFENCODE_HEADER)) {
return true;
}
_inFile.reset();
return false;
}
public static String markRead(Reader a, int x, int y) throws IOException {
int m = 0;
int r;
StringBuilder builder = new StringBuilder();
do {
m++;
r = a.read();
if (m == x)
a.mark((x + y));
if (m == (x + y))
a.reset();
if (r != -1)
builder.append((char) r);
} while (r != -1);
return builder.toString();
}
private static int parse(Reader reader) {
try {
reader.mark(1);
int first = reader.read();
reader.reset();
if (HttpParser.isAlpha(first)) {
return HttpParser.readHostDomainName(reader);
} else if (HttpParser.isNumeric(first)) {
return HttpParser.readHostIPv4(reader, false);
} else if ('[' == first) {
return HttpParser.readHostIPv6(reader);
} else {
// Invalid
throw new IllegalArgumentException();
}
} catch (IOException ioe) {
// Should never happen
throw new IllegalArgumentException(ioe);
}
}
@Test
void testRead() throws IOException {
Reader reader = new FastStringReader("ScalaScalaScala");
assertTrue(reader.ready());
assertEquals('S', reader.read());
char[] dst = new char[4];
assertEquals(4, reader.read(dst));
assertArrayEquals(new char[]{'a', 'l', 'a'}, dst);
reader.mark(15);
CharBuffer buff = CharBuffer.allocate(15);
assertEquals(10, reader.read(buff));
assertEquals(5, buff.remaining());
buff.flip();
assertEquals("ScalaScala", buff.toString());
}
private static char[] readCharArray(Reader reader) throws IOException {
if (reader.markSupported()) {
reader.mark(1024);
}
int length = reader.read();
int delimiter = reader.read();
if (delimiter != 0) {
if (reader.markSupported()) {
reader.reset();
}
throw new IOException("Unsupported reply exception");
}
char[] buffer = new char[length];
reader.read(buffer);
return buffer;
}
public static String markRead(Reader a, int x, int y) throws IOException {
int m = 0;
int r;
StringBuilder builder = new StringBuilder();
do {
m++;
r = a.read();
if (m == x)
a.mark((x + y));
if (m == (x + y))
a.reset();
if (r != -1)
builder.append((char) r);
} while (r != -1);
return builder.toString();
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
/**
* Some text editors (e.g. Notepad on Windows) write a BOM as first character,
* when writing an UTF-8 encoded text file. BOMs are unicode characters encoded
* as 2,3, or 4-byte sequence specific for the unicode type (UTF-8, 16, ...) and
* little vs. big-endian byte order. Java Readers and InputStreams don't filter
* BOM out of the stream. Thus, we need to do it ourselfes.
* @param reader
*/
public static void skip(Reader reader) {
try {
reader.mark(1);
char[] possibleBOM = new char[1];
if (reader.read(possibleBOM) == 1 && possibleBOM[0] != '\ufeff')
reader.reset();
}
catch (IOException ioe) {}
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
private static boolean trailingSpace(Reader in) throws IOException {
boolean trailing = false;
if (!in.markSupported()) {
// oh well
return true;
} else {
// make readAheadLimit huge -
// in practice, AVA was passed a StringReader from X500Name,
// and StringReader ignores readAheadLimit anyways
in.mark(9999);
while (true) {
int nextChar = in.read();
if (nextChar == -1) {
trailing = true;
break;
} else if (nextChar == ' ') {
continue;
} else if (nextChar == '\\') {
int followingChar = in.read();
if (followingChar != ' ') {
trailing = false;
break;
}
} else {
trailing = false;
break;
}
}
in.reset();
return trailing;
}
}
private static String readLineFromReaderWithMark(final Reader input)
throws IOException {
char[] cbuf = new char[charBufferSize];
try {
input.mark(charBufferSize);
} catch (IOException e) {
// this should never happen
LOG.warning("Caught exception setting mark on supporting reader: " + e);
// fallback
return readLineFromReaderWithoutMark(input);
}
// could be changed into do..while, but then
// we might create an additional StringBuilder
// instance at the end of the stream
int count = input.read(cbuf);
if (count == EOF) // we are at the end of the input data
return null;
StringBuilder line = new StringBuilder(expectedLineLength);
// now work on the buffer(s)
int ls = lineSeparatorIndex(cbuf, count);
while (ls == -1) {
line.append(cbuf, 0, count);
count = input.read(cbuf);
if (count == EOF) {
// we are at the end of the input data
return line.toString();
}
ls = lineSeparatorIndex(cbuf, count);
}
line.append(cbuf, 0, ls);
// correct ls if we have \r\n
int skipLS = 1;
if (ls + 1 < count) {
// we are not at the end of the buffer
if (cbuf[ls] == '\r' && cbuf[ls + 1] == '\n') {
skipLS++;
}
} else {
if (cbuf[ls] == '\r' && input.read() == '\n') {
skipLS++;
}
}
//reset() and skip over last linesep
input.reset();
input.skip(line.length() + skipLS);
return line.toString();
}
/**
* LHEX can be read unambiguously with or without surrounding quotes so this
* parsing method for LHEX permits optional surrounding double quotes. Some
* buggy clients (libwww-perl for DIGEST auth) are known to send quoted LHEX
* when the specification requires just LHEX.
*
* <p>
* LHEX are, literally, lower-case hexadecimal digits. This implementation
* allows for upper-case digits as well, converting the returned value to
* lower-case.
*
* @return the sequence of LHEX (minus any surrounding quotes) if any was
* found, or <code>null</code> if data other LHEX was found
*/
static String readLhex(Reader input) throws IOException {
StringBuilder result = new StringBuilder();
boolean quoted = false;
skipLws(input);
input.mark(1);
int c = input.read();
if (c == '"') {
quoted = true;
} else if (c == -1 || !isHex(c)) {
return null;
} else {
if ('A' <= c && c <= 'F') {
c -= ('A' - 'a');
}
result.append((char) c);
}
input.mark(1);
c = input.read();
while (c != -1 && isHex(c)) {
if ('A' <= c && c <= 'F') {
c -= ('A' - 'a');
}
result.append((char) c);
input.mark(1);
c = input.read();
}
if (quoted) {
if (c != '"') {
return null;
}
} else {
// Use mark(1)/reset() rather than skip(-1) since skip() is a NOP
// once the end of the String has been reached.
input.reset();
}
if (c != -1 && result.length() == 0) {
return null;
} else {
return result.toString();
}
}
/**
* Returns {@link ProbeResult#SUPPORTED} if the given storage appears to begin with an expected keyword
* Returning {@code SUPPORTED} from this method does not guarantee that reading or writing will succeed,
* only that there appears to be a reasonable chance of success based on a brief inspection of the storage
* header.
*
* @param connector information about the storage (URL, stream, JDBC connection, <i>etc</i>).
* @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable.
* @throws DataStoreException if an I/O or SQL error occurred.
*/
@SuppressWarnings("null")
public final ProbeResult probeContent(final StorageConnector connector) throws DataStoreException {
char[] keyword = null;
int pos = 0;
try {
final ByteBuffer buffer = connector.getStorageAs(ByteBuffer.class);
final Reader reader;
if (buffer != null) {
buffer.mark();
reader = null;
} else {
// User gave us explicitly a Reader (e.g. a StringReader wrapping a String instance).
reader = connector.getStorageAs(Reader.class);
if (reader == null) {
return ProbeResult.UNSUPPORTED_STORAGE;
}
reader.mark(READ_AHEAD_LIMIT);
}
/*
* Ignore leading spaces and comments if any, then get a keyword no longer than 'maxLength'.
* That keyword shall be followed by [ or (, ignoring whitespaces.
*/
int c;
while ((c = nextAfterSpaces(buffer, reader)) == COMMENT) {
toEndOfLine(buffer, reader);
}
int s;
if ((s = isKeywordChar(c)) >= ACCEPT) {
keyword = new char[maxLength];
do {
if (s == ACCEPT) {
if (pos >= keyword.length) {
pos = 0; // Keyword too long.
break;
}
keyword[pos++] = (char) c;
}
c = (buffer == null) ? IOUtilities.readCodePoint(reader) : buffer.hasRemaining() ? (char) buffer.get() : -1;
} while ((s = isKeywordChar(c)) >= ACCEPT);
/*
* At this point we finished to read and store the keyword.
* Verify if the keyword is followed by a character that indicate a keyword end.
*/
if (Character.isWhitespace(c)) {
c = nextAfterSpaces(buffer, reader);
}
if (!isPostKeyword(c)) {
pos = 0;
}
}
if (buffer != null) {
buffer.reset();
} else {
reader.reset();
}
if (c < 0) {
return ProbeResult.INSUFFICIENT_BYTES;
}
} catch (IOException e) {
throw new DataStoreException(e);
}
return forKeyword(keyword, pos);
}
private String nextToken(Reader reader) throws java.io.IOException {
StringBuilder token = new StringBuilder();
int i;
char ch;
char ch2;
boolean previousWasDigit = false;
boolean tokenCharFound = false;
if (!reader.ready()) {
return null;
}
while ((i = reader.read()) != -1) {
ch = (char) i;
if (ch == ':') {
String tokenString = token.toString() + ':';
if (tokenString.equals("From:") || tokenString.equals("Return-Path:") || tokenString.equals("Subject:") || tokenString.equals("To:")) {
return tokenString;
}
}
if (Character.isLetter(ch) || ch == '-' || ch == '$' || ch == '€'
|| ch == '!' || ch == '\'') {
tokenCharFound = true;
previousWasDigit = false;
token.append(ch);
} else if (Character.isDigit(ch)) {
tokenCharFound = true;
previousWasDigit = true;
token.append(ch);
} else if (previousWasDigit && (ch == '.' || ch == ',')) {
reader.mark(1);
previousWasDigit = false;
i = reader.read();
if (i == -1) {
break;
}
ch2 = (char) i;
if (Character.isDigit(ch2)) {
tokenCharFound = true;
previousWasDigit = true;
token.append(ch);
token.append(ch2);
} else {
reader.reset();
break;
}
} else if (ch == '\r') { //NOPMD
// cr found, ignore
} else if (ch == '\n') {
// eol found
tokenCharFound = true;
previousWasDigit = false;
token.append(ch);
break;
} else if (tokenCharFound) {
break;
}
}
if (tokenCharFound) {
// System.out.println("Token read: " + token);
return token.toString();
} else {
return null;
}
}
private void handleEscaping(final Reader source,
final Position sourcePosition,
final StringSection currentSection,
final StringBuilder lookAhead) throws IOException, FinishedReadingException {
//if we get here, we just read in a back-slash from the source, now figure out what to do with it
int c = read(source, sourcePosition, lookAhead);
/*
The _only_ special escaping this template engine allows is to escape the sequences:
${ and <% and potential slashes in front of these. Escaping in any other sections of the
source string is ignored. The following is a source -> result mapping of a few values, assume a
binding of [alice: 'rabbit'].
Note: we don't do java escaping of slashes in the below
example, i.e. the source string is what you would see in a text editor when looking at your template
file:
source string result
'bob' -> 'bob'
'\bob' -> '\bob'
'\\bob' -> '\\bob'
'${alice}' -> 'rabbit'
'\${alice}' -> '${alice}'
'\\${alice}' -> '\rabbit'
'\\$bob' -> '\\$bob'
'\\' -> '\\'
'\\\' -> '\\\'
'%<= alice %>' -> 'rabbit'
'\%<= alice %>' -> '%<= alice %>'
*/
if (c == '\\') {
//this means we have received a double backslash sequence
//if this is followed by ${ or <% we output one backslash
//and interpret the following sequences with groovy, if followed by anything
//else we output the two backslashes and continue as usual
source.mark(3);
int d = read(source, sourcePosition, lookAhead);
c = read(source, sourcePosition, lookAhead);
clear(lookAhead);
if ((d == '$' && c == '{') ||
(d == '<' && c == '%')) {
source.reset();
currentSection.data.append('\\');
return;
} else {
currentSection.data.append('\\');
currentSection.data.append('\\');
currentSection.data.append((char) d);
}
} else if (c == '$') {
c = read(source, sourcePosition, lookAhead);
if (c == '{') {
currentSection.data.append('$');
} else {
currentSection.data.append('\\');
currentSection.data.append('$');
}
} else if (c == '<') {
c = read(source, sourcePosition, lookAhead);
if (c == '%') {
currentSection.data.append('<');
} else {
currentSection.data.append('\\');
currentSection.data.append('<');
}
} else {
currentSection.data.append('\\');
}
currentSection.data.append((char) c);
clear(lookAhead);
}
/**
* Read lines from a (buffered / mark-able) reader keeping all new-lines and line-feeds.
* @param reader the reader
* @return the line iterator
*/
protected static Iterator<CharSequence> readLines(final Reader reader) {
if (!reader.markSupported()) {
throw new IllegalArgumentException("mark support in reader required");
}
return new Iterator<CharSequence>() {
private CharSequence next = doNext();
private CharSequence doNext() {
StringBuffer strb = new StringBuffer(64); // CSOFF: MagicNumber
int c;
boolean eol = false;
try {
while ((c = reader.read()) >= 0) {
if (eol) {// && (c != '\n' && c != '\r')) {
reader.reset();
break;
}
if (c == '\n') {
eol = true;
}
strb.append((char) c);
reader.mark(1);
}
} catch (IOException xio) {
return null;
}
return strb.length() > 0 ? strb : null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public CharSequence next() {
CharSequence current = next;
if (current != null) {
next = doNext();
}
return current;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
};
}