(一)子節緩衝流
(1) 一次讀取一個字節數組的方式要比一次讀取一個字節方式高效.
一次讀取一個字節數組,相當於構造一個緩衝區,有沒有比一次讀取一個字節數組還要高效的流?
字節緩衝流 :
(2)字節緩衝輸出流:
構造方式:
(第一種開發中) public BufferedOutputStream(OutputStream out):採用的默認的緩衝區大小(足夠大了) ,來構造一個字節緩衝輸出流對象
public BufferedOutputStream(OutputStream out,int size):指定size緩衝區大小構造緩衝輸出流對象
IllegalArgumentException - 如果 size <= 0
寫數據的方式:
一次寫一個字節
write(int by)
一次寫一個字節數組的一部分
write(byte[] b, int off, int len)
(2)字節緩衝輸入流
- public BufferedInputStream(InputStream in):默認緩衝區大小構造緩衝輸入流對象
- public BufferedInputStream(InputStream in,int size):指定緩衝區大小構造緩衝輸入流對象
- public int read()
- public int read(byte[] b,int off,int len)
-
在使輸入流的時候,
兩種方式讀取(一次讀取一個字節/一次讀取一個字節數在),只能用一種方式,否則,會出現錯誤!
(3)計算機如何存儲中文的?
當前平臺默認編碼集 :GBK 一箇中文兩個字節
第一個字節:一定是負數
第二個字節:一般是負數,可能也會是正數,不會影響的結果.
(4)存儲文件
IO流:永久存儲(耗時)
數據庫:永久存儲
基本的字節流
文件字節輸入流/文件字節輸出流
高效的字節流(緩衝流)
StringBuffer:提供了一個字符串緩衝區 (可以在緩衝區中不斷追加字符串)
(5)編碼和解碼
編碼和解碼:前後的編碼格式要一致!
編碼:
- 簡單理解:將能看懂的東西--->看不懂的東西
- 解碼:
- 看不懂的東西---能看懂的東西
- 舉例: 諜戰片
今天老地方見... -
編碼:
今---->字節---->二進制數據 -
解碼:二進制數據-->十進制數據--->字節---->字符串
今編碼: 將字符串變成一個字節數組
- public byte[] getBytes() :平臺默認編碼集(默認的是Gbk)
- public byte[] getBytes(Charset charset) ;"指定編碼格式
-
解碼:將字節數組--->字符串
- public String(byte[] bytes) :使用平臺默認編碼集(gbk)
- public String(byte[] bytes,Charset charset):用指定的編碼格式來解碼
(二)字符流
(1)使用字節流一次讀取一個字節的方式,會造成中文亂碼--->Java提供了一個字符流(專門用來解決中文亂碼問題)
(2 字符輸入流:Reader
字符輸出流:Writer - 字符輸出流/字符輸入流:都是抽象類
- 使用一個子類:轉換流
字符輸出流的構造方法 - public OutputStreamWriter(OutputStream out):使用默認的編碼格式構造一個字符轉換輸出流對象
-
public OutputStreamWriter(OutputStream out, Charset cs):使用指定編碼格式構造一個字符轉換輸出流對象
轉換流的構成=字節流+編碼格式(平臺默認/指定)
轉換流的對象的創建,格式比較長,非常麻煩,Java--->轉換流的便捷類
Reader:抽象類:字符輸入流 - inputStreamReader(字符轉換輸入流 :inputStream+編碼格式)
-
便捷類:FileReader,這個類可以直接對文件進行操作
Writer:抽象類:字符輸出流
- outputStreamWriter(字符轉換輸出流:outputStream+編碼格式)
(3)字符轉換輸入流:InputStreamReader - InputStreamReader(InputStream in) :構造一個字符轉換輸入流,默認編碼
- public InputStreamReader(InputStream in,Charset cs) 構造一個字符轉換輸入流,指定編碼
字符轉換輸入流=字節流+編碼格式
(4字符輸入流讀數據的方法: - int read(char[] chs):讀取一個字符數組
- int read():讀取單個字符
(5)字符輸出流寫數據的功能: - public void write(int c):寫單個字符
- public void write(char[] cbuf):寫字符數組
- public abstract void write(char[] cbuf, int off, int len):寫字符數組的一部分
- public void write(String str):寫字符串
- public void write(String str,int off, int len):寫字符串的某一部分
-
*flush和close方法的區別?
- close:關閉該流,關閉該流對象以及它關聯 的資源文件,關閉之後,不能再對流對象進行操作了,否則會有異常
- flush:刷新該流,爲了防止一些文件(圖片文件/音頻文件),缺失,或者沒有加載到流對象中,刷新了該流,還是可以流對象進行操作
字符緩衝輸入流/字符緩衝輸出流
雜七雜八的流(properties:屬性集合類/合併流/序列化Serializable/內存操作流)
(三)字符緩衝流
在字符流中提供了一個更高效的流-->字符緩衝流 - 字符緩衝輸入流
- 字符緩衝輸出流
(1)BufferedReader:字符緩衝輸入流
構造方法 - public BufferedReader(Reader in)創建一個使用默認大小輸入緩衝區的緩衝字符輸入流。
- public BufferedReader(Reader in, int sz)創建一個使用指定大小輸入緩衝區的緩衝字符輸入流。
(2)BufferedWrier:文本寫入字符輸出流,緩衝各個字符,從而提供單個字符、數組和字符串的高效寫入
構造方法 - BufferedWriter(Writer out) :默認緩衝區大小構造字符緩衝輸出流對象
- BufferedWriter(Writer out,int size):指定緩衝區大小
(3)字符緩衝輸出流:
- 特有功能:public void newLine():寫入一個行的分隔符號
-
*字符緩衝輸入流:
- 特有功能:public String readLine():一次讀取一行
(4)使用字符緩衝流進行復制操作
分別使用兩種方式 - 1)一次讀取一個字符數組
- 2)一次讀取一行
(四)其他流
(1)內存操作流:適用於臨時存儲文件.
內存操作輸入流:byteArrayInputStream - ByteArrayInputStream(byte[] buf)
內存操作輸出流: byteArrayOutputStream
構造方法:ByteArrayOutputStream()
內存操作流:一個程序結束後,那麼這些程序的變量,就會從內存消失(馬上消失的這些數據進行讀取寫入)
(2)數據流:針對Java基本類型的數據進行讀寫操作
數據輸入流:DataInputStream
數據輸出流:DataOutputStream
(3)打印流
字符打印流(針對文本進行操作:PrintWriter)
字節打印流(printStream 和標準輸出流有關係 System.out;)
PrintWriter:屬於輸出流
1)只能寫數據(只能針對目的地文件進行操作),不能讀數據(不能針對源文件進行操作)
2)可以針對文件直接進行操作
如果一個類中的構造方法裏面有File對象或者String類型數據,這個類可以對文本文件直接操作 - FileInputStream
- FileOutputStream
- FileWriter
- FileReader..
- PrintWriter
- 3)自動刷新功能::PrintWriter(OutputStream out/Writer out,boolean autoflush);第二個參數如果是true 表示啓動自動刷新功能
- 4)打印的方法:print(XXX x)/println(XXX xx)
(4)合併流
SequenceInputStream 表示其他輸入流的邏輯串聯(合併流)
構造方法 - public SequenceInputStream(InputStream s1, InputStream s2)
- sequenceInputStream另一種構造方式
- public SequenceInputStream(Enumeration e)
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
/*
sequenceInputStream另一種構造方式
public SequenceInputStream(Enumeration e)
- 將多個輸入流對象進行合併
- a.txt+b.txt+c.txt--->d.txt
-
*/
public class SequenceInputStreamDemo2 {public static void main(String[] args) throws IOException {
//StringDemo.java+SystemInDemo.java+PrintWriterDemo.java--->Copy.java文件中//定義一個集合Vector Vector<InputStream> v = new Vector<InputStream>() ; //使用InputStream封裝文件 InputStream s1 = new FileInputStream("StringDemo.java") ; InputStream s2 = new FileInputStream("SystemInDemo.java") ; InputStream s3 = new FileInputStream("PrintWriterDemo.java") ; //將流對象添加到集合中 v.add(s1) ; v.add(s2) ; v.add(s3) ; //特有功能 Enumeration<InputStream> en = v.elements() ; //創建合併輸入流對象 SequenceInputStream sis = new SequenceInputStream(en) ; //創建字節緩衝輸出流對象 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java")) ; //一次讀取一個字節數組 byte[] bys = new byte[1024] ; int len = 0 ; while((len=sis.read(bys))!=-1) { bos.write(bys, 0, len); bos.flush(); } //關閉資源 bos.close(); sis.close();
}
}
(5)標準的輸入輸出流 - InputStream in = System.in
- PrintStream out = Syste.out ;
-
*jdk5以後,Java--->Scanner(InputStream in)
- 鍵盤錄入
- 1)Scanner
- 2)BufferedReader裏面包裝字符轉換輸入流,包裝System.in
標準輸出流 -
PrintStream ps = System.out ;
使用BufferedWriter 去包裝System.out
(6)對象流
序列化:將對象按照流的方式存儲到文本文件中或者再網絡中傳輸 對象---->流數據 序列化流 (ObjectOutputStream)
反序列化:將文本文件中的流對象或者網絡傳輸中的流對象還原成對象 流數據--->對象 反序列化流(ObjectInputStream)
java.io.NotSerializableException :當前類未實現序列化功能的異常 - Serializable:接口 沒有構造方法,沒有字段,也沒有方法
-
接口---->標記接口
-
自定義類要實現序列化功能,必須實現接口Serializable接口
- 類實現了serializable也意味着他是標記類
- 假設之前操作針對Peroson操作序列的時候,產生一個標記 Preson.class--->固定ID 100
- name -100
- age -100
- 已經序列化完畢了,然後有修改了Person類裏面的一些東西,加入了toString()
- Person.class---固定id -- 200
-
(五)屬性集合類
(1)Properties:表示了一個持久的屬性集(簡稱:屬性集合類) extends Hashtable<K,V> Map集合的 - 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串。
- public Properties():無參構造
(2)屬性集合類的特有功能: - public Object setProperty(String key, String value) :給屬性列表中添加鍵和值,並且強制都使用String
- public Set<String> stringPropertyNames():遍歷的功能
- public String getProperty(String key)用指定的鍵在此屬性列表中搜索屬性
可保存在流中或從流中加載,只能使用屬性集合類
public void store(Writer writer,String comments):把集合中的數據保存文本文件中(屬性集合)
public void load(Reader reader):將文本文件中的數據加載到屬性集合中
(六)多線程
(1)何實現多線程程序呢?
要實現多線程程序,需要開啓進程,
開啓進程,是需要創建系統資源,但是Java語言不能創建系統資源
只有C/C++可以創建系統資源, 利用c語言創建好的系統資源實現
Java提供了一個類:Thread類 - 實現多線程程序的步驟:
- 1)將類聲明爲 Thread 的子類
- 2)該子類應重寫 Thread 類的 run 方法
- 3)在主線程進行該自定義的線程類的對象的創建
並行和併發(高併發:MyBatis --->IBatis:半自動化)
強者邏輯上的同時,指的是同一個時間段內
後者物理上的同時,指的是同一個時間點
MyThread類就是一個執行線程類
並且重寫Thread類中的run 方法
run()方法裏面應該是一些耗時的操作,IO操作/循環語句..
(2)Thread 類提供了一些方法 - public final void setName(String name):給線程起名稱
- public final String getName() :獲取線程名稱
(3)跟線程優先級相關的方法: - public final int getPriority()返回線程的優先級。
- public final void setPriority(int newPriority)更改線程的優先級
- 線程存在一個默認優先級
- public static final int MAX_PRIORITY 10 最大優先級
public static final int MIN_PRIORITY 1 最小優先級
public static final int NORM_PRIORITY 5 默認優先級
(4)public final void setDaemon(boolean on) :true時,表示爲守護線程 - 將該線程標記爲守護線程或用戶線程。當正在運行的線程都是守護線程時,Java 虛擬機退出。(守護線程不會立即結束掉,它會執行一段時間在結束掉)
- 該方法必須在啓動線程前調用。
(5)方法 - public final void join():等待該線程終止 interruputedException 中斷異常
- public static void sleep(long millis):線程睡眠 指定是時間毫秒值
- throws InterruptedException
- 兩個區別?
public final void stop() ;強迫線程停止執行。 不會執行了 (過時了),方法能使用的
public void interrupt()中斷線程。 表示中斷線程的一種狀態
面試題
區別?
wait(): wait()調用的,立即釋放鎖 (同步鎖/Lock鎖)
sleep(): 線程睡眠,調用不會釋放鎖 - public final void stop() ;強迫線程停止執行。 不會執行了 (過時了),方法能使用的
- public static void yield()暫停當前正在執行的線程對象,並執行其他線程