Day14基礎(chǔ)不牢地動山搖-Java基礎(chǔ)
1、定時器
推動整個計算機硬件的發(fā)展的核心關(guān)鍵性技術(shù)就是時鐘。所以在企業(yè)開發(fā)中定時操作往往成為開發(fā)重點。而在JDK本身也支持這種定時調(diào)度的處理操作,這種操作不會直接使用。還是和多線程有關(guān)。
- 如果想要定時調(diào)度處理操作,需要兩個類
- 定時調(diào)度任務(wù):java.util.TimerTask定時調(diào)度操作:java.util.Timer
package com.day14.demo; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; class MyTask extends TimerTask{ @Override public void run() { // TODO Auto-generated method stub System.out.println(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS").format(new Date())); } } public class TaskDemo { public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new MyTask(), 1000,2000); } }
2、UUID類
UUID類是根據(jù)你當(dāng)前的地址還有時間戳自動生成一個幾乎不會重復(fù)的字符串。
package com.day14.demo; import java.util.UUID; public class UUIDDemo { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); System.out.println(uuid); } }
以后再文件上傳等類似的操作中通過UUID類來進行簡單的文件名稱,以防止重名的問題。
3、Base64加密處理
Base64是一種數(shù)據(jù)加密算法,使用整個算法可以使我們的數(shù)據(jù)進行安全處理。如果要想進行加密處理可以使用兩個:加密器、解密器。
加密處理
package com.day14.demo; import java.util.Base64; public class Base64Demo { public static void main(String[] args) { String msg = "123456"; String emsg = Base64.getEncoder().encodeToString(msg.getBytes()); System.out.println("加密:" + emsg); byte[] decode = Base64.getDecoder().decode(emsg); System.out.println("解密:" + new String(decode)); } }
多次加密
package com.day14.demo; import java.util.Base64; public class Base64Demo { public static void main(String[] args) { String msg = encode("123456"); String emsg = encode(encode(encode(msg))); System.out.println("加密:" + emsg); byte[] decode = Base64.getDecoder().decode(emsg); System.out.println("解密:" + new String(decode)); } public static String encode(String code){ return Base64.getEncoder().encodeToString(code.getBytes()); } }
還有一個做法就是種子樹
package com.day14.demo; import java.util.Base64; public class Base64Demo { public static void main(String[] args) { String sed = encode("zsr--rsz"); String msg = "123456"+sed; String emsg = encode(msg); System.out.println("加密:" + emsg); byte[] decode = Base64.getDecoder().decode(emsg); System.out.println("解密:" + new String(decode)); } public static String encode(String code){ return Base64.getEncoder().encodeToString(code.getBytes()); } }
必須保證長度,以后的開發(fā)將Base64和MD5一起開發(fā),長度是32位。
4、ThreadLocal類
TheadLocal類不繼承Thread類,也不實現(xiàn)Runable接口,ThreadLocal類為每一個線程都維護了自己獨有的變量拷貝。每個線程都擁有自己獨立的變量。
ThreadLocal采用了“以空間換時間”的方式:訪問并行化,對象獨享化。前者僅提供一份變量,讓不同的線程排隊訪問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。
ThreadLocal的實現(xiàn)是這樣的:每個Thread維護了一個ThreadLocalMap映射表,這個映射表的key是ThreadLocal實例本身。Value是真正需要存儲的變量。也就是說,ThreadLocal本身并不存儲值,它只是作為一個key來讓線程從ThreadLocalMap獲取value。注意,ThreadLocalMap是使用ThreadLocal的弱引用作為key的,弱引用的對象在GC時會被回收。
通過給方法傳遞參數(shù),調(diào)用兩個線程輸出不同的信息
package com.day14.demo; class Message{ private String note; public String getNote() { return note; } public void setNote(String note) { this.note = note; }; } class GetMessage{ public void print(Message msg){ System.out.println(Thread.currentThread().getName() + msg.getNote()); } } public class ThreadLocalDemo { public static void main(String[] args) { new Thread(()->{ Message message = new Message(); message.setNote("Hello,world!!"); new GetMessage().print(message); },"用戶A").start(); new Thread(()->{ Message message = new Message(); message.setNote("Hello,world!!zsr"); new GetMessage().print(message); },"用戶B").start(); } }
但是我現(xiàn)在的需求是不希望通過傳遞傳輸給GetMessage的print方法,還希望實現(xiàn)相同的功能。
package com.day14.demo; class Message{ private String note; public String getNote() { return note; } public void setNote(String note) { this.note = note; }; } class GetMessage{ public void print(Message msg){ System.out.println(Thread.currentThread().getName() + msg.getNote()); } } public class ThreadLocalDemo { public static void main(String[] args) { new Thread(()->{ Message message = new Message(); message.setNote("Hello,world!!"); new GetMessage().print(message); },"用戶A").start(); new Thread(()->{ Message message = new Message(); message.setNote("Hello,world!!zsr"); new GetMessage().print(message); },"用戶B").start(); } }
我們發(fā)現(xiàn)兩個線程的內(nèi)容并沒有同步輸出,所以我們會想到通過ThreadLocal類來解決此數(shù)據(jù)不同步的問題。
public class ThreadLocal<T> extends Object
這個類里面有幾個重要的方法:
- 取得數(shù)據(jù):public T get()
- 存放數(shù)據(jù):public void set(T value)
- 刪除數(shù)據(jù):public void remove()
利用ThreadLocal來解決當(dāng)前我問題
package com.day14.demo; class Message{ private String note; public String getNote() { return note; } public void setNote(String note) { this.note = note; }; } class GetMessage{ public void print(){ System.out.println(Thread.currentThread().getName() + MyUtil.get().getNote()); } } class MyUtil{ private static ThreadLocal<Message> tl = new ThreadLocal<Message>(); public static void set(Message msg){ tl.set(msg); } public static Message get(){ return tl.get(); } } public class ThreadLocalDemo { public static void main(String[] args) { new Thread(()->{ Message msg = new Message(); msg.setNote("Hello,world!!"); MyUtil.set(msg); new GetMessage().print(); },"用戶A").start(); new Thread(()->{ Message msg = new Message(); msg.setNote("Hello,world!!zsr"); MyUtil.set(msg); new GetMessage().print(); },"用戶B").start(); } }
這樣我們就解決了數(shù)據(jù)不同步的問題了。
5、IO—File類
5.1 基本操作
如果要想學(xué)好IO,必須要清楚抽象類、IO的操作部分掌握兩個代碼模型。IO的核心組成五個類(File、OutputStream、InputStream、Writer、Reader)一個接口(Serializable)。
再java.io是一個與文本本身操作有關(guān)的程序(創(chuàng)建、刪除、信息取得—)
如果要想使用File類操作文件的話,那么肯定要通過構(gòu)造方法實例化File類對象,而實例化File類對象的過程之中主要使用以下兩種構(gòu)造方法:
- 方法一:public File(String pathname);
- 方法二:public File(File parent,String child).
文件的基本操作,主要有以下幾種功能:
- **創(chuàng)建一個新文件:**public boolean createNewFile() throws IOException
- **刪除文件:**public Boolean delete();
- **判斷路徑是否存在:**public Boolean exists();
創(chuàng)建新文件
package com.day14.demo; import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) throws IOException { File file = new File("f:\\hello.txt"); file.createNewFile(); } }
如果文件存在進行刪除,不存在進行創(chuàng)建
package com.day14.demo; import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) throws IOException { File file = new File("f:\\hello.txt"); if(file.exists()){//文件存在 file.delete(); }else{//文件不存在 file.createNewFile();//創(chuàng)建文件 } } }
本程序操作就表示如果文件存在則刪除,如果不存在則創(chuàng)建一個新的文件,此時基本功能是實現(xiàn)了,不過這個程序此時存在三個問題:
問題一:關(guān)于路徑的分隔符
在windows操作之中,使用“\”作為路徑分隔符,而在Linux系統(tǒng)下使用“/”作為路徑分隔符,而實際的開發(fā)而言,大部分情況下會在windows中做開發(fā),而后將項目部署在Linus,那么此時,路徑的分隔符都需要進行修改,這樣實在是國語麻煩,為此在File類之中提供了一個常量:public static final String separator(按照Java的命名規(guī)范來講,對于全局常量應(yīng)該使用大寫字母的方式定義,而此處使用的是小寫,是由Java的發(fā)展歷史所帶來的問題)。
//由不同的操作系統(tǒng)的JVM來決定最終的separator是什么內(nèi)容File file = new File("f:" + File.separator + "hello.txt");
問題二:是有可能會出現(xiàn)的延遲問題
發(fā)現(xiàn)程序執(zhí)行完成之后,對于文件的創(chuàng)建或者是刪除是會存在一些操作上的延遲,如果現(xiàn)在假設(shè)先刪除了一個文件,而后立刻判斷此文件是否存在,那么可能得到的結(jié)果就是錯誤的(為true),一位所有的*.class文件都要通過JVM與操作系統(tǒng)間接操作,這樣就有可能會出現(xiàn)延遲的問題。
問題三:目錄問題
之前進行文件創(chuàng)建的時候都是在根目錄下創(chuàng)建完成的,如果說現(xiàn)在要創(chuàng)建的文件有目錄呢?例如,現(xiàn)在要創(chuàng)建一個f:\hello\hello.txt文件,而此時在執(zhí)行程序的時候hello目錄不存在,這個時候執(zhí)行的話就會出現(xiàn)錯誤提示:
Exception in thread "main" java.io.IOException: 系統(tǒng)找不到指定的路徑。
因為現(xiàn)在目錄不存在,所以不能創(chuàng)建,那么這個時候必須首先判斷要創(chuàng)建文件的父路徑是否存在,如果不存在應(yīng)該創(chuàng)建一個目錄,之后再進行文件的創(chuàng)建,而要想完成這樣的操作,需要一下幾個方法支持:
**找到一個指定文件的父路徑:**public File getParentFile();
**創(chuàng)建目錄:**public boolean mldirs()。
package com.day14.demo; import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) throws IOException { //由不同的操作系統(tǒng)的JVM來決定最終的separator是什么內(nèi)容 File file = new File("f:" + File.separator +"hello" + File.separator + "hello.txt"); if(!file.getParentFile().exists()){//父目錄 file.getParentFile().mkdirs();//創(chuàng)建父目錄 } if(file.exists()){//文件存在 file.delete(); }else{//文件不存在 file.createNewFile();//創(chuàng)建文件 } } }
以后在任何的java.io.File類開發(fā)過程之中,都一定要考慮文件目錄的問題。
5.2 取得文件信息
在File類之中還可以通過以下的方法取得一些文件的基本信息:
方法名稱 | 描述 |
public String getName() | 取得文件的名稱 |
public boolean isDirectory() | 給定的路徑是否為文件夾 |
public boolean isFile() | 給定的路徑是否是文件 |
public boolean isHidden() | 是否是隱藏文件 |
public long lastModified() | 文件的最后一次修改日期 |
public long length() | 取得文件大小,是以字節(jié)為單位返回的。 |
獲取文件的大小信息以及核心信息
package com.day14.demo;import java.io.File;import java.math.BigDecimal;import java.text.SimpleDateFormat;import java.util.Date;class MyMath{ public static double round(double num, int scale){ return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale); }}public class FileDemo2 { public static void main(String[] args) { File file = new File("f:" + File.separator + "701_03_支付寶沙箱使用.avi"); if(file.exists() && file.isFile()){ System.out.println("1文件大小為:" + MyMath.round(file.length() / (double) 1024 / 1024, 2)); System.out.println("最后一次修改日期:"+ new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date(file.lastModified()))); System.out.println("2文件大小為:" + new BigDecimal(file.length() / (double)1024 /1024).divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP).doubleValue()); } }}
**列出目錄內(nèi)容:**public File [] listFiles(),此方法將目錄中的所有文件以File對象數(shù)組的方式返回;
列出目錄的所有結(jié)構(gòu)
package com.day14.demo; import java.io.File; import java.util.Arrays; public class FileDemo3 { public static void main(String[] args) { File file = new File("f:" + File.separator); if(file.exists() && file.isDirectory()){ File[] listFiles = file.listFiles(); System.out.println(Arrays.toString(listFiles)); } } }
5.3 綜合案例:目錄列表
現(xiàn)在希望把一個目錄下的全部文件都列出來,那么這種情況下只能采用遞歸:因為列出一個目錄下的全部文件或著文件夾之后,如果發(fā)現(xiàn)列出的內(nèi)容是文件夾,則應(yīng)該向后繼續(xù)列出。
列出指定目錄下的所有文件
package com.day14.demo; import java.io.File; public class FileListDemo { public static void main(String[] args) { File file = new File("f:" + File.separator); list(file); } public static void list(File file){ if(file.isDirectory()){ File[] files = file.listFiles(); if(files != null){ for (int i = 0; i < files.length; i++) { list(files[i]);//繼續(xù)列出 } } } System.out.println(file); } }
線程阻塞問題
現(xiàn)在代碼都在main線程下執(zhí)行,如果該程序執(zhí)行完成后才能繼續(xù)執(zhí)行下一條語句,要想解決這種耗時的問題。最好產(chǎn)生一個新的線程進行列出。
package com.day14.demo;import java.io.File;public class FileListDemo { public static void main(String[] args) { new Thread(()->{ File file = new File("f:" + File.separator); list(file); },"列出線程").start(); System.out.println("開始進行文件信息列出。。。。"); } public static void list(File file){ if(file.isDirectory()){ File[] files = file.listFiles(); if(files != null){ for (int i = 0; i < files.length; i++) { list(files[i]);//繼續(xù)列出 } } } System.out.println(file); }}
6、IO— 字節(jié)流與字符流
字符流和字節(jié)流最本質(zhì)的區(qū)別就是只有一個字節(jié)流是原生的操作,二字符流是經(jīng)過處理后的操作。經(jīng)過磁盤數(shù)據(jù)保存所保存的支持的數(shù)據(jù)類型只有:字節(jié),所有磁盤中的數(shù)據(jù)必須先讀到內(nèi)存后才可以操作,內(nèi)存里面會幫助我們把字節(jié)變?yōu)樽址?。字符更加適合處理中文。
**字節(jié)操作流:**OutputStream,InputStream;
**字符操作流:**Writer,Reader。
但是不管是字節(jié)流還是字符流的操作,本身都表示資源操作,而執(zhí)行所有的資源都會按照如下幾個步驟進行,下面以文件操作為例(對文件進行讀,寫操作):
- 要根據(jù)文件創(chuàng)建File對象
- 根據(jù)字節(jié)流或字符流的子類實例化我們的父類對象
- 進行數(shù)據(jù)的讀取、寫入操作
- 關(guān)閉流(clone())
對于IO操作屬于資源處理,所有的對于資源的處理進行處理完成后必須進行關(guān)閉,否則資源就再也無法執(zhí)行。
6.1 字節(jié)輸出流:OutputStream
Java.io.OutputStream主要的功能是進行字節(jié)數(shù)據(jù)的輸出的,而這個類的定義如下:
public abstract class OutputStream extends Object implements Closeable, Flushable
發(fā)現(xiàn)OutputStream類定義的時候?qū)崿F(xiàn)了兩個接口:Closeable,Flushable,這兩個接口定義如下:
Closeable: | Flushable: |
public interface Closeable extends AutoCloseable{ public void close() throws IOException; } |
public interface Closeable{ public void flush() throws IOException; } |
當(dāng)取得了OutputStream類實例化對象之后,下面肯定要進行輸出操作,在OutputStream類之中定義了三個方法:
**輸出單個字節(jié)數(shù)組數(shù)據(jù):**public abstract void write(int b) throws IOException
**輸出一組字節(jié)數(shù)組數(shù)據(jù):**public void write(byte[] b) throws IOException
**輸出部分字節(jié)數(shù)組數(shù)據(jù):**public void write(byte[] b,int off,int len) throws IOException
提示:對于Closeable繼承的AutoCloseable接口
AuotCloseable實在JDK1.7的時候又增加了一個新的接口,但是這個接口的定義和Closeable定義是完全一樣的,我個人認為:有可能在一些其他的類上出現(xiàn)了自動的關(guān)閉功能,Closeable是手工關(guān)閉,AutoCloseable屬于自動關(guān)閉。
但是對于Closeable和Flushable這兩個接口實話而言不需要關(guān)注,因為從最早的習(xí)慣對于flush()和close()連個方法都是直接在OutputStream類之中定義的,所以很少去關(guān)心這些父接口問題。
對于OutputStream類而言發(fā)現(xiàn)其本身定義的是一個抽象類(abstract class),按照抽象類的使用原則來講,如果要想為父類實例化,那么就需要使用子類,就需要定義抽象的子類,而現(xiàn)在如果要執(zhí)行的是文件操作,則可以使用FileOutputStream子類完成。如果按照面向?qū)ο蟮拈_發(fā)原則,子類要為抽象類進行對象的實例化,而后調(diào)用的方法以父類中定義的方法為主,而具體的實現(xiàn)找實例化這個父類的子類完成,也就是說在整個的操作之中,用戶最關(guān)心的只有子類的構(gòu)造方法:
**實例化FileOutputStream(新建數(shù)據(jù)):**public FileOutputStream([File file) throws FileNotFoundException
**實例化FileOutputStream(追加數(shù)據(jù)):**public FileOutputStream(File file,boolean append) throws FileNotFoundException
實現(xiàn)文件內(nèi)容的輸出
package com.day14.demo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class OutputDemo { public static void main(String[] args) throws Exception { //1.定義文件路徑 File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.getParentFile().exists()){//父路徑不存在 file.getParentFile().mkdirs();//創(chuàng)建父目錄 } //2.要輸出的數(shù)據(jù) String str = "Hello,zsr!!!!"; //3.實例化對象 FileOutputStream stream = new FileOutputStream(file); //4.將內(nèi)容寫進stream stream.write(str.getBytes());//輸出數(shù)據(jù),要將輸出的數(shù)據(jù)變?yōu)樽止?jié)數(shù)組輸出 //5.關(guān)閉流 stream.close(); } }
這里默認執(zhí)行時進行文檔內(nèi)容的覆寫,如果不希望進行文檔內(nèi)容的覆寫可以直接將FileOutputStream改為
FileOutputStream stream = new FileOutputStream(file,true);
如果對寫入的內(nèi)容需要換行操作必須使用\r\n進行換行操作。
6.2 字節(jié)輸入流:InputStream
如果現(xiàn)在要從指定的數(shù)據(jù)源之中讀取數(shù)據(jù),使用InputStream,而這個類的定義如下:
public abstract class InputStreamextends Objectimplements Closeable
發(fā)現(xiàn)InputStream只實現(xiàn)了Closeable接口
在InputStream之中定義了三個讀取數(shù)據(jù)的方法:
**讀取單個字節(jié):**public abstract int read() throws IOException
**說明:**每次執(zhí)行read()方法都會讀取一個數(shù)據(jù)源的指定數(shù)據(jù),如果現(xiàn)在發(fā)現(xiàn)已經(jīng)讀取到了結(jié)尾則返回-1.
**讀取多個字節(jié):**public int read(byte[] b) throws IOException
**說明:**如果現(xiàn)在要讀取的數(shù)據(jù)小于開辟的字節(jié)數(shù)組,這個時候read()方法的返回值int返回的是數(shù)據(jù)個數(shù);如果現(xiàn)在開辟的字節(jié)數(shù)組小于讀取的長度,則這個時候返回就是長度;如果數(shù)據(jù)已經(jīng)讀完了,則這個時候的int返回的是-1.
**讀取指定多個字節(jié):**public int read(byte[] b,int off,int len) throws IOException
**說明:**每次只讀取傳遞數(shù)組的部分內(nèi)容,如果讀取滿了,返回就是長度;如果沒有讀取滿,返回的就是讀取的個數(shù);如果讀取到最后沒有數(shù)據(jù)了,就返回-1
既然InputStream為抽象類,那么這個抽象類要使用就必須有子類,現(xiàn)在是通過文件讀取內(nèi)容,肯定使用FileInputStream子類進行操作,與OutputStream類的使用一樣,對于FileInputStream也只關(guān)心構(gòu)造方法:
**FileInputStream****類構(gòu)造方法:public FileInputStream(File file) throws FileNotFoundException
文件信息的讀取
package com.day14.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; public class InputDemo { public static void main(String[] args) throws Exception { File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.exists()){ System.out.println("指定文件不存在??!"); }else{ FileInputStream is = new FileInputStream(file); byte[] result = new byte[1024]; int length = is.read(result); System.out.println("讀取的內(nèi)容為:" + new String(result,0,length)); } } }
6.3 字符輸出流:Writer
Writer類也是一個專門用來數(shù)據(jù)輸出的操作類,對于中文數(shù)據(jù)來說是比較友好的,這個類定義:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
在Writer類之中定義的writer()方法都是以字符數(shù)據(jù)為主,但是在這些方法之中,只關(guān)心一個:
**輸出一個字符串:**public void write(String str) throws IOException
如果要操作文件肯定使用FileWriter子類。
package com.day14.demo; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class WriterDemo { public static void main(String[] args) throws IOException { //1.定義文件路徑 File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.getParentFile().exists()){//父路徑不存在 file.getParentFile().mkdirs();//創(chuàng)建父目錄 } //2.要輸出的數(shù)據(jù) String str = "我正在學(xué)java這門課程?。。?!\r\n"; //如果想要進行內(nèi)容不覆蓋的直接使用true就可以了 //FileWriter out = new FileWriter(file,true); FileWriter out = new FileWriter(file); out.write(str); out.close(); } }
6.4 字符輸入流:Reader
Reader是進行字符數(shù)據(jù)讀取的一個操作類,其定義:
public abstract class Reader extends Object implements Readable, Closeable
在Writer類之中存在了直接輸出一個字符串?dāng)?shù)據(jù)的方法,可是在Reader類之中并沒有定義這樣的方法,只是定義了三個按照字符串讀取的方法?為什么會這樣?
因為在使用OutputStream輸出數(shù)據(jù)的時候,其程序可以輸出的大小一定是程序可以承受的數(shù)據(jù)的大小,那么如果說使用InputStream讀取的時候,可能被讀取的數(shù)據(jù)非常大,那么如果一次性全讀進來,就會出現(xiàn)問題,所以只能一個一個的進行讀取。
Reader依然是抽象類,那么如果從文件讀取,依然使用FileReader類
package com.day14.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class ReadDemo { public static void main(String[] args) throws IOException { File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.exists()){ System.out.println("指定文件不存在??!"); }else{ FileReader reader = new FileReader(file); char[] result = new char[1024]; int length = reader.read(result); System.out.println("讀取的內(nèi)容為:" + new String(result,0,length)); } } }
字符比字節(jié)的好處就是在于字符串?dāng)?shù)據(jù)的支持上,而這個好處還只是在Writer()類中體現(xiàn),所以與字節(jié)流相比,字符流的操作并不是對等的關(guān)系。
6.5 字節(jié)流與字符流區(qū)別
通過我們一系統(tǒng)的分析,可以發(fā)現(xiàn)字節(jié)流和字符流的代碼操作區(qū)別不大,如果從我們實際的使用,我們字節(jié)流是優(yōu)先考慮,只有再我們使用中文的時候才考慮使用字符流,因為所有的字符都需要通過內(nèi)存緩沖來進行處理。
既然讀數(shù)據(jù)需要緩存的處理,那么寫數(shù)據(jù)也同樣需要。如果使用字符流沒有進行刷新,那么我們的內(nèi)容可能再緩存之中,所以必須進行強制刷新才能得到完整的數(shù)據(jù)內(nèi)容。
package com.day14.demo; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class WriterDemo { public static void main(String[] args) throws IOException { //1.定義文件路徑 File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.getParentFile().exists()){//父路徑不存在 file.getParentFile().mkdirs();//創(chuàng)建父目錄 } //2.要輸出的數(shù)據(jù) String str = "我正在學(xué)java這門課程?。。?!\r\n"; //如果想要進行內(nèi)容不覆蓋的直接使用true就可以了 //FileWriter out = new FileWriter(file,true); FileWriter out = new FileWriter(file); out.write(str); out.flush(); } }
在以后的IO處理的時候,如果處理的是圖片、音樂、文字都可以使用字節(jié)流,只有再處理中文的時候才會使用字符流。
7、轉(zhuǎn)換流
現(xiàn)在對于IO操作就存在了字節(jié)流和字符流兩種操作,那么對于這兩種操作流之間也是可以進行轉(zhuǎn)換的,而轉(zhuǎn)換的操作類有兩個:
將字節(jié)輸出流變?yōu)樽址敵隽鳎∣utputStream->Writer)——OutputStreamWriter;
將字節(jié)輸入流變?yōu)樽址斎肓鳎↖nputStream->Reader)——InputStreaReader。
OutputStreamWriter | InputStreamReader |
public class OutputStreamWriter extends Writer | public class InputStreamReader extends Reader |
public OutputStreamWriter(OutputStream out) | public InputStreamReader(InputStream in) |
通過以上的繼承結(jié)構(gòu)和構(gòu)造方法可以清楚發(fā)現(xiàn),既然OutputStreamWriter是Writer的子類,那么必然OutputStreamWriter可以通過Writer類執(zhí)行對象的向上轉(zhuǎn)型進行接收,而同時這個OutputStreamWriter類的構(gòu)造方法可以接收OutputStream,這樣就可以完成轉(zhuǎn)型。
將字節(jié)輸出流變?yōu)樽址敵隽?/p>
package com.day14.demo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; public class OutWriterDemo { public static void main(String[] args) throws Exception { //1.定義文件路徑 File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt"); if(!file.getParentFile().exists()){//父路徑不存在 file.getParentFile().mkdirs();//創(chuàng)建父目錄 } //2.要輸出的數(shù)據(jù) String str = "Hello,world!!!!"; //3.實例化對象 OutputStream stream = new FileOutputStream(file,true); //4.將內(nèi)容寫進stream Writer out = new OutputStreamWriter(stream); out.write(str); //5.關(guān)閉流 out.close(); } }
對于文件操作可以使用FileInputStream,F(xiàn)ileOutputStream,F(xiàn)ileReader,F(xiàn)ileWriter四個類,那么下面分別觀察這四個類的繼承結(jié)構(gòu)。
觀察FileInputStream,F(xiàn)ileOutoutStream類的繼承結(jié)構(gòu)
FileInputStream | FileOutoutStream |
java.lang.Object java.io.InputStream java.io.FilterInputStream |
java.lang.Object java.io.OutputStream java.io.FileOutputStream |
觀察FileReader,F(xiàn)ileWriter類的繼承結(jié)構(gòu)
FileReader | FileWrite |
java.lang.Object java.io.Reader java.io.InputStreamReader java.io.FileReader |
java.lang.Object java.io.Writer java.io.OutputStreamWriter java.io.FileWriter |
通過以上的繼承關(guān)系也可以發(fā)現(xiàn),實際上所有的字符數(shù)據(jù)都是需要進行轉(zhuǎn)換的,依靠轉(zhuǎn)換流完成,以后真正保存或者是傳輸?shù)臄?shù)據(jù)是不可能有字符的,全部都是字節(jié),而字節(jié)只是在電腦之中處理后的結(jié)果。
到此這篇關(guān)于Day14基礎(chǔ)不牢地動山搖-Java基礎(chǔ)的文章就介紹到這了,更多相關(guān)Java基礎(chǔ)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!