Stream
Stream流的三類方法:
獲取Stream流
中間方法
流水線上的操作,一次操作完畢之后,還可以繼續進行其他操作 終結方法
是流水線上的最后一個操作,一個Stream流只能有一次終結方法
創建Stream流的方式:
方式1:根據集合獲取流
Collection根接口中提供了stream()方法可以獲取流。 單列集合:直接調用stream0方法即可 雙列集合:先獲取鍵和值的單列集合,再通過集合獲取鍵和值各自的Stream流 方式2:根據of方法獲取流
Stream類提供了靜態的of()方法,可以創建一個流對象 Stream.of(T …values)
Stream流的常用方法:
成員方法方法作用返回值類型方法種類 filter 過濾 Stream 中間方法 limit 取用前幾個 Stream 中間方法 skip 跳過前幾個 Stream 中間方法 map 映射 Stream 中間方法 count 統計個數 long 終結方法 forEach 逐一處理 void 終結方法 靜態方法 方法作用 返回值類型 方法種類 static concat(流1,流2) 組合兩個流 Stream 靜態方法
Stream流的使用注意:
一個Stream流對象只能操作一次 調用中間方法會返回新流,以便下次操作使用 終結方法如果沒調用,中間方法也不會執行
案例:
已知兩個集合數據:
第一個集合隊伍數據:令狐沖,風清揚,任我行,東方不敗,岳不群 第二個集合隊伍數據:馬云,李彥宏,劉強東,馬化騰,馬保國
要求:
第一個隊伍只要名字為3個字的姓名 第一個隊伍篩選之后只要前3人 第二個隊伍只要姓馬的姓名 第二個隊伍不要前2人 .將兩個隊伍合并到一個隊伍 根據姓名創建Person對象,存儲到一個新集合
package com. demo_4Stream 流
; import java. util. ArrayList ;
import java. util. List ;
import java. util. function. Consumer ;
import java. util. function. Function ;
import java. util. stream. Collectors ;
import java. util. stream. Stream ; public class Demo_07_ 案例
{ public static void main ( String [ ] args
) { Stream < String > s1
= Stream . of ( "令狐沖" , "風清揚" , "任我行" , "東方不敗" , "岳不群" ) ; Stream < String > s2
= Stream . of ( "馬云" , "李彥宏" , "劉強東" , "馬化騰" , "馬保國" ) ; Stream < String > s3
= s1
. filter ( a
-> a
. length ( ) == 3 ) ; Stream < String > s8
= s3
. limit ( 3 ) ; Stream < String > s4
= s2
. filter ( s
-> s
. startsWith ( "馬" ) ) ; Stream < String > s7
= s4
. skip ( 2 ) ; Stream < String > result
= Stream . concat ( s7
, s8
) ; Stream < Person > s5
= result
. map ( new Function < String , Person > ( ) { @Override public Person apply ( String s
) { return new Person ( s
) ; } } ) ; List < Person > personList
= s5
. collect ( Collectors . toList ( ) ) ; personList
. forEach ( new Consumer < Person > ( ) { @Override public void accept ( Person person
) { System . out
. println ( person
) ; } } ) ; }
}
1.字節流
1.1 IO流概述和分類
IO流概述:
IO:輸入/輸出(Input/Output) 流:是一種抽象概念,是對數據傳輸的總稱。也就是說數據在設備間的傳輸稱為流,流的本質是數據傳輸 IO流就是用來處理設備間數據傳輸問題的 常見的應用:文件復制;文件上傳;文件下載
IO流分類:
按照數據的流向 輸入流:讀數據 輸出流:寫數據 按照數據類型來分
字節流 字節輸入流;字節輸出流 字符流 字符輸入流;字符輸出流
一般來說,我們說IO流的分類是按照數據類型 來分的
那么這兩種流都在什么情況下使用呢?
如果數據通過Window自帶的記事本軟件打開,我們還可以讀懂里面的內容 ,就使用字符流, 否則使用字節流。如果你不知道該使用哪種類型的流,就使用字節流
1.2 字節流寫數據
字節流抽象基類:
InputStream:這個抽像類是表示字節輸入流的所有類的超類 OutputStream:這個抽象類是表示字節輸出流的所有類的超類 子類名特點:子類名稱都是以其父類名作為子類名的后綴
FileOutputStream::文件輸出流用于將數據寫入File
FileOutputStream(String name):創建文件輸出流以指定的名稱寫入文件
使用字節輸出流寫數據的步驟:
創建字節輸出流對象(調用系統功能創建了文件,創建字節輸出流對象,讓字節輸出流對象指向文件) 調用字節輸出流對象的寫數據方法 釋放資源(關閉此文件輸出流并釋放與此流相關聯的任何系統資源)
package demo_01 ; import java. io. FileOutputStream ;
import java. io. IOException ; public class FileOutputStreamDemo { public static void main ( String [ ] args
) throws IOException { FileOutputStream fos
= new FileOutputStream ( "myByteStream\\java.txt" ) ; fos
. write ( 97 ) ; fos
. close ( ) ; }
}
1.3 字節流寫數據的3種方式
方法名說明 void write(int b) 將指定的字節寫入此文件輸出流 一次寫一個字節數據 void write(byte[] b) 將b.length字節從指定的字節數組寫入此文件輸出流 一次寫一個字節數組數據 void write(byte[] b, int off, int len) 將Ien字節從指定的字節數組開始,從偏移量off開始寫入此文件輸出流 一次寫一個字節數組的部分數據
package demo_01 ;
import java. io. File ;
import java. io. FileOutputStream ;
import java. io. IOException ; public class FileOutputStreamDemo02 { public static void main ( String [ ] args
) throws IOException { FileOutputStream fos
= new FileOutputStream ( "myByteStream\\java.txt" , true ) ;
fos
. write ( 97 ) ; fos
. write ( 98 ) ; byte [ ] bys
= { 97 , 98 , 99 } ; fos
. write ( bys
) ; byte [ ] bys1
= { 97 , 98 , 99 } ; int len
= bys1
. length
; fos
. write ( bys1
, 0 , len
) ; fos
. close ( ) ; }
}
byte [ ] getBytes ( ) : 使用平臺的默認字符集將此
String 編碼為字節序列(返回字符串對應的字節數組)
1.4 字節流寫數據的兩個小問題
字節流寫數據如何實現換行呢?
windows: \r\n linux: \n mac: \r
字節流寫數據如何實現追加寫入呢?
public FileOutputStream(String name, boolean append) 創建文件輸出流以指定的名稱寫入文件。如果第二個參數為true,則字節將寫入文件的未尾而不是開頭
package demo_01 ; import java. io. FileOutputStream ;
import java. io. IOException ; public class FileOutputStreamDemo03 { public static void main ( String [ ] args
) throws IOException {
FileOutputStream fos
= new FileOutputStream ( "myByteStream\\java.txt" , true ) ; for ( int i
= 0 ; i
< 10 ; i
++ ) { fos
. write ( "hello" . getBytes ( ) ) ; fos
. write ( "\r\n" . getBytes ( ) ) ; } fos
. close ( ) ; }
}
1.5 字節流寫數據加異常處理
finally:在異常處理時提供finally塊來執行所有清除操作。比如說IO流中的釋放資源 特點:被finally控制的語句一定會執行,除非JVM退出
try {
} catch ( 異常類名 變量名
) {
} finally {
}
package demo_01 ; import java. io. FileOutputStream ;
import java. io. IOException ; public class FileOutputStreamDemo04 { public static void main ( String [ ] args
) { FileOutputStream fos
= null ; try { fos
= new FileOutputStream ( "myByteStream\\java.txt" ) ; fos
. write ( "hello" . getBytes ( ) ) ; } catch ( IOException e
) { e
. printStackTrace ( ) ; } finally { if ( fos
!= null ) { try { fos
. close ( ) ; } catch ( IOException e
) { e
. printStackTrace ( ) ; } } } }
}
1.6 字節流讀數據(一次讀一個字節數據)
需求:把文件java.txt中的內容讀取出來在控制臺輸出
FilelnputStream:從文件系統中的文件獲取輸入字節
FilelnputStream(String name):通過打開與實際文件的連接來創建一個FilelnputStream,該文件由文件系統中的路徑名name命名
使用字節輸入流讀數據的步驟: ①創建字節輸入流對象 ②調用字節輸入流對象的讀數據方法 ③釋放資源
package demo_02 ; import java. io. FileInputStream ;
import java. io. IOException ; public class FileInputStreamDemo01 { public static void main ( String [ ] args
) throws IOException { FileInputStream fis
= new FileInputStream ( "myByteStream\\java.txt" ) ; int by
; while ( ( by
= fis
. read ( ) ) != - 1 ) { System . out
. print ( ( char ) by
) ; } fis
. close ( ) ; }
}
案例:復制文本文件
需求:把“D:\\.File\\java.txt”復制到模塊目錄下的“java.txt”
分析:
①復制文本文件,其實就把文本文件的內容從一個文件中讀取出來(數據源),然后寫入到另一個文件中(目的地)
②數據源: D:\\.File\\java.txt—讀數據—InputStream—FilelnputStream
③目的地: myByteStream\\java.txt—寫數據—OutputStream–FileOutputStream
思路:
①根據數據源創建字節輸入流對象 ②根據目的地創建字節輸出流對象 ③讀寫數據,復制文本文件(一次讀取一個字節,一次寫入一個字節) ④釋放資源
package demo_02 ; import java. io. FileInputStream ;
import java. io. FileOutputStream ;
import java. io. IOException ;
public class CopyTxtDemo { public static void main ( String [ ] args
) throws IOException { FileInputStream fis
= new FileInputStream ( "D:\\File\\java.txt" ) ; FileOutputStream fos
= new FileOutputStream ( "myByteStream\\java.txt" ) ; int by
; while ( ( by
= fis
. read ( ) ) != - 1 ) { fos
. write ( by
) ; } fis
. close ( ) ; fos
. close ( ) ; }
}
1.7 字節流讀數據(一次讀一個字節數組數據)
需求:把文件java.txt中的內容讀取出來在控制臺輸出
使用字節輸入流讀數據的步驟:
創建字節輸入流對象 調用字節輸入流對象的讀數據方法 釋放資源
package demo_02 ; import java. io. FileInputStream ;
import java. io. IOException ; public class FileInputStreamDemo02 { public static void main ( String [ ] args
) throws IOException { FileInputStream fis
= new FileInputStream ( "myByteStream\\java.txt" ) ; byte [ ] bys
= new byte [ 1024 ] ; int len
; while ( ( len
= fis
. read ( bys
) ) != - 1 ) { System . out
. println ( new String ( bys
, 0 , len
) ) ; System . out
. println ( ) ; } fis
. close ( ) ; }
}
String ( byte [ ] bytes
, int offset
, int length
) 通過使用平臺的默認字符集解碼指定的字節子陣列來構造新的
String ( String 的構造方法
)
案例:復制圖片
需求:把“D:\\File\\mn.jpg”復制到模塊目錄下的“mn.jpg”
思路: ①根據數據源創建字節輸入流對像 ②根據目的地創建字節輸出流對象 ③讀寫數據,復制圖片(一次讀取一個字節數組,一次寫入一個字節數組) ④釋放資源
package demo_02 ; import java. io. FileInputStream ;
import java. io. FileOutputStream ;
import java. io. IOException ; public class CopyImgDome { public static void main ( String [ ] args
) throws IOException { FileInputStream fis
= new FileInputStream ( "D:\\File\\mn.jpg" ) ; FileOutputStream fos
= new FileOutputStream ( "myByteStream\\mn.jpg" ) ; byte [ ] bys
= new byte [ 1024 ] ; int len
; while ( ( len
= fis
. read ( ) ) != - 1 ) { fos
. write ( bys
, 0 , len
) ; } fis
. close ( ) ; fos
. close ( ) ; }
}
1.8 字節緩沖流
字節緩沖流:
BufferOutputStream:該類實現緩沖輸出流。通過設置這樣的輸出流,應用程序可以向底層輸出流寫入字節,而不必為寫入的每個字節導致底層系統的調用 BufferedInputStream:創建BufferedInputStream將創建一個內部緩沖區數組。當從流中讀取或跳過字節時,內部緩沖區將根據需要從所包含的輸入流中重新填充,一次很多字節
構造方法:
字節緩沖輸出流:BufferedOutputStream(OutputStream out) 字節緩沖輸入流:BufferedInputStream(InputStream in)
為什么構造方法需要的是字節流,而不是具體的文件或者路徑呢?
字節緩沖流僅僅提供緩沖區 ,而真正的讀寫數據還得依靠基本的字節流對象進行操作
package demo_03 ; import java. io. * ; public class BufferStreamDemo { public static void main ( String [ ] args
) throws IOException { BufferedInputStream bis
= new BufferedInputStream ( new FileInputStream ( "myByteStream\\java.txt" ) ) ; int by
; while ( ( by
= bis
. read ( ) ) != - 1 ) { System . out
. print ( ( char ) by
) ; } bis
. close ( ) ; }
}
案例:復制視頻
需求:把"D:\\File\\mv.avi"復制到模塊目錄下的"mv.avi”
思路: ①根據數據源創建字節輸入流對像 ②根據目的地創建字節輸出流對象 ③讀寫數據,復制視頻 ④釋放資源
package demo_03 ; import java. io. * ; public class CopyAviDemo { public static void main ( String [ ] args
) throws IOException { long startTime
= System . currentTimeMillis ( ) ;
method4 ( ) ; long endTime
= System . currentTimeMillis ( ) ; System . out
. println ( "共耗時:" + ( endTime
- startTime
) + "毫秒" ) ; } public static void method1 ( ) throws IOException { FileInputStream fis
= new FileInputStream ( "D:\\File\\mv.avi" ) ; FileOutputStream fos
= new FileOutputStream ( "myByteStream\\mv.avi" ) ; int by
; while ( ( by
= fis
. read ( ) ) != - 1 ) { fos
. write ( by
) ; } fis
. close ( ) ; fos
. close ( ) ; } public static void method2 ( ) throws IOException { FileInputStream fis
= new FileInputStream ( "D:\\File\\mv.avi" ) ; FileOutputStream fos
= new FileOutputStream ( "myByteStream\\mv.avi" ) ; byte [ ] bys
= new byte [ 1024 ] ; int len
; while ( ( len
= fis
. read ( bys
) ) != - 1 ) { fos
. write ( bys
, 0 , len
) ; } fis
. close ( ) ; fos
. close ( ) ; } public static void method3 ( ) throws IOException { BufferedInputStream bis
= new BufferedInputStream ( new FileInputStream ( "D:\\File\\mv.avi" ) ) ; BufferedOutputStream bos
= new BufferedOutputStream ( new FileOutputStream ( "myByteStream\\mv.avi" ) ) ; int by
; while ( ( by
= bis
. read ( ) ) != - 1 ) { bos
. write ( by
) ; } bis
. close ( ) ; bos
. close ( ) ; } public static void method4 ( ) throws IOException { BufferedInputStream bis
= new BufferedInputStream ( new FileInputStream ( "D:\\File\\mv.avi" ) ) ; BufferedOutputStream bos
= new BufferedOutputStream ( new FileOutputStream ( "myByteStream\\mv.avi" ) ) ; byte [ ] bys
= new byte [ 1024 ] ; int len
; while ( ( len
= bis
. read ( bys
) ) != - 1 ) { bos
. write ( bys
, 0 , len
) ; } bis
. close ( ) ; bos
. close ( ) ; }
}
2.字符流
2.1 為什么會出現字符流
由于字節流操作中文不是特別的方便,所以小ava就提供字符流
用字節流復制文本文件時,文本文件也會有中文,但是沒有問題,原因是最終底層操作會自動進行字節拼接成 中文,如何識別是中文的呢?
漢字在存儲的時候,無論選擇哪種編碼存儲,第一個字節都是負數 UTF-8編碼,一個漢字占用3個字節 GBK編碼,一個漢字占用2個字節
package demo_01 ; import java. io. IOException ;
import java. util. Arrays ; public class FileInputStreamDemo { public static void main ( String [ ] args
) throws IOException {
String s
= "中國" ; byte [ ] bys
= s
. getBytes ( "UTF-8" ) ;
System . out
. println ( Arrays . toString ( bys
) ) ; }
}
[ - 28 , - 72 , - 83 , - 27 , - 101 , - 67 ]
2.2 編碼表
基礎知識:
計算機中儲存的信息都是用二進制數表示的:我們在屏幕上看到的英文、漢字等字符是二進制數轉換之后 的結果
按照某種規則,將字符存儲到計算機中,稱為編碼。反之,將存儲在計算機中的二進制數按照某種規則解 析顯示出來,稱為解碼。這里強調一下:按照A編碼存儲,必須按照A編碼解析,這樣才能顯示正確的文本 符號。否則就會導致亂碼現象
字符編碼:就是一套自然語言的字符與二進制數之間的對應規則(A , 65)
字符集:
是一個系統支持的所有字符的集合,包括各國家文字、標點符號、圖形符號、數字等 計算機要準確的存儲和識別各種字符集符號,就需要進行字符編碼,一套字符集必然至少有一套字符編碼。 常見字符集有ASCII字符集、GBXXX字符集、Unicode:字符集等
1. ASCII字符集:
ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼):是基于拉丁字母的一套電腦編碼系統,用于顯示現代英語,主要包括控制字符(回車鍵、退格、換行鍵等)和可顯示字符英文大小寫字符、阿拉伯數字和西文符號) 基本的ASCII字符集,使用7位表示一個字符,共128字符。ASC的擴展字符集使用8位表示一個字符,共26字符,方便支持歐洲常用字符。是一個系統支持的所有字符的集合,包括各國家文字、標點符號、圖形符號,數字等
2. GBXXX:字符集:
GB2312:簡體中文碼表。一個小于127的字符的意義與原來相同,但兩個大于127的字符連在一起時,就表示一個漢字,這樣大約可以組合了包含7000多個簡體漢字,此外數學符號、羅馬希臘的字母、日文的假名等都編進去了,連在ASC里本來就有的數字、標點、字母都統統重新編了兩個字節長的編碼,這就是常說的“全角“字符,而原來在127號以下的那些就叫"半角“字符了 GBK:最常用的中文碼表。是在GB2312標準基礎上的擴展規范,使用了雙字節編碼方案,共收錄了21003個漢字,完全兼容GB2312標準,同時支持繁體漢字以及日韓漢字等 GB18030:最新的中文碼表。收錄漢字70244個,采用多字節編碼,每個字可以由1個、2個或4個字節組成。支持中國國內少數民族的文字,同時支持繁體漢字以及日韓漢字等
3. Unicode字符集:
為表達任意語言的任意字符而設計,是業界的一種標準,也稱為統一碼、標準萬國碼。它最多使用4個字節的數字來表達每個字母、符號,或者文字。有三種編碼方案,UTF-8、UTF-16和UTF32。最為常用的UTF-8編碼 UTF-8編碼:可以用來表示Jnicode標準中任意字符,它是電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼?;ヂ摼W工程工作小組(ETF)要求所有互聯網協議都必須支持UTF-8編碼。它使用一至四個字節為每個字符編碼
編碼規則:
128個US-ASCI字符,只需一個字節編碼 拉丁文等字符,需要二個字節編碼 大部分常用字(含中文),使用三個字節編碼 其他極少使用的Unicode?輔助字符,使用四字節編碼
小結:采用何種規則編碼,就要采用對應規則解碼,否則就會出現亂碼
2.3 字符串中的編碼解碼問題
編碼:
byte[] getBytes():使用平臺的默認字符集將該String編碼為一系列字節,將結果存儲到新的字節數組中 byte[] getBytes(String charsetName)):使用指定的字符集將該String編碼為一系列字節,將結果存儲 到新的字節數組中
解碼:
String(byte[] bytes):通過使用平臺的默認字符集解碼指定的字節數組來構造新的String String(byte[]bytes,String charsetName):通過指定的字符集解碼指定的字節數組來構造新的String
package demo_01 ;
import java. io. IOException ;
import java. util. Arrays ; public class StringDemo { public static void main ( String [ ] args
) throws IOException { String s
= "中國" ;
byte [ ] bys
= s
. getBytes ( "GBK" ) ; System . out
. println ( Arrays . toString ( bys
) ) ;
String ss
= new String ( bys
, "GBK" ) ; System . out
. println ( ss
) ; }
}
2.4 字符流中編碼解碼問題
InputStreamReader:是從字節流到字符流的橋梁:它讀取字節,并使用指定的charset將其解碼為字符, 它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集。
構造方法:
InputStreamReader(InputStream in) 創建一個使用默認字符集的InputStreamReader InputStreamReader(InputStream in, String charsetName) 創建一個使用命名字符集的InputStreamReader
OutputStreamWriter:是字符的橋梁流以字節流:向其寫入的字符編碼成使用指定的字節。 它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺的默認字符集 。
構造方法:
OutputStreamWriter(OutputStream out) 創建一個使用默認字符編碼的OutputStreamWriter OutputStreamWriter(OutputStream out, String charsetName) 創建一個使用命名字符集的OutputStreamWriter
package demo_01 ; import java. io. * ; public class StreamReadAndWriterDemo { public static void main ( String [ ] args
) throws IOException {
OutputStreamWriter osw
= new OutputStreamWriter ( new FileOutputStream ( "myCharStream\\java.txt" ) , "UTF-8" ) ; osw
. write ( "中國" ) ; osw
. close ( ) ;
InputStreamReader isw
= new InputStreamReader ( new FileInputStream ( "myCharStream\\java.txt" ) , "UTF-8" ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= isw
. read ( chs
) ) != - 1 ) { System . out
. println ( new String ( chs
, 0 , len
) ) ; } isw
. close ( ) ; }
}
2.5 字符流寫數據的5種方式
方法名說明 void write(int c) 寫一個字符 void write(char[] cbuf) 寫入一個字符數組 void write(char[]cbuf, int off, int len) 寫入字符數組的一部分 void write(String str) 寫一個字符串 void write(String str, int off, int len) 寫一個字符串的一部分
方法名說明 fiush() 刷新流,還可以繼續寫數據 close() 關閉流,釋放資源,但是在關閉之前會先刷新流。一旦關閉,就不能再寫數據
package demo_01 ; import java. io. FileOutputStream ;
import java. io. IOException ;
import java. io. OutputStreamWriter ; public class WriterMethod5Demo { public static void main ( String [ ] args
) throws IOException { OutputStreamWriter osw
= new OutputStreamWriter ( new FileOutputStream ( "myCharStream\\java.txt" ) ) ; String s
= "abcd" ; osw
. write ( s
, 1 , s
. length ( ) - 1 ) ; osw
. flush ( ) ; osw
. close ( ) ; }
}
2.6 字符讀取數據的2種方式
方法名說明 int rea() 一次讀一個字符數據 int read(char[] cbuf) 一次讀一個字符數組數據
package demo_01 ; import java. io. * ; public class StreamReadAndWriterDemo { public static void main ( String [ ] args
) throws IOException {
InputStreamReader isw
= new InputStreamReader ( new FileInputStream ( "myCharStream\\java.txt" ) , "UTF-8" ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= isw
. read ( chs
) ) != - 1 ) { System . out
. println ( new String ( chs
, 0 , len
) ) ; } isw
. close ( ) ; }
}
案例:復制Java文件
需求:把模塊目錄下的“Java.txt”復制到模塊目錄下的“Copy.txt"
思路: ①根據數據源創建字符輸入流對象 ②根據目的地創建字符輸出流對象 ③讀寫數據,復制文件 ④釋放資源
package demo_02 ; import java. io. * ; public class CopyJavaDemo { public static void main ( String [ ] args
) throws IOException { InputStreamReader isr
= new InputStreamReader ( new FileInputStream ( "myCharStream\\java.txt" ) ) ; OutputStreamWriter osw
= new OutputStreamWriter ( new FileOutputStream ( "myCharStream\\copy.txt" ) ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= isr
. read ( chs
) ) != - 1 ) { osw
. write ( chs
, 0 , len
) ; } isr
. close ( ) ; osw
. close ( ) ; }
}
案例:復制Java文件(改進版)
需求:把模塊目錄下的“java.txt”復制到模塊目錄下的"Copy.txt’
分析: ①轉換流的名字比較長,而我們常見的操作都是按照本地默認編碼實現的,所以,為了簡化書寫,轉換流提供了對應的子類 ②FileReader:用于讀取字符文件的便捷類 FileReader(String fileName) ③FileWriter:用于寫入字符文件的便捷類 FileWriter(String fileName) ④數據源和目的地的分析 數據源:myCharStream\java.txt—讀數據—Reader—InputStreamReader—FileReader 目的地:myCharStream\copy.txt—寫數據—Writer—OutputStreamWriter—FileWriter
思路: ①根據數據源創建字符輸入流對像 ②根據目的地創建字符輸出流對象 ③讀寫數據,復制文件 ④釋放資源
package demo_02 ; import java. io. FileReader ;
import java. io. FileWriter ;
import java. io. IOException ; public class CopyJavaDemo02 { public static void main ( String [ ] args
) throws IOException { FileReader fr
= new FileReader ( "myCharStream\\java.txt" ) ; FileWriter fw
= new FileWriter ( "myCharStream\\copy.txt" ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= fr
. read ( chs
) ) != - 1 ) { fw
. write ( chs
, 0 , len
) ; } fr
. close ( ) ; fw
. close ( ) ; }
}
2.7 字符緩沖流
字符緩沖流:
BufferedWriter:將文本寫入字符輸出流,緩沖字符,以提供單個字符,數組和字符串的高效寫入,可以指定緩沖區大小,或者可以接受默認大小。默認值足夠大,可用于大多數用途 BufferedReader:從字符輸入流讀取文本,緩沖字符,以提供字符,數組和行的高效讀取,可以指定緩沖區大小,或者可以使用默認大小。默認值足夠大,可用于大多數用途
構造方法:
BufferedWriter(Writer out) BufferedReader(Reader in)
package demo_03 ; import java. io. * ; public class BufferedStreamDemo { public static void main ( String [ ] args
) throws IOException { BufferedWriter bw
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; bw
. write ( "hello\r\n" ) ; bw
. write ( "world\r\n" ) ; bw
. close ( ) ; BufferedReader br
= new BufferedReader ( new FileReader ( "myCharStream\\java.txt" ) ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= br
. read ( chs
) ) != - 1 ) { System . out
. print ( new String ( chs
, 0 , len
) ) ; } br
. close ( ) ; }
}
案例:復制java文件(字符緩沖流改進版)
需求:把模塊目錄下的“java.txt”復制到模塊目錄下的"copy.txt’
思路: ①根據數據源創建字符緩沖輸入流對象 ②根據目的地創建字符緩沖輸出流對象 ③讀寫數據,復制文件 ④釋放資源
package demo_03 ; import java. io. * ; public class BufferedStreamDemo02 { public static void main ( String [ ] args
) throws IOException { BufferedReader br
= new BufferedReader ( new FileReader ( "myCharStream\\java.txt" ) ) ; BufferedWriter bw
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; char [ ] chs
= new char [ 1024 ] ; int len
; while ( ( len
= br
. read ( chs
) ) != - 1 ) { bw
. write ( chs
, 0 , len
) ; } br
. close ( ) ; bw
. close ( ) ; }
}
2.8 字節緩沖流特有功能
BufferedWriter:
void newLine() :寫一行行分隔符,行分隔符字符串由系統屬性定義
BufferedReader:
public String readLine() :讀一行文字。結果包含行的內容的字符串,不包括任何行終止字符,如果流的結尾已經到達,則為null
package demo_03 ; import java. io. * ; public class NewMethodBufferdeDemo { public static void main ( String [ ] args
) throws IOException { BufferedWriter bw
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; for ( int i
= 0 ; i
< 10 ; i
++ ) { bw
. write ( "hello" + i
) ;
bw
. newLine ( ) ; bw
. flush ( ) ; }
FileReader fr
= new FileReader ( "myCharStream\\java.txt" ) ; BufferedReader br
= new BufferedReader ( fr
) ; String line
; while ( ( line
= br
. readLine ( ) ) != null ) { System . out
. println ( line
) ; } br
. close ( ) ; bw
. close ( ) ; }
}
案例:復制Java文件(字符緩沖流特有功能改進版)
需求:把模塊目錄下的“java.txt”復制到模塊目錄下的"copy.txt’
思路: ①根據數據源創建字符緩沖輸入流對象 ②根據目的地創建字符緩沖輸出流對象 ③讀寫數據,復制文件 使用字符緩沖流特有功能實現 ④釋放資源
package demo_03 ; import java. io. * ; public class CopyJavaNewMethodDemo { public static void main ( String [ ] args
) throws IOException { BufferedReader bis
= new BufferedReader ( new FileReader ( "myCharStream\\java.txt" ) ) ; BufferedWriter bos
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; String len
; while ( ( len
= bis
. readLine ( ) ) != null ) { bos
. write ( len
) ; bos
. newLine ( ) ; bos
. flush ( ) ; } bis
. close ( ) ; bos
. close ( ) ; }
}
2.9 IO流小結
案例:集合到文件
需求:把ArrayList:集合中的字符串數據寫入到本文件。
要求:每一個字符串元素作為文件中的一行數據
思路: ①創建ArrayList集合 ②往集合中存儲字符串元素 ③創建字符緩沖輸出流對象 ④遍歷集合,得到每一個字符串數據 ⑤調用字符緩沖輸出流對象的方法寫數據 ⑥釋放資源
package demo_04 ; import java. io. BufferedWriter ;
import java. io. FileWriter ;
import java. io. IOException ;
import java. util. ArrayList ; public class ArrayListToTxtDemo { public static void main ( String [ ] args
) throws IOException { ArrayList < String > array
= new ArrayList < String > ( ) ; array
. add ( "hello" ) ; array
. add ( "java" ) ; array
. add ( "world" ) ; BufferedWriter bw
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; for ( String s
: array
) { bw
. write ( s
) ; bw
. newLine ( ) ; bw
. flush ( ) ; } bw
. close ( ) ; }
}
案例:點名器
需求:我有一個文件里面存儲了班級同學的姓名,每一個姓名占一行,要求通過程序實現隨機點名器
思路: ①創建字符緩沖輸入流對象 ②創建ArrayList集合對象 ③調用字符緩沖輸入流對象的方法讀數據 ④把讀取到的字符串數據存儲到集合中 ⑤釋放資源 ⑥使用Random產生一個隨機數,隨機數的范圍在:[O,集合的長度) ⑦把第6步產生的隨機數作為索引到ArrayList集合中獲取值 ⑧把第7步得到的數據輸出在控制臺
package demo_04 ; import java. io. BufferedReader ;
import java. io. FileReader ;
import java. io. IOException ;
import java. util. ArrayList ;
import java. util. Random ; public class CallNameDemo { public static void main ( String [ ] args
) throws IOException { BufferedReader br
= new BufferedReader ( new FileReader ( "myCharStream\\java.txt" ) ) ; ArrayList < String > array
= new ArrayList < String > ( ) ; String line
; while ( ( line
= br
. readLine ( ) ) != null ) { array
. add ( line
) ; } br
. close ( ) ; Random name
= new Random ( ) ; int index
= name
. nextInt ( array
. size ( ) ) ; String s1
= array
. get ( index
) ; System . out
. println ( s1
) ; }
}
案例:集合到文件(改進版)
需求:把ArrayList集合中的學生數據寫入到文本文件。
要求:每一個學生對象的數據作為文件中的一行數據
格式:學號姓名,年齡,居住地 舉例:001,張三,18,鄭州
思路: ①定義學生類 ②創建ArrayList集合 ③創建學生對象 ④把學生對象添加到集合中 ⑤創建字符緩沖輸出流對象 ⑥遍歷集合,得到每一個學生對象 ⑦把學生對象的數據拼接成指定格式的字符串 ⑧調用字符緩沖輸出流對像的方法寫數據 ⑨釋放資源
package demo_05 ; public class Student { private String sid
; private String name
; private int age
; private String address
; public Student ( ) { } public Student ( String name
, String sid
, int age
, String address
) { this . sid
= sid
; this . name
= name
; this . age
= age
; this . address
= address
; } public String getName ( ) { return name
; } public void setName ( String name
) { this . name
= name
; } public String getSid ( ) { return sid
; } public void setSid ( String sid
) { this . sid
= sid
; } public int getAge ( ) { return age
; } public void setAge ( int age
) { this . age
= age
; } public String getAddress ( ) { return address
; } public void setAddress ( String address
) { this . address
= address
; }
}
package demo_05 ; import java. io. BufferedWriter ;
import java. io. FileWriter ;
import java. io. IOException ;
import java. util. ArrayList ; public class ArrayListToFileDemo { public static void main ( String [ ] args
) throws IOException { ArrayList < Student > array
= new ArrayList < Student > ( ) ; Student s1
= new Student ( "001" , "張三" , 18 , "鄭州" ) ; Student s2
= new Student ( "002" , "李四" , 20 , "廣州" ) ; Student s3
= new Student ( "003" , "王五" , 19 , "深圳" ) ; array
. add ( s1
) ; array
. add ( s2
) ; array
. add ( s3
) ; BufferedWriter br
= new BufferedWriter ( new FileWriter ( "myCharStream\\java.txt" ) ) ; for ( Student s
: array
) { StringBuilder sb
= new StringBuilder ( ) ; sb
. append ( s
. getSid ( ) ) . append ( "," ) . append ( s
. getName ( ) ) . append ( "," ) . append ( s
. getAge ( ) ) . append ( "," ) . append ( s
. getAddress ( ) ) ; br
. write ( sb
. toString ( ) ) ; br
. newLine ( ) ; br
. flush ( ) ; } br
. close ( ) ; }
}
案例:文件到集合(改進版)
需求:把文本文件中的數據讀取到集合中,并遍歷集合。
要求:文件中每一行數據是一個學生對象的成員變量值
舉例:001,張三,18,鄭州
思路: ①定義學生類 ②創建字符緩沖輸入流對象 ③創建ArrayList集合對象 ④調用字符緩沖輸入流對象的方法讀數據 ⑤把讀取到的字符串數據用split()進行分割,得到一個字符串數組 ⑥創建學生對象 ⑦把字符串數組中的每一個元素取出來對應的賦值給學生對像的成員變量值 ⑧把學生對象添加到集合 ⑨釋放資源
package demo_05 ; import java. io. BufferedReader ;
import java. io. FileReader ;
import java. io. IOException ;
import java. util. ArrayList ; public class FileToArrayListDemo { public static void main ( String [ ] args
) throws IOException { BufferedReader br
= new BufferedReader ( new FileReader ( "myCharStream\\java.txt" ) ) ; ArrayList < Student > array
= new ArrayList < Student > ( ) ; String line
; while ( ( line
= br
. readLine ( ) ) != null ) { String [ ] strArray
= line
. split ( "," ) ; Student s
= new Student ( ) ; s
. setSid ( strArray
[ 0 ] ) ; s
. setName ( strArray
[ 1 ] ) ; s
. setAge ( Integer . parseInt ( strArray
[ 2 ] ) ) ; s
. setAddress ( strArray
[ 3 ] ) ; array
. add ( s
) ; } br
. close ( ) ; for ( Student s1
: array
) { System . out
. println ( s1
. getSid ( ) + "," + s1
. getName ( ) + ", " + s1
. getAge ( ) + ", " + s1
. getAddress ( ) ) ; } }
}
案例:集合到文件(數據排序改進版)
需求:鍵盤錄入5個學生信息(姓名,語文成績,數學成績,英語成績)。要求按照成績總分從高到低寫入文本文件
格式:姓名,語文成績數學成績英語成績 舉例:張三,98,99,100
思路: ①定義學生類 ②創建TreeSet集合,通過比較器排序進行排序 ③鍵盤錄入學生數據 ④創建學生對象,把鍵盤錄入的數據對應賦值給學生對象的成員變量 ⑤把學生對象添加到TreeSet集臺 ⑥創建字符緩沖輸出流對象 ⑦遍歷集合,得到每一個學生對象 ⑧把學生對象的數據拼接成指定格式的字符串 ⑨調用字符緩沖輸出流對像的方法寫數據 ⑩釋放資源
package demo_06 ; public class Student { private String name
; private int chinese
; private int math
; private int english
; public Student ( ) { } public Student ( String name
, int chinese
, int math
, int english
) { this . name
= name
; this . chinese
= chinese
; this . math
= math
; this . english
= english
; } public String getName ( ) { return name
; } public void setName ( String name
) { this . name
= name
; } public int getChinese ( ) { return chinese
; } public void setChinese ( int chinese
) { this . chinese
= chinese
; } public int getMath ( ) { return math
; } public void setMath ( int math
) { this . math
= math
; } public int getEnglish ( ) { return english
; } public void setEnglish ( int english
) { this . english
= english
; } public int sum ( ) { return chinese
+ math
+ english
; }
}
package demo_06 ; import java. io. BufferedWriter ;
import java. io. FileWriter ;
import java. io. IOException ;
import java. util. Comparator ;
import java. util. Scanner ;
import java. util. TreeSet ; public class TreeSetFileDemo { public static void main ( String [ ] args
) throws IOException { TreeSet < Student > ts
= new TreeSet < Student > ( new Comparator < Student > ( ) { @Override public int compare ( Student s1
, Student s2
) { int num
= s2
. sum ( ) - s1
. sum ( ) ; int num2
= num
== 0 ? s2
. getChinese ( ) - s1
. getChinese ( ) : num
; int num3
= num2
== 0 ? s2
. getMath ( ) - s1
. getMath ( ) : num2
; int num4
= num3
== 0 ? s2
. getName ( ) . compareTo ( s1
. getName ( ) ) : num3
; return num4
; } } ) ; for ( int i
= 0 ; i
< 5 ; i
++ ) { Scanner sc
= new Scanner ( System . in
) ; System . out
. println ( "請輸入姓名:" ) ; String name
= sc
. nextLine ( ) ; System . out
. println ( "請輸入語文成績:" ) ; int chinese
= sc
. nextInt ( ) ; System . out
. println ( "請輸入數學成績:" ) ; int math
= sc
. nextInt ( ) ; System . out
. println ( "請輸入英語成績:" ) ; int english
= sc
. nextInt ( ) ; Student s
= new Student ( ) ; s
. setName ( name
) ; s
. setChinese ( chinese
) ; s
. setMath ( math
) ; s
. setEnglish ( english
) ; ts
. add ( s
) ; } BufferedWriter br
= new BufferedWriter ( new FileWriter ( "myCharStream\\copy.txt" ) ) ; for ( Student s1
: ts
) { StringBuilder sb
= new StringBuilder ( ) ; sb
. append ( s1
. getName ( ) ) . append ( "," ) . append ( s1
. getChinese ( ) ) . append ( ", " ) . append ( s1
. getMath ( ) ) . append ( ", " ) . append ( s1
. getEnglish ( ) ) . append ( ", " ) . append ( s1
. sum ( ) ) ; br
. write ( sb
. toString ( ) ) ; br
. newLine ( ) ; br
. flush ( ) ; } br
. close ( ) ; }
}
對象流(序列化流)
1. 對象輸出流(序列化)
對象輸出流說明 ObjectOutputStream(OutputStream out) 對象輸出流,把對象以字節的形式寫到本地文件 public void writeObject(Object obj) 寫一個對象到文件中
package com. itheima. demo10ObjectOutputStream 對象輸出流
; import java. io. Serializable ; public class Person implements Serializable { private static final long serialVersionUID
= 123456789 ; private String name
; private transient int age
; private String sex
;
}
public class Demo10 { public static void main ( String [ ] args
) throws IOException { ObjectOutputStream oos
= new ObjectOutputStream ( new FileOutputStream ( "day_11/files/person.bin" ) ) ; Person p
= new Person ( "張三" , 18 , "男" ) ; oos
. writeObject ( p
) ; oos
. close ( ) ; }
}
2. 對象輸出流(反序列化)
對象輸入流說明 ObjectInputStream(InputStream in) 對象輸入流,把寫到本地文件中的對像讀到內存中 public Object readObject() 讀取文件中的對象數據到文件中
public class Demo11 { public static void main ( String [ ] args
) throws IOException , ClassNotFoundException { ObjectInputStream ois
= new ObjectInputStream ( new FileInputStream ( "day_11/files/person.bin" ) ) ; Person o
= ( Person ) ois
. readObject ( ) ; System . out
. println ( o
) ; ois
. close ( ) ; }
}
注意細節:
使用對象輸出流將對象保存到文件時會出現NotSerializableException.異常。
解決辦法:需要讓類實現Serializable接口。 用對象序列化流序列化了一個對象后,假如我們修改了對象所屬的類結構,會拋出InvalidClassException異常?
給對象所屬的類加一個serialVersionUlD屬性 例如:private static final long serialVersionUlD=5645742L; 如果一個對象中的某個成員變量的值不想被序列化,又該如何實現呢?
給成員變量加transient:關鍵字,該成員變量就不會被序列化到文件中。
屬性集(Properties重點)
Properties作為集合的使用
Properties實現了Map接口,就是一個雙列集合可以存儲鍵值對數據, 鍵和值都是字符串 Properties可以結合流進行操作, 可以把集合中的數據保存到流中, 也可以從流中來加載數據
Properties作Map集合的特有方法:
方法名說明 Object setProperty(String key, String value) 添加鍵值對,修改鍵值對 String getProperty(String key) 通過鍵獲取值 Set stringPropertyNames() 獲取所有的鍵
public class Demo141 { public static void main ( String [ ] args
) { Properties pro
= new Properties ( ) ; pro
. setProperty ( "gz" , "廣州" ) ; pro
. setProperty ( "sh" , "上海" ) ; pro
. setProperty ( "sz" , "深圳" ) ; String value
= pro
. getProperty ( "gz" ) ; System . out
. println ( value
) ; String bj
= pro
. getProperty ( "bj" , "北京" ) ; System . out
. println ( bj
) ; Set < String > str
= pro
. stringPropertyNames ( ) ; System . out
. println ( str
) ; }
}
Properties和IO的結合方法:
方法名說明 void load(Reader reader) 使用字符輸入流加載鍵值對到Properties中(加載到屬性集) void store(Writer writer,String comments) 使用字符輸出流將Properties中的鍵值對保存到文件中(存儲到文件中) void load(InputStream inStream) 使用字節輸入流加載數據到Properties中 void store(OutputStream out,String comments) 使用字節輸出流將Propertiest中的數據保存到文件
package com. itheima. demo14Properties_ 重點
; import java. io. FileReader ;
import java. io. FileWriter ;
import java. io. IOException ;
import java. util. Properties ;
public class Demo142 { public static void main ( String [ ] args
) throws IOException {
testLoad ( ) ; } public static void testStore ( ) throws IOException { Properties ps
= new Properties ( ) ; ps
. setProperty ( "username" , "admin" ) ; ps
. setProperty ( "password" , "123456" ) ; FileWriter fw
= new FileWriter ( "day_11/files/config.properties" ) ; ps
. store ( fw
, "用戶名和密碼" ) ; fw
. close ( ) ; } public static void testLoad ( ) throws IOException { Properties pro
= new Properties ( ) ; FileReader fr
= new FileReader ( "day_11/files/config.properties" ) ; pro
. load ( fr
) ; System . out
. println ( pro
) ; fr
. close ( ) ; }
}
更多內容請訪問博主博客:逸樂的博客 - 今晚一起吃火鍋
文章如有紕漏請指出,整理不易多多包涵。
Java后續筆記將持續更新…
總結
以上是生活随笔 為你收集整理的Java笔记 - 黑马程序员_06(Stream,字节流,字符流,对象流(序列化流),属性集(Properties)) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。