Java?IO流之StringWriter和StringReader用法分析
簡介
StringWriter和StringReader分別繼承自Writer和Reader抽象類,作用就是將字符串String類型適配到StringWriter和StringReader類.
其中StringWriter實(shí)際上是用StringBuffer實(shí)現(xiàn)的,StringBuffer是一個線程安全的類,實(shí)際上默認(rèn)的是16個字符的char數(shù)組.所以通過方法write()和append()等其他重載的方法.將字符串添加到StringBuffer中,可以調(diào)用toString()或者getBuffer()方法顯示StringWriter流中所有的數(shù)據(jù).其中close()方法和flush()方法,無實(shí)際的功能,只是簡單的繼承.
StringReader的有參構(gòu)造方法傳入的是String類型的數(shù)據(jù),通過read()重載方法讀取流中部分或者全部的字符內(nèi)容.
StringWriter介紹
1.構(gòu)造方法
public StringWriter() {} public StringWriter(int initialSize) {}
無參構(gòu)造方法,創(chuàng)建的是默認(rèn)大小為StringBuffer的StringWriter流,其中StringBuffer底層實(shí)際是一個字符數(shù)組,默認(rèn)大小是16個字符.
有參構(gòu)造方法,創(chuàng)建的是指定大小的StringBuffer的StringWriter流,也就是指定initialSize個字符的字符數(shù)組.
2.內(nèi)部變量
private StringBuffer buf;
StringWriter流中緩沖區(qū)實(shí)際上通過StringBuffer來實(shí)現(xiàn)的.
3. 內(nèi)部方法
public void write(int c) {} public void write(char cbuf[], int off, int len){} public void write(String str) {} public void write(String str, int off, int len){} public StringWriter append(CharSequence csq){} public StringWriter append(CharSequence csq, int start, int end){} public StringWriter append(char c){} public String toString() {} public StringBuffer getBuffer() {} public void flush() {} public void close() {}
write(int c)
---將單個字符寫到流中.write(char cbuf[] ,int off,int len)
---將字符數(shù)組cbuf中off開始,len個字符寫到流中.write(String str)
---將字符串str寫到流中.write(String str,int off,int len)
---將字符串str中off位置開始,len個字符寫到流中.append(charsequence csq)
---將字符序列csq寫到流中.append(charsequence csq,int start ,int end)
----將字符序列中start到end之間字符寫到流中.append(char c)
---將單個字符寫到流中.toString()
---將流中所有字符轉(zhuǎn)換成字符串返回.getBuffer()
----將流中內(nèi)容,實(shí)際是StringBuffer返回.flush()
---僅僅是繼承,方法內(nèi)沒有任何實(shí)現(xiàn).close()
----僅僅是繼承,方法內(nèi)沒有任何實(shí)現(xiàn).
StringReader介紹
1.構(gòu)造方法
public StringReader(String s) {}
有參構(gòu)造方法,傳入的實(shí)際上是流中內(nèi)容為字符串s.
2.內(nèi)部變量
private String str; private int length; private int next = 0; private int mark = 0;
str
---StringReader流中實(shí)際的數(shù)據(jù)就是通過構(gòu)造方法傳入的字符串str.length
---流中字符串的長度.next
---要讀取的下一個字符的位置.mark
---標(biāo)記字符位置,調(diào)用mark()方法會將當(dāng)前位置保存到mark中.
3. 內(nèi)部方法
private void ensureOpen(){} public int read(){} public int read(char cbuf[], int off, int len){} public long skip(long ns){} public boolean ready(){} public boolean markSupported() {} public void mark(int readAheadLimit){} public void reset(){} public void close(){}
ensureOpen()
---確保流沒有關(guān)閉,實(shí)際判斷是流中內(nèi)容字符串str不為null.read()
---從流中讀取一個字符.read(char cbuf[],int off,int len)
---將流中最多l(xiāng)en個字符讀取到字符數(shù)組cbuf中,cbuf中從off開始.skip(long ns)
---跳過ns個字符.ready()
---流是否準(zhǔn)備讀取.markSupported()
---是否支持標(biāo)記mark(int readAheadLimit)
---標(biāo)記當(dāng)前位置,readAheadLimit表示的是在標(biāo)記有效情況下,從當(dāng)前位置開始可取的最大字符數(shù).reset()
---將流中當(dāng)前位置重置到標(biāo)記位置.close()
---關(guān)閉流,實(shí)際上是將流中內(nèi)容字符串str置為null.
案例
public class StringWriterDemo { public static void main(String[] args) throws IOException { testStringWriter(); testStringReader(); testOfAnotherStringWriter(); } //測試StringWriter private static void testStringWriter() throws IOException { StringWriter sw = new StringWriter(); sw.append("this is a"); sw.write("demo of StringWriter"); System.out.println(sw.toString()); sw.close(); } //測試StringReader private static void testStringReader() throws IOException { String content = "this is a demo of StringReader"; StringReader sr = new StringReader(content); int c; while((c=sr.read())!=-1) { System.out.println((char)c); } sr.close(); } //將讀取的數(shù)據(jù)先寫到StringWriter流中,然后直接調(diào)用toString()方法打印結(jié)果 private static void testOfAnotherStringWriter() throws IOException { FileReader fr = new FileReader("D:\\java.txt"); BufferedReader br = new BufferedReader(fr); StringWriter sw = new StringWriter(); int n; char cbuf[] = new char[1024]; while((n=br.read(cbuf))!=-1) { sw.write(cbuf, 0, n); } System.out.println(sw.toString()); fr.close(); br.close(); } }
源碼分析
1.StringWriter源碼分析
public class StringWriter extends Writer { //StringWriter中緩沖功能是通過StringBuffer來實(shí)現(xiàn)的. private StringBuffer buf; //創(chuàng)建默認(rèn)緩沖為16個字符的StringWriter.默認(rèn)的StringBuffer實(shí)際是大小為16個字符的字符數(shù)組. public StringWriter() { buf = new StringBuffer(); lock = buf; } //創(chuàng)建指定大小StringBuffer的StringWriter,也就是指定了initialSize個字符的字符數(shù)組. public StringWriter(int initialSize) { if (initialSize < 0) { throw new IllegalArgumentException("Negative buffer size"); } buf = new StringBuffer(initialSize); lock = buf; } //向流寫入單個字符c public void write(int c) { buf.append((char) c); } //將字符數(shù)組cbuf中off位置開始,len個字符寫到流中 public void write(char cbuf[], int off, int len) { if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } buf.append(cbuf, off, len); } //將字符串str寫到流中 public void write(String str) { buf.append(str); } //將字符串str中off位置開始,len個字符寫到流中 public void write(String str, int off, int len) { buf.append(str.substring(off, off + len)); } //將字符序列csq添加到流中. public StringWriter append(CharSequence csq) { if (csq == null) write("null"); else write(csq.toString()); return this; } //將字符序列csq中start位置到end之間的字符添加到流中 public StringWriter append(CharSequence csq, int start, int end) { CharSequence cs = (csq == null ? "null" : csq); write(cs.subSequence(start, end).toString()); return this; } //向流中添加一個字符c public StringWriter append(char c) { write(c); return this; } //將流中字符轉(zhuǎn)換成字符串返回. public String toString() { return buf.toString(); } //返回流的內(nèi)容,即StringBuffer public StringBuffer getBuffer() { return buf; } //刷新流,沒有具體實(shí)現(xiàn). public void flush() { } //關(guān)閉流后讀取數(shù)據(jù)不會拋出異常,因?yàn)闆]有具體實(shí)現(xiàn) public void close() throws IOException { } }
2,StringReader源碼分析
public class StringReader extends Reader { //流中實(shí)際數(shù)據(jù)就是通過構(gòu)造方法傳入str字符串. private String str; //字符串str的長度 private int length; //下一個要讀取字符的位置. private int next = 0; //標(biāo)記的位置. private int mark = 0; //創(chuàng)建一個StringReader流,參數(shù)傳入的是字符串s public StringReader(String s) { this.str = s; this.length = s.length(); } //確保流沒有關(guān)閉,實(shí)際判斷的是StringReader構(gòu)造方法是否有傳入字符串. private void ensureOpen() throws IOException { if (str == null) throw new IOException("Stream closed"); } //讀取單個字符 public int read() throws IOException { synchronized (lock) { ensureOpen(); if (next >= length) return -1; return str.charAt(next++); } } //將緩沖區(qū)中最多l(xiāng)en個字符寫到字符數(shù)組cbuf中,位置從off開始,長度為len個 public int read(char cbuf[], int off, int len) throws IOException { synchronized (lock) { ensureOpen(); //檢測參數(shù)的合法性 if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } //超過字符串的長度,返回-1 if (next >= length) return -1; //剩余可讀取的字符為length-next, //如果len超過剩余可讀取字符,實(shí)際只能讀取剩余可讀取字符 //如果len小于剩余可讀取字符,實(shí)際上讀取的是len個字符 int n = Math.min(length - next, len); str.getChars(next, next + n, cbuf, off); next += n; return n; } } //跳過ns個字符,返回跳過的字符數(shù) public long skip(long ns) throws IOException { synchronized (lock) { ensureOpen(); if (next >= length) return 0; // Bound skip by beginning and end of the source //緩沖區(qū)中剩余字符數(shù)與要跳過的字符數(shù)比較.取較小值 long n = Math.min(length - next, ns); n = Math.max(-next, n); next += n; return n; } } //流是否準(zhǔn)備讀取. public boolean ready() throws IOException { synchronized (lock) { ensureOpen(); return true; } } //流是否支持標(biāo)記 public boolean markSupported() { return true; } //標(biāo)記緩沖區(qū)中當(dāng)前位置,readAheadLimit表示的是在保留標(biāo)記的情況下,最大可讀取的字符數(shù) public void mark(int readAheadLimit) throws IOException { if (readAheadLimit < 0){ throw new IllegalArgumentException("Read-ahead limit < 0"); } synchronized (lock) { ensureOpen(); mark = next; } } //將緩沖區(qū)當(dāng)前位置重置到標(biāo)記位置 public void reset() throws IOException { synchronized (lock) { ensureOpen(); next = mark; } } //關(guān)閉流,釋放相關(guān)資源(實(shí)際只是將流中內(nèi)容字符串置為空) public void close() { str = null; } }
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringCloud使用Feign實(shí)現(xiàn)服務(wù)調(diào)用
這篇文章主要為大家詳細(xì)介紹了SpringCloud使用Feign實(shí)現(xiàn)服務(wù)調(diào)用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04SpringBoot Pom文件依賴及Starter啟動器詳細(xì)介紹
這篇文章主要介紹了SpringBoot Pom文件的依賴與starter啟動器的作用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09使用sharding-jdbc實(shí)現(xiàn)水平分庫+水平分表的示例代碼
本文主要介紹了使用sharding-jdbc實(shí)現(xiàn)水平分庫+水平分表,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12java獲取百度網(wǎng)盤真實(shí)下載鏈接的方法
這篇文章主要介紹了java獲取百度網(wǎng)盤真實(shí)下載鏈接的方法,涉及java針對URL操作及頁面分析的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07Java實(shí)現(xiàn)整數(shù)的逆序輸出的三種方法
這篇文章主要介紹了Java實(shí)現(xiàn)整數(shù)的逆序輸出的三種方法,第一種是無限制整數(shù)的逆序輸出,第二種是非負(fù)整數(shù)的逆序輸出,第三種是非特殊情況的逆序輸出,每種方法給大家講解的非常詳細(xì)需要的朋友可以參考下2022-11-11