目錄
- 目錄
- 01轉換流概述
- 02轉換流_字符轉字節的過程
- 03OutputStreamWriter寫文本文件
- 04轉換流_字節轉字符流過程
- 05InputSteamReader讀取文本文件
- 06轉換流子類父類的區別
- 07緩衝流概述
- 08字節輸出流緩衝流BufferedOutputStream
- 09字節輸入流緩衝流BufferedInputStream
- 10四種文件複製方式的效率比較
- 11字符輸出流緩衝流BufferedWriter
- 12字符輸出流緩衝流BufferedWriter特有方法newLine
- 13字符輸入流緩衝流BufferedReader
- 14字符輸入流緩衝流BufferedReader讀取文本行
- 15字符流緩衝區流複製文本文件
- 16IO流對象的操作規律
- 01Properties集合的特點
- 02Properties集合存儲鍵值對
- 03Properties集合的方法load
- 04Properties集合的方法store
- 05對象的序列化與反序列化
- 06ObjectOutputStream流寫對象
- 07ObjectInputStream流讀取對象
- 08靜態不能序列化
- 09transient關鍵字
- 10Serializable接口的含義
- 11序列化中的序列號衝突問題
- 12序列化中自定義的序列號
- 14打印流輸出目的是File對象
- 15輸出語句是char數組
- 16打印流輸出目的是String和流對象
- 17打印流開啓自動刷新
- 18打印流複製文本文件
- 19commons-io工具類介紹
- 20使用工具類commons_io
- 21IO工具類FilenameUtils
- 22IO工具類FileUtils
- 01進程概念
- 02線程的概念
- 03深入線程的概念
- 04迅雷的多線程下載
- 05線程的運行模式
- 06main的主線程
- 07Thread類介紹
- 08實現線程程序繼承Thread
- 09線程執行的隨機性
- 10爲什麼要繼承Thread
- 11多線程內存圖解
- 12獲取線程名字Thread類方法getName
- 13獲取線程名字Thread類方法currentThread
- 14線程名字設置
- 15Thread類方法sleep
- 16實現線程的另一種方式實現Runnable接口
- 17實現接口方式的好處
- 18匿名內部類實現線程程序
- 19線程的狀態圖
- 20線程池的原理
- 21JDK5實現線程池
- 22實現線程的Callable接口方式
- 23線程實現異步計算
- 目錄
01轉換流概述
* A: 轉換流概述
* a: 轉換流概述
* OutputStreamWriter 是字符流通向字節流的橋樑:可使用指定的字符編碼表,將要寫入流中的字符編碼成字節
* 將字符串按照指定的編碼表轉成字節,在使用字節流將這些字節寫出去
02轉換流_字符轉字節的過程
* A: 轉換流_字符轉字節的過程
* a.圖解
* 詳見day24_source/轉換流.JPG圖片
03OutputStreamWriter寫文本文件
* A: OutputStreamWriter寫文本文件
* a: OutputStreamWriter
* java.io.OutputStreamWriter 繼承Writer類
* 就是一個字符輸出流,寫文本文件
* write()字符,字符數組,字符串
* 字符通向字節的橋樑,將字符流轉字節流
* OutputStreamWriter 使用方式
* 構造方法:
* OutputStreamWriter(OuputStream out)接收所有的字節輸出流
* 字節輸出流: FileOutputStream
* OutputStreamWriter(OutputStream out, String charsetName)
* String charsetName 傳遞編碼表名字 GBK UTF-8
* OutputStreamWriter 有個子類, FileWriter
* b: 案例代碼
public class OutputStreamWriterDemo {
public static void main(String[] args)throws IOException {
// writeGBK();
writeUTF();
}
/*
* 轉換流對象OutputStreamWriter寫文本
* 採用UTF-8編碼表寫入
*/
public static void writeUTF()throws IOException{
//創建字節輸出流,綁定文件
FileOutputStream fos = new FileOutputStream("c:\\utf.txt");
//創建轉換流對象,構造方法保證字節輸出流,並指定編碼表是UTF-8
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
osw.write("你好");
osw.close();
}
/*
* 轉換流對象 OutputStreamWriter寫文本
* 文本採用GBK的形式寫入
*/
public static void writeGBK()throws IOException{
//創建字節輸出流,綁定數據文件
FileOutputStream fos = new FileOutputStream("c:\\gbk.txt");
//創建轉換流對象,構造方法,綁定字節輸出流,使用GBK編碼表
OutputStreamWriter osw = new OutputStreamWriter(fos);
//轉換流寫數據
osw.write("你好");
osw.close();
}
}
04轉換流_字節轉字符流過程
* A: 轉換流_字節轉字符流過程
* a: InputStreamReader
* java.io.InputStreamReader 繼承 Reader
* 字符輸入流,讀取文本文件
* 字節流向字符的敲了,將字節流轉字符流
* 讀取的方法:
* read() 讀取1個字符,讀取字符數組
* 技巧
* OuputStreamWriter寫了文件
* InputStreamReader讀取文件
* OutputStreamWriter(OutputStream out)所有字節輸出流
* InputStreamReader(InputStream in) 接收所有的字節輸入流
* 可以傳遞的字節輸入流: FileInputStream
* InputStreamReader(InputStream in,String charsetName) 傳遞編碼表的名字
* b: 圖解
* 詳見day24_source/轉換流.JPG圖片
05InputSteamReader讀取文本文件
* A: InputSteamReader讀取文本文件
* a: 案例代碼
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
// readGBK();
readUTF();
}
/*
* 轉換流,InputSteamReader讀取文本
* 採用UTF-8編碼表,讀取文件utf
*/
public static void readUTF()throws IOException{
//創建自己輸入流,傳遞文本文件
FileInputStream fis = new FileInputStream("c:\\utf.txt");
//創建轉換流對象,構造方法中,包裝字節輸入流,同時寫編碼表名
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
char[] ch = new char[1024];
int len = isr.read(ch);
System.out.println(new String(ch,0,len));
isr.close();
}
/*
* 轉換流,InputSteamReader讀取文本
* 採用系統默認編碼表,讀取GBK文件
*/
public static void readGBK()throws IOException{
//創建自己輸入流,傳遞文本文件
FileInputStream fis = new FileInputStream("c:\\gbk.txt");
//創建轉換流對象,構造方法,包裝字節輸入流
InputStreamReader isr = new InputStreamReader(fis);
char[] ch = new char[1024];
int len = isr.read(ch);
System.out.println(new String(ch,0,len));
isr.close();
}
}
06轉換流子類父類的區別
* A: 轉換流子類父類的區別
* a: 繼承關係
OutputStreamWriter:
|--FileWriter:
InputStreamReader:
|--FileReader;
* b: 區別
* OutputStreamWriter和InputStreamReader是字符和字節的橋樑:也可以稱之爲字符轉換流。字符轉換流原理:字節流+編碼表。
* FileWriter和FileReader:作爲子類,僅作爲操作字符文件的便捷類存在。
當操作的字符文件,使用的是默認編碼表時可以不用父類,而直接用子類就完成操作了,簡化了代碼。
* 以下三句話功能相同
* InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默認字符集。
* InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。
* FileReader fr = new FileReader("a.txt");
07緩衝流概述
* A: 緩衝流概述
* a: 概述
* 可提高IO流的讀寫速度
* 分爲字節緩衝流與字符緩衝流
08字節輸出流緩衝流BufferedOutputStream
* A: 字節輸出流緩衝流BufferedOutputStream
* a: BufferedOutputStream
* 字節輸出流的緩衝流
* java.io.BufferedOuputStream 作用: 提高原有輸出流的寫入效率
* BufferedOuputStream 繼承 OutputStream
* 方法,寫入 write 字節,字節數組
* 構造方法:
* BufferedOuputStream(OuputStream out)
* 可以傳遞任意的字節輸出流, 傳遞的是哪個字節流,就對哪個字節流提高效率
* b: 案例代碼
public class BufferedOutputStreamDemo {
public static void main(String[] args)throws IOException {
//創建字節輸出流,綁定文件
//FileOutputStream fos = new FileOutputStream("c:\\buffer.txt");
//創建字節輸出流緩衝流的對象,構造方法中,傳遞字節輸出流
BufferedOutputStream bos = new
BufferedOutputStream(new FileOutputStream("c:\\buffer.txt"));
bos.write(55);
byte[] bytes = "HelloWorld".getBytes();
bos.write(bytes);
bos.write(bytes, 3, 2);
bos.close();
}
}
09字節輸入流緩衝流BufferedInputStream
* A: 字節輸入流緩衝流BufferedInputStream
* a: BufferedInputStream
* 字節輸入流的緩衝流
* 繼承InputStream,標準的字節輸入流
* 讀取方法 read() 單個字節,字節數組
* 構造方法:
* BufferedInputStream(InputStream in)
* 可以傳遞任意的字節輸入流,傳遞是誰,就提高誰的效率
* 可以傳遞的字節輸入流 FileInputStream
* b: 案例代碼
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException{
//創建字節輸入流的緩衝流對象,構造方法中包裝字節輸入流,包裝文件
BufferedInputStream bis = new
BufferedInputStream(new FileInputStream("c:\\buffer.txt"));
byte[] bytes = new byte[10];
int len = 0 ;
while((len = bis.read(bytes))!=-1){
System.out.print(new String(bytes,0,len));
}
bis.close();
}
}
10四種文件複製方式的效率比較
* A:四種文件複製方式的效率比較
* a: 四中複製方式
* 字節流讀寫單個字節 125250 毫秒
* 字節流讀寫字節數組 193 毫秒 OK
* 字節流緩衝區流讀寫單個字節 1210 毫秒
* 字節流緩衝區流讀寫字節數組 73 毫秒 OK
* b: 案例代碼
public class Copy {
public static void main(String[] args)throws IOException {
long s = System.currentTimeMillis();
copy_4(new File("c:\\q.exe"), new File("d:\\q.exe"));
long e = System.currentTimeMillis();
System.out.println(e-s);
}
/*
* 方法,實現文件複製
* 4. 字節流緩衝區流讀寫字節數組
*/
public static void copy_4(File src,File desc)throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));
int len = 0 ;
byte[] bytes = new byte[1024];
while((len = bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
}
/*
* 方法,實現文件複製
* 3. 字節流緩衝區流讀寫單個字節
*/
public static void copy_3(File src,File desc)throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(desc));
int len = 0 ;
while((len = bis.read())!=-1){
bos.write(len);
}
bos.close();
bis.close();
}
/*
* 方法,實現文件複製
* 2. 字節流讀寫字節數組
*/
public static void copy_2(File src,File desc)throws IOException{
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int len = 0 ;
byte[] bytes = new byte[1024];
while((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}
/*
* 方法,實現文件複製
* 1. 字節流讀寫單個字節
*/
public static void copy_1(File src,File desc)throws IOException{
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int len = 0 ;
while((len = fis.read())!=-1){
fos.write(len);
}
fos.close();
fis.close();
}
}
11字符輸出流緩衝流BufferedWriter
* A: 字符輸出流緩衝流BufferedWriter
* a: BufferedWriter
* 字符輸出流緩衝區流
* java.io.BufferedWriter 繼承 Writer
* 寫入方法 write () 單個字符,字符數組,字符串
* 構造方法:
* BufferedWriter(Writer w)傳遞任意字符輸出流
* 傳遞誰,就高效誰
* 能傳遞的字符輸出流 FileWriter, OutputStreamWriter
* b: 案例代碼
public class BufferedWrierDemo {
public static void main(String[] args) throws IOException{
//創建字符輸出流,封裝文件
FileWriter fw = new FileWriter("c:\\buffer.txt");
BufferedWriter bfw = new BufferedWriter(fw);
bfw.write(100);
bfw.flush();
bfw.write("你好".toCharArray());
bfw.flush();
bfw.write("你好");
bfw.flush();
bfw.write("我好好");
bfw.flush();
bfw.write("大家都好");
bfw.flush();
bfw.close();
}
}
12字符輸出流緩衝流BufferedWriter特有方法newLine
* A: 字符輸出流緩衝流BufferedWriter特有方法newLine
* a: 方法介紹
* void newLine() 寫換行
* newLine()文本中換行, \r\n也是文本換行
* 方法具有平臺無關性
* Windows \r\n
* Linux \n
* newLine()運行結果,和操作系統是相互關係
* JVM: 安裝的是Windows版本,newLine()寫的就是\r\n
* 安裝的是Linux版本,newLine()寫的就是\n
/*
* 將數據源 c:\\a.txt
* 複製到 d:\\a.txt 數據目的
* 字節輸入流,綁定數據源
* 字節輸出流,綁定數據目的
*
* 輸入,讀取1個字節
* 輸出,寫1個字節
*/
* b: 案例代碼
public class BufferedWrierDemo {
public static void main(String[] args) throws IOException{
//創建字符輸出流,封裝文件
FileWriter fw = new FileWriter("c:\\buffer.txt");
BufferedWriter bfw = new BufferedWriter(fw);
bfw.write(100);
bfw.flush();
bfw.write("你好".toCharArray());
bfw.flush();
bfw.write("你好");
bfw.newLine();
bfw.flush();
bfw.write("我好好");
bfw.newLine();
bfw.flush();
bfw.write("大家都好");
bfw.flush();
bfw.close();
}
}
13字符輸入流緩衝流BufferedReader
* A: 字符輸入流緩衝流BufferedReader
* a: 概述
* 從字符輸入流中讀取文本,緩衝各個字符,從而實現字符、數組和行的高效讀取
* public String readLine() 讀取一個文本行,包含該行內容的字符串,不包含任何行終止符,如果已到達流末尾,則返回 null
14字符輸入流緩衝流BufferedReader讀取文本行
* A: 字符輸入流緩衝流BufferedReader讀取文本行
* a: BufferedReader
* 字符輸入流緩衝流
* java.io.BufferedReader 繼承 Reader
* 讀取功能 read() 單個字符,字符數組
* 構造方法:
* BufferedReader(Reader r)
* 可以任意的字符輸入流
FileReader InputStreamReader
* BufferedReader自己的功能
* String readLine() 讀取文本行 \r\n
* 方法讀取到流末尾,返回null
* b: 小特點
* 獲取內容的方法一般都有返回值
* int 沒有返回的都是負數
* 引用類型 找不到返回null
* boolean 找不到返回false
* c: 案例代碼
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
int lineNumber = 0;
//創建字符輸入流緩衝流對象,構造方法傳遞字符輸入流,包裝數據源文件
BufferedReader bfr = new BufferedReader(new FileReader("c:\\a.txt"));
//調用緩衝流的方法 readLine()讀取文本行
//循環讀取文本行, 結束條件 readLine()返回null
String line = null;
while((line = bfr.readLine())!=null){
lineNumber++;
System.out.println(lineNumber+" "+line);
}
bfr.close();
}
}
/*
* String line = bfr.readLine();
System.out.println(line);
line = bfr.readLine();
System.out.println(line);
line = bfr.readLine();
System.out.println(line);
line = bfr.readLine();
System.out.println(line);
line = bfr.readLine();
System.out.println(line);
*/
15字符流緩衝區流複製文本文件
* A: 字符流緩衝區流複製文本文件
* a: 案例代碼
/*
* 使用緩衝區流對象,複製文本文件
* 數據源 BufferedReader+FileReader 讀取
* 數據目的 BufferedWriter+FileWriter 寫入
* 讀取文本行, 讀一行,寫一行,寫換行
*/
public class Copy_1 {
public static void main(String[] args) throws IOException{
BufferedReader bfr = new BufferedReader(new FileReader("c:\\w.log"));
BufferedWriter bfw = new BufferedWriter(new FileWriter("d:\\w.log"));
//讀取文本行, 讀一行,寫一行,寫換行
String line = null;
while((line = bfr.readLine())!=null){
bfw.write(line);
bfw.newLine();
bfw.flush();
}
bfw.close();
bfr.close();
}
}
16IO流對象的操作規律
* A: IO流對象的操作規律
* a: 明確一:要操作的數據是數據源還是數據目的。
* 源:InputStream Reader
* 目的:OutputStream Writer
* 先根據需求明確要讀,還是要寫。
* b: 明確二:要操作的數據是字節還是文本呢?
* 源:
* 字節:InputStream
* 文本:Reader
* 目的:
* 字節:OutputStream
* 文本:Writer
* c: 明確三:明確數據所在的具體設備。
* 源設備:
* 硬盤:文件 File開頭。
* 內存:數組,字符串。
* 鍵盤:System.in;
* 網絡:Socket
* 目的設備:
* 硬盤:文件 File開頭。
* 內存:數組,字符串。
* 屏幕:System.out
* 網絡:Socket
* 完全可以明確具體要使用哪個流對象。
* d: 明確四:是否需要額外功能呢?
* 額外功能:
* 轉換嗎?轉換流。InputStreamReader OutputStreamWriter
* 高效嗎?緩衝區對象。BufferedXXX
* 已經明確到了具體的體系上。
01Properties集合的特點
* A: Properties集合的特點
* a: Properties類介紹
* Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串
* b: 特點
* Hashtable的子類,map集合中的方法都可以用。
* 該集合沒有泛型。鍵值都是字符串。
* 它是一個可以持久化的屬性集。鍵值可以存儲到集合中,也可以存儲到持久化的設備(硬盤、U盤、光盤)上。鍵值的來源也可以是持久化的設備。
* 有和流技術相結合的方法。
* c: 方法介紹
* load(InputStream inputStream) 把指定流所對應的文件中的數據,讀取出來,保存到Propertie集合中
* load(Reader reader) 按簡單的面向行的格式從輸入字符流中讀取屬性列表(鍵和元素對)
* store(OutputStream outputStream,String commonts) 把集合中的數據,保存到指定的流所對應的文件中,參數commonts代表對描述信息
* stroe(Writer writer,String comments) 以適合使用 load(Reader) 方法的格式,將此 Properties 表中的屬性列表(鍵和元素對)寫入輸出字符
02Properties集合存儲鍵值對
* A: Properties集合存儲鍵值對
* a: 方法介紹
* 集合對象Properties類,繼承Hashtable,實現Map接口
* 可以和IO對象結合使用,實現數據的持久存儲
* 使用Properties集合,存儲鍵值對
* setProperty等同與Map接口中的put
* setProperty(String key, String value)
* 通過鍵獲取值, getProperty(String key)
* b: 案例代碼
public class PropertiesDemo {
public static void main(String[] args)throws IOException {
function_2();
}
/*
* 使用Properties集合,存儲鍵值對
* setProperty等同與Map接口中的put
* setProperty(String key, String value)
* 通過鍵獲取值, getProperty(String key)
*/
public static void function(){
Properties pro = new Properties();
pro.setProperty("a", "1");
pro.setProperty("b", "2");
pro.setProperty("c", "3");
System.out.println(pro);
String value = pro.getProperty("c");
System.out.println(value);
//方法stringPropertyNames,將集合中的鍵存儲到Set集合,類似於Map接口的方法keySet
Set<String> set = pro.stringPropertyNames();
for(String key : set){
System.out.println(key+"..."+pro.getProperty(key));
}
}
}
03Properties集合的方法load
* A: Properties集合的方法load
* a: 方法介紹
* Properties集合特有方法 load
* load(InputStream in)
* load(Reader r)
* 傳遞任意的字節或者字符輸入流
* 流對象讀取文件中的鍵值對,保存到集合
* b: 案例代碼
public class PropertiesDemo {
public static void main(String[] args)throws IOException {
function_1();
}
/*
* Properties集合特有方法 load
* load(InputStream in)
* load(Reader r)
* 傳遞任意的字節或者字符輸入流
* 流對象讀取文件中的鍵值對,保存到集合
*/
public static void function_1()throws IOException{
Properties pro = new Properties();
FileReader fr = new FileReader("c:\\pro.properties");
//調用集合的方法load,傳遞字符輸入流
pro.load(fr);
fr.close();
System.out.println(pro);
}
}
04Properties集合的方法store
* A: Properties集合的方法store
* a: 方法介紹
* Properties集合的特有方法store
* store(OutputStream out)
* store(Writer w)
* 接收所有的字節或者字符的輸出流,將集合中的鍵值對,寫回文件中保存
* b: 案例代碼
public class PropertiesDemo {
public static void main(String[] args)throws IOException {
function_2();
}
/*
* Properties集合的特有方法store
* store(OutputStream out)
* store(Writer w)
* 接收所有的字節或者字符的輸出流,將集合中的鍵值對,寫回文件中保存
*/
public static void function_2()throws IOException{
Properties pro = new Properties();
pro.setProperty("name", "zhangsan");
pro.setProperty("age", "31");
pro.setProperty("email", "[email protected]");
FileWriter fw = new FileWriter("c:\\pro.properties");
//鍵值對,存迴文件,使用集合的方法store傳遞字符輸出流
pro.store(fw, "");
fw.close();
}
}
05對象的序列化與反序列化
* A: 對象的序列化與反序列化
* a: 基本概念
* 對象的序列化
* 對象中的數據,以流的形式,寫入到文件中保存過程稱爲寫出對象,對象的序列化
* ObjectOutputStream將對象寫道文件中,實現序列化
* 對象的反序列化
* 在文件中,以流的形式,將對象讀出來,讀取對象,對象的反序列化
* ObjectInputStream 將文件對象讀取出來
06ObjectOutputStream流寫對象
* A: ObjectOutputStream流寫對象
* a: 簡單介紹
* IO流對象,實現對象Person序列化,和反序列化
* ObjectOutputStream 寫對象,實現序列化
* ObjectInputStream 讀取對象,實現反序列化
* b: 案例代碼
public class Person implements Serializable{
public String name;
public int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class ObjectStreamDemo {
public static void main(String[] args)throws IOException, ClassNotFoundException {
// writeObject();
readObject();
}
/*
* ObjectOutputStream
* 構造方法: ObjectOutputStream(OutputSteam out)
* 傳遞任意的字節輸出流
* void writeObject(Object obj)寫出對象的方法
*/
public static void writeObject() throws IOException{
//創建字節輸出流,封裝文件
FileOutputStream fos = new FileOutputStream("c:\\person.txt");
//創建寫出對象的序列化流的對象,構造方法傳遞字節輸出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("lisi",25);
//調用序列化流的方法writeObject,寫出對象
oos.writeObject(p);
oos.close();
}
}
07ObjectInputStream流讀取對象
* A: ObjectInputStream流讀取對象
* a: 簡單介紹
* ObjectInputStream
* 構造方法:ObjectInputStream(InputStream in)
* 傳遞任意的字節輸入流,輸入流封裝文件,必須是序列化的文件
* Object readObject() 讀取對象
* b: 案例代碼
/*
* IO流對象,實現對象Person序列化,和反序列化
* ObjectOutputStream 寫對象,實現序列化
* ObjectInputStream 讀取對象,實現反序列化
*/
public class ObjectStreamDemo {
public static void main(String[] args)throws IOException, ClassNotFoundException {
readObject();
}
/*
* ObjectInputStream
* 構造方法:ObjectInputStream(InputStream in)
* 傳遞任意的字節輸入流,輸入流封裝文件,必須是序列化的文件
* Object readObject() 讀取對象
*/
public static void readObject() throws IOException, ClassNotFoundException{
FileInputStream fis = new FileInputStream("c:\\person.txt");
//創建反序列化流,構造方法中,傳遞字節輸入流
ObjectInputStream ois = new ObjectInputStream(fis);
//調用反序列化流的方法 readObject()讀取對象
Object obj =ois.readObject();
System.out.println(obj);
ois.close();
}
}
08靜態不能序列化
* A: 靜態不能序列化
* a: 原因
* 序列化是把對象數據進行持久化存儲
* 靜態的東西不屬於對象,而屬於類
09transient關鍵字
* A: transient關鍵字
* a: 作用
* 被transient修飾的屬性不會被序列化
* transient關鍵字只能修飾成員變量
10Serializable接口的含義
* A:Serializable接口的含義
* a: 作用
* 給需要序列化的類上加標記。該標記中沒有任何抽象方法
* 只有實現了 Serializable接口的類的對象才能被序列化
11序列化中的序列號衝突問題
* A: 序列化中的序列號衝突問題
* a: 問題產生原因
* 當一個類實現Serializable接口後,創建對象並將對象寫入文件,之後更改了源代碼(比如:將成員變量的修飾符有private改成public),
再次從文件中讀取對象時會報異常
* 見day25_source文件夾下的"序列號的衝突.JPG"文件
12序列化中自定義的序列號
* A: 序列化中自定義的序列號
* a: 定義方式
* private static final long serialVersionUID = 1478652478456L;
* 這樣每次編譯類時生成的serialVersionUID值都是固定的
* b: 案例代碼
public class Person implements Serializable{
public String name;
public /*transient阻止成員變量序列化*/ int age;
//類,自定義了序列號,編譯器不會計算序列號
private static final long serialVersionUID = 1478652478456L;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
###13打印流和特性
* A: 打印流和特性
* a: 概述
* 打印流添加輸出數據的功能,使它們能夠方便地打印各種數據值表示形式.
* 打印流根據流的分類:
* 字節打印流 PrintStream
* 字符打印流 PrintWriter
* 方法:
* void print(String str): 輸出任意類型的數據,
* void println(String str): 輸出任意類型的數據,自動寫入換行操作
* b: 特點
* 此流不負責數據源,只負責數據目的
* 爲其他輸出流,添加功能
* 永遠不會拋出IOException,但是可能拋出別的異常
* 兩個打印流的方法,完全一致
* 構造方法,就是打印流的輸出目的端
* PrintStream構造方法
* 接收File類型,接收字符串文件名,接收字節輸出流OutputStream
* PrintWriter構造方法
* 接收File類型,接收字符串文件名,接收字節輸出流OutputStream, 接收字符輸出流Writer
14打印流輸出目的是File對象
* A: 打印流輸出目的是File對象
* a: 案例代碼
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
function_3();
}
/*
* 打印流,向File對象的數據目的寫入數據
* 方法print println 原樣輸出
* write方法走碼錶
*/
public static void function() throws FileNotFoundException{
File file = new File("c:\\1.txt");
PrintWriter pw = new PrintWriter(file);
pw.println(true);
pw.write(100);
pw.close();
}
}
15輸出語句是char數組
* A: 輸出語句是char數組
* a: 案例代碼
public class Demo {
public static void main(String[] args) {
int[] arr = {1};
System.out.println(arr);
char[] ch = {'a','b'};
System.out.println(ch);
byte[] b = {};
System.out.println(b);
}
}
* b: 結果分析
* println數組,只有打印字符數組時只有容,其餘均打印數組的地址
* 因爲api中定義了打印字符數組的方法,其底層是在遍歷數組中的元素
* 而其他打印數組的方法,都是將數組對象編程Object,其底層再將對象編程String,調用了String s = String.valueOf(x);方法
16打印流輸出目的是String和流對象
* A: 打印流輸出目的是String和流對象
* a: 案例代碼
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
function_2();
}
/*
* 打印流,輸出目的,是流對象
* 可以是字節輸出流,可以是字符的輸出流
* OutputStream Writer
*/
public static void function_2() throws IOException{
// FileOutputStream fos = new FileOutputStream("c:\\3.txt");
FileWriter fw = new FileWriter("c:\\4.txt");
PrintWriter pw = new PrintWriter(fw);
pw.println("打印流");
pw.close();
}
/*
* 打印流,輸出目的,String文件名
*/
public static void function_1() throws FileNotFoundException{
PrintWriter pw = new PrintWriter("c:\\2.txt");
pw.println(3.5);
pw.close();
}
}
17打印流開啓自動刷新
* A: 打印流開啓自動刷新
* 案例代碼
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
function_3();
}
/*
* 打印流,可以開啓自動刷新功能
* 滿足2個條件:
* 1. 輸出的數據目的必須是流對象
* OutputStream Writer
* 2. 必須調用println,printf,format三個方法中的一個,啓用自動刷新
*/
public static void function_3()throws IOException{
//File f = new File("XXX.txt");
FileOutputStream fos = new FileOutputStream("c:\\5.txt");
PrintWriter pw = new PrintWriter(fos,true);
pw.println("i");
pw.println("love");
pw.println("java");
pw.close();
}
}
18打印流複製文本文件
* A: 打印流複製文本文件
* a: 案例代碼
/*
* 打印流實現文本複製
* 讀取數據源 BufferedReader+File 讀取文本行
* 寫入數據目的 PrintWriter+println 自動刷新
*/
public class PrintWriterDemo1 {
public static void main(String[] args) throws IOException{
BufferedReader bfr = new BufferedReader(new FileReader("c:\\a.txt"));
PrintWriter pw = new PrintWriter(new FileWriter("d:\\a.txt"),true);
String line = null;
while((line = bfr.readLine())!=null){
pw.println(line);
}
pw.close();
bfr.close();
}
}
19commons-io工具類介紹
* A: commons-io工具類介紹
* a: 工具類介紹
* 解壓縮commons-io-2.4.zip文件
* commons-io-2.4.jar需要導入到項目中的jar包,裏面存放的是class文件
* commons-io-2.4-sources.jar工具類中原代碼
* docs是幫助文檔
20使用工具類commons_io
* A: 使用工具類commons_io
* a: 導入jar包
* 加入classpath的第三方jar包內的class文件才能在項目中使用
* 創建lib文件夾
* 將commons-io.jar拷貝到lib文件夾
* 右鍵點擊commons-io.jar,Build Path→Add to Build Path
* b: 學會如何看源代碼
21IO工具類FilenameUtils
* A: IO工具類FilenameUtils
* a: 方法介紹
* getExtension(String path):獲取文件的擴展名;
* getName():獲取文件名;
* isExtension(String fileName,String ext):判斷fileName是否是ext後綴名;
* b: 案例代碼
public class Commons_IODemo {
public static void main(String[] args) {
function_2();
}
/*
* FilenameUtils類的方法
* static boolean isExtension(String filename,String extension)
* 判斷文件名的後綴是不是extension
*/
public static void function_2(){
boolean b = FilenameUtils.isExtension("Demo.java", "java");
System.out.println(b);
}
/*
* FilenameUtils類的方法
* static String getName(String filename)
* 獲取文件名
*/
public static void function_1(){
String name = FilenameUtils.getName("c:\\windows\\");
System.out.println(name);
}
/*
* FilenameUtils類的方法
* static String getExtension(String filename)
* 獲取文件名的擴展名
*/
public static void function(){
String name = FilenameUtils.getExtension("c:\\windows");
System.out.println(name);
}
}
22IO工具類FileUtils
* A: IO工具類FileUtils
* a: 方法介紹
* readFileToString(File file):讀取文件內容,並返回一個String;
* writeStringToFile(File file,String content):將內容content寫入到file中;
* copyDirectoryToDirectory(File srcDir,File destDir);文件夾複製
* copyFile(File srcFile,File destFile);文件複製
* b: 案例代碼
public class Commons_IODemo1 {
public static void main(String[] args)throws IOException {
function_3();
}
/*
* FileUtils工具類方法
* static void copyDirectoryToDirectory(File src,File desc)
* 複製文件夾
*/
public static void function_3() throws IOException{
FileUtils.copyDirectoryToDirectory(new File("d:\\demo"), new File("c:\\"));
}
/*
* FileUtils工具類的方法
* static void copyFile(File src,File desc)
* 複製文件
*/
public static void function_2() throws IOException{
FileUtils.copyFile(new File("c:\\k.jpg"),new File("d:\\k.jpg"));
}
/*
* FileUtils工具類的方法
* static void writeStringToFile(File src,String date)
* 將字符串直接寫到文件中
*/
public static void function_1() throws IOException{
FileUtils.writeStringToFile(new File("c:\\b.txt"),"我愛Java編程");
}
/*
* FileUtils工具類的方法
* static String readFileToString(File src)讀取文本,返回字符串
*/
public static void function() throws IOException{
String s = FileUtils.readFileToString(new File("c:\\a.txt"));
System.out.println(s);
}
}
01進程概念
*A:進程概念
*a:進程:進程指正在運行的程序。確切的來說,當一個程序進入內存運行,
即變成一個進程,進程是處於運行過程中的程序,並且具有一定獨立功能。
02線程的概念
*A:線程的概念
*a:線程:線程是進程中的一個執行單元(執行路徑),負責當前進程中程序的執行,
一個進程中至少有一個線程。一個進程中是可以有多個線程的,
這個應用程序也可以稱之爲多線程程序。
簡而言之:一個程序運行後至少有一個進程,一個進程中可以包含多個線程
03深入線程的概念
A:深入線程的概念
什麼是多線程呢?
即就是一個程序中有多個線程在同時執行。
一個核心的CPU在多個線程之間進行着隨即切換動作,由於切換時間很短(毫秒甚至是納秒級別),導致我們感覺不出來
單線程程序:即,若有多個任務只能依次執行。當上一個任務執行結束後,下一個任務開始執行。如去 網吧上網,網吧只能讓一個人上網,當這個人下機後,下一個人才能上網。
多線程程序:即,若有多個任務可以同時執行。如,去網吧上網,網吧能夠讓多個人同時上網。
04迅雷的多線程下載
A:迅雷的多線程下載
多線程,每個線程都讀一個文件
05線程的運行模式
A:線程的運行模式
a:分時調度
所有線程輪流使用 CPU 的使用權,平均分配每個線程佔用 CPU 的時間。
b:搶佔式調度
優先讓優先級高的線程使用 CPU,如果線程的優先級相同,那麼會隨機選擇一個(線程隨機性),Java使用的爲搶佔式調度。
大部分操作系統都支持多進程併發運行,現在的操作系統幾乎都支持同時運行多個程序。比如:現在我們上課一邊使用編輯器,一邊使用錄屏軟件,同時還開着畫圖板,dos窗口等軟件。此時,這些程序是在同時運行,”感覺這些軟件好像在同一時刻運行着“。
實際上,CPU(中央處理器)使用搶佔式調度模式在多個線程間進行着高速的切換。對於CPU的一個核而言,某個時刻,只能執行一個線程,而 CPU的在多個線程間切換速度相對我們的感覺要快,看上去就是在同一時刻運行。
其實,多線程程序並不能提高程序的運行速度,但能夠提高程序運行效率,讓CPU的使用率更高。
06main的主線程
*A:main的主線程
/*
* 程序中的主線程
*/
public class Demo {
public static void main(String[] args) {
System.out.println(0/0);
function();
System.out.println(Math.abs(-9));
}
public static void function(){
for(int i = 0 ; i < 10000;i++){
System.out.println(i);
}
}
}
=======================第二節課開始=============================================
07Thread類介紹
A:Thread類介紹:Thread是程序中的執行線程。Java 虛擬機允許應用程序併發地運行多個執行線程。
發現創建新執行線程有兩種方法。
a:一種方法是將類聲明爲 Thread 的子類。該子類應重寫 Thread 類的 run 方法。創建對象,開啓線程。run方法相當於其他線程的main方法。
b:另一種方法是聲明一個實現 Runnable 接口的類。該類然後實現 run 方法。然後創建Runnable的子類對象,傳入到某個線程的構造方法中,開啓線程。
08實現線程程序繼承Thread
*A:實現線程程序繼承Thread
/*
* 創建和啓動一個線程
* 創建Thread子類對象
* 子類對象調用方法start()
* 讓線程程序執行,JVM調用線程中的run
*/
public class ThreadDemo {
public static void main(String[] args) {
SubThread st = new SubThread();
SubThread st1 = new SubThread();
st.start();
st1.start();
for(int i = 0; i < 50;i++){
System.out.println("main..."+i);
}
}
}
/*
* 定義子類,繼承Thread
* 重寫方法run
*/
public class SubThread extends Thread{
public void run(){
for(int i = 0; i < 50;i++){
System.out.println("run..."+i);
}
}
}
09線程執行的隨機性
*A:線程執行的隨機性
/*
代碼分析:
整個程序就只有三個線程,
一個是主線程
啓動另外兩個線程
st.start();
st1.start();
for(int i = 0; i < 50;i++){
System.out.println("main..."+i);
}
一個是st(Thread-0)線程
for(int i = 0; i < 50;i++){
System.out.println("run..."+i);
}
一個是st1(Thread-1)線程下
*/
public class ThreadDemo {
public static void main(String[] args) {
SubThread st = new SubThread();
SubThread st1 = new SubThread();
st.start();
st1.start();
for(int i = 0; i < 50;i++){
System.out.println("main..."+i);
}
}
}
/*
* 定義子類,繼承Thread
* 重寫方法run
*/
public class SubThread extends Thread{
public void run(){
for(int i = 0; i < 50;i++){
System.out.println("run..."+i);
}
}
}
10爲什麼要繼承Thread
*A:什麼要繼承Thread
a:我們爲什麼要繼承Thread類,並調用其的start方法才能開啓線程呢?
繼承Thread類:因爲Thread類用來描述線程,具備線程應該有功能。那爲什麼不直接創建Thread類的對象呢?
如下代碼:
Thread t1 = new Thread();
t1.start();//這樣做沒有錯,但是該start調用的是Thread類中的run方法
//而這個run方法沒有做什麼事情,更重要的是這個run方法中並沒有定義我們需要讓線程執行的代碼。
b:創建線程的目的是什麼?
是爲了建立程序單獨的執行路徑,讓多部分代碼實現同時執行。也就是說線程創建並執行需要給定線程要執行的任務。
對於之前所講的主線程,它的任務定義在main函數中。自定義線程需要執行的任務都定義在run方法中。
11多線程內存圖解
*A:多線程內存圖解
多線程執行時,到底在內存中是如何運行的呢?
多線程執行時,在棧內存中,其實每一個執行線程都有一片自己所屬的棧內存空間。進行方法的壓棧和彈棧。
當執行線程的任務結束了,線程自動在棧內存中釋放了。但是當所有的執行線程都結束了,那麼進程就結束了。
=======================第三節課開始=============================================
12獲取線程名字Thread類方法getName
*A:獲取線程名字Thread類方法getName
/*
* 獲取線程名字,父類Thread方法
* String getName()
*/
public class NameThread extends Thread{
public NameThread(){
super("小強");
}
public void run(){
System.out.println(getName());
}
}
/*
* 每個線程,都有自己的名字
* 運行方法main線程,名字就是"main"
* 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1"
*
* JVM開啓主線程,運行方法main,主線程也是線程,是線程必然就是
* Thread類對象
*/
public class ThreadDemo {
public static void main(String[] args) {
NameThread nt = new NameThread();
nt.start();
}
}
13獲取線程名字Thread類方法currentThread
*A:獲取線程名字Thread類方法currentThread
/*
* 獲取線程名字,父類Thread方法
* String getName()
*/
public class NameThread extends Thread{
public void run(){
System.out.println(getName());
}
}
/*
* 每個線程,都有自己的名字
* 運行方法main線程,名字就是"main"
* 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1"
*
* JVM開啓主線程,運行方法main,主線程也是線程,是線程必然就是
* Thread類對象
* Thread類中,靜態方法
* static Thread currentThread()返回正在執行的線程對象
*/
public class ThreadDemo {
public static void main(String[] args) {
NameThread nt = new NameThread();
nt.start();
/*Thread t =Thread.currentThread();
System.out.println(t.getName());*/
System.out.println(Thread.currentThread().getName());
}
}
14線程名字設置
A:線程名字設置
/*
* 獲取線程名字,父類Thread方法
* String getName()
*/
public class NameThread extends Thread{
public NameThread(){
super("小強");
}
public void run(){
System.out.println(getName());
}
}
/*
* 每個線程,都有自己的名字
* 運行方法main線程,名字就是"main"
* 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1"
*
* JVM開啓主線程,運行方法main,主線程也是線程,是線程必然就是
* Thread類對象
* Thread類中,靜態方法
* static Thread currentThread()返回正在執行的線程對象
*/
public class ThreadDemo {
public static void main(String[] args) {
NameThread nt = new NameThread();
nt.setName("旺財");
nt.start();
}
}
15Thread類方法sleep
A:Thread類方法sleep
public class ThreadDemo {
public static void main(String[] args) throws Exception{
/*for(int i = 0 ; i < 5 ;i++){
Thread.sleep(50);
System.out.println(i);
}*/
new SleepThread().start();
}
}
public class SleepThread extends Thread{
public void run(){
for(int i = 0 ; i < 5 ;i++){
try{
Thread.sleep(500);//睡眠500ms,500ms已到並且cpu切換到該線程繼續向下執行
}catch(Exception ex){
}
System.out.println(i);
}
}
}
16實現線程的另一種方式實現Runnable接口
A:實現線程的另一種方式實現Runnable接口
/*
* 實現接口方式的線程
* 創建Thread類對象,構造方法中,傳遞Runnable接口實現類
* 調用Thread類方法start()
*/
public class ThreadDemo {
public static void main(String[] args) {
SubRunnable sr = new SubRunnable();
Thread t = new Thread(sr);
t.start();
for(int i = 0 ; i < 50; i++){
System.out.println("main..."+i);
}
}
}
/*
* 實現線程成功的另一個方式,接口實現
* 實現接口Runnable,重寫run方法
*/
public class SubRunnable implements Runnable{
public void run(){
for(int i = 0 ; i < 50; i++){
System.out.println("run..."+i);
}
}
}
17實現接口方式的好處
A:實現接口方式的好處
第二種方式實現Runnable接口避免了單繼承的侷限性,所以較爲常用。
實現Runnable接口的方式,更加的符合面向對象,線程分爲兩部分,一部分線程對象,一部分線程任務。
繼承Thread類,線程對象和線程任務耦合在一起。
一旦創建Thread類的子類對象,既是線程對象,有又有線程任務。
實現runnable接口,將線程任務單獨分離出來封裝成對象,類型就是Runnable接口類型。Runnable接口對線程對象和線程任務進行解耦。
(降低緊密性或者依賴性,創建線程和執行任務不綁定)
18匿名內部類實現線程程序
*A:匿名內部類實現線程程序
/*
* 使用匿名內部類,實現多線程程序
* 前提: 繼承或者接口實現
* new 父類或者接口(){
* 重寫抽象方法
* }
*/
public class ThreadDemo {
public static void main(String[] args) {
//繼承方式 XXX extends Thread{ public void run(){}}
new Thread(){
public void run(){
System.out.println("!!!");
}
}.start();
//實現接口方式 XXX implements Runnable{ public void run(){}}
Runnable r = new Runnable(){
public void run(){
System.out.println("###");
}
};
new Thread(r).start();
new Thread(new Runnable(){
public void run(){
System.out.println("@@@");
}
}).start();
}
}
=======================第四節課開始=============================================
19線程的狀態圖
A:線程的狀態圖
a:參見線程狀態圖.jpg
20線程池的原理
A:線程池的原理
1.在java中,如果每個請求到達就創建一個新線程,開銷是相當大的。
2.在實際使用中,創建和銷燬線程花費的時間和消耗的系統資源都相當大,甚至可能要比在處理實際的用戶請求的時間和資源要多的多。
3.除了創建和銷燬線程的開銷之外,活動的線程也需要消耗系統資源。
如果在一個jvm裏創建太多的線程,可能會使系統由於過度消耗內存或“切換過度”而導致系統資源不足。
爲了防止資源不足,需要採取一些辦法來限制任何給定時刻處理的請求數目,儘可能減少創建和銷燬線程的次數,特別是一些資源耗費比較大的線程的創建和銷燬,儘量利用已有對象來進行服務。
線程池主要用來解決線程生命週期開銷問題和資源不足問題。通過對多個任務重複使用線程,線程創建的開銷就被分攤到了多個任務上了,而且由於在請求到達時線程已經存在,所以消除了線程創建所帶來的延遲。這樣,就可以立即爲請求服務,使用應用程序響應更快。另外,通過適當的調整線程中的線程數目可以防止出現資源不足的情況。
21JDK5實現線程池
A:JDK5實現線程池
/*
* JDK1.5新特性,實現線程池程序
* 使用工廠類 Executors中的靜態方法創建線程對象,指定線程的個數
* static ExecutorService newFixedThreadPool(int 個數) 返回線程池對象
* 返回的是ExecutorService接口的實現類 (線程池對象)
*
* 接口實現類對象,調用方法submit (Ruunable r) 提交線程執行任務
*
*/
public class ThreadPoolDemo {
public static void main(String[] args) {
//調用工廠類的靜態方法,創建線程池對象
//返回線程池對象,是返回的接口
ExecutorService es = Executors.newFixedThreadPool(2);
//調用接口實現類對象es中的方法submit提交線程任務
//將Runnable接口實現類對象,傳遞
es.submit(new ThreadPoolRunnable());
es.submit(new ThreadPoolRunnable());
es.submit(new ThreadPoolRunnable());
}
}
public class ThreadPoolRunnable implements Runnable {
public void run(){
System.out.println(Thread.currentThread().getName()+" 線程提交任務");
}
}
22實現線程的Callable接口方式
A:實現線程的Callable接口方式
/*
* 實現線程程序的第三個方式,實現Callable接口方式
* 實現步驟
* 工廠類 Executors靜態方法newFixedThreadPool方法,創建線程池對象
* 線程池對象ExecutorService接口實現類,調用方法submit提交線程任務
* submit(Callable c)
*/
public class ThreadPoolDemo1 {
public static void main(String[] args)throws Exception {
ExecutorService es = Executors.newFixedThreadPool(2);
//提交線程任務的方法submit方法返回 Future接口的實現類
Future<String> f = es.submit(new ThreadPoolCallable());
String s = f.get();
System.out.println(s);
}
}
/*
* Callable 接口的實現類,作爲線程提交任務出現
* 使用方法返回值
*/
import java.util.concurrent.Callable;
public class ThreadPoolCallable implements Callable<String>{
public String call(){
return "abc";
}
}
23線程實現異步計算
A:線程實現異步計算
/*
* 使用多線程技術,求和
* 兩個線程,1個線程計算1+100,另一個線程計算1+200的和
* 多線程的異步計算
*/
public class ThreadPoolDemo {
public static void main(String[] args)throws Exception {
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Integer> f1 =es.submit(new GetSumCallable(100));
Future<Integer> f2 =es.submit(new GetSumCallable(200));
System.out.println(f1.get());
System.out.println(f2.get());
es.shutdown();
}
}
public class GetSumCallable implements Callable<Integer>{
private int a;
public GetSumCallable(int a){
this.a=a;
}
public Integer call(){
int sum = 0 ;
for(int i = 1 ; i <=a ; i++){
sum = sum + i ;
}
return sum;
}
}