PushbackInputStream 理解
這是2014.9.12做的一篇筆記,重新整理下。
PushbackInputStream 存在的意義就是允許我試探性的讀取資料流,如果不是我們想要的則返還回去,之所以能夠這樣,因為其內部維護了一個pushback buffer緩衝區。建構函式可以指定返回的位元組個數。
示例
public class GetIntFromFile { public int getInt(PushbackInputStream input) { int c, res = 0; try { //跳過空白 while ((c = input.read()) == ' ') ; //不是數字,不是+-符號 if (!isDigit(c) && c != -1 && c != '+' && c != '-') { input.unread(c); return -1;//讀出的不是一個數字 } int sign = (c == '-') ? -1 : 1; //符號 if (c == '+' || c == '-') c = input.read(); for (res = 0; isDigit(c); c = input.read()) res = 10 * res + (c - '0'); res *= sign; if (c != -1) input.unread(c); } catch (IOException e) { e.printStackTrace(); } return res; } private boolean isDigit(int c) { if (c >= '0' && c <= '9') return true; return false; } public static void main(String[] args) throws Exception { PushbackInputStream input = new PushbackInputStream(new FileInputStream("/tmp/int.txt"), 1); System.out.println((new GetIntFromFile().getInt(input))); } }
PushbackInputStream 原始碼分析
PushbackInputStream 之所以能實現這樣的功能,就是因為其內部單獨維護了一個緩衝區,讀取流的時候先讀這個緩衝區,回退(push back)的時候就是把字元放置到這個緩衝區中。
public int read() throws IOException { ensureOpen(); if (pos < buf.length) { return buf[pos++] & 0xff; } return super.read(); } public void unread(int b) throws IOException { ensureOpen(); if (pos == 0) { throw new IOException("Push back buffer is full"); } buf[--pos] = (byte)b; }
學習這個類的時候其實聯絡到了《K&R》P82中那個從檔案讀取整數的例子,上述示例便是實現了同樣的功能。
C 語言
標準庫提供了 ungetc,但是相比於 K&R 中提供的 ungetch 功能受限。我們看看 ungetch 是如何實現的就對 PushbackInputStream 的實現一目瞭然了。
#include <stdio.h> #define BUFSIZE 100 char buf[BUFSIZE]; /* buffer for ungetch */ int bufp = 0; /* next free position in buf */ int getch(void) /* get a (possibly pushed-back) character */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* push character back on input */ { if (bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }