Java IO詳解

IO 是什么?其實(shí)就是Java中的一種輸入和輸出功能,也可以理解為對(duì)文件的寫入和讀出的操作,只不過Java中對(duì)這種操作叫做對(duì)流的操作。而流不只是對(duì)文件進(jìn)行讀寫,還可以對(duì)內(nèi)存,網(wǎng)絡(luò),程度操作。

一、字節(jié)與字符

在Java中有輸入、輸出兩種IO流,每種輸入、輸出流又分為字節(jié)流和字符流兩大類。

  • 關(guān)于字節(jié),每個(gè)字節(jié)(byte)有8bit組成。
  • 關(guān)于字符,我們可能知道代表一個(gè)漢字或者英文字母。

字節(jié)與字符之間的關(guān)系
Java采用unicode編碼,通講,2個(gè)字節(jié)來表示一個(gè)字符。
在0~127整數(shù)之間的字符映射,unicode向下兼容ASCII,也就是1個(gè)字節(jié)表示一個(gè)字符。
一個(gè)中文或英文字符的unicode編碼都占2個(gè)字節(jié)。

編碼方式 英文字符 中文字符
GB 2312、GBK 1 2
UTF-8 1 3-4
UTF-16 2 3-4
UTF-32 4 4

二、File

文件和文件夾的操作都可以用File來完成。

文件的獲取
File.png
//構(gòu)造函數(shù)File(String pathname)
File f1 =new File("c:\\abc\\1.txt");
//File(String parent,String child)
File f2 =new File("c:\\abc","2.txt");
//File(File parent,String child)
File f3 =new File("c:"+File.separator+"abc");//separator 跨平臺(tái)分隔符
File f4 =new File(f3,"3.txt");
System.out.println(f1);//c:\abc\1.txt
文件的創(chuàng)建以及刪除
//如果文件存在返回false,否則返回true并且創(chuàng)建文件 
boolean createNewFile();
//創(chuàng)建一個(gè)File對(duì)象所對(duì)應(yīng)的目錄,成功返回true,否則false。且File對(duì)象必須為路徑而不是文件。只會(huì)創(chuàng)建最后一級(jí)目錄,如果上級(jí)目錄不存在就拋異常。
boolean mkdir();
//創(chuàng)建一個(gè)File對(duì)象所對(duì)應(yīng)的目錄,成功返回true,否則false。且File對(duì)象必須為路徑而不是文件。創(chuàng)建多級(jí)目錄,創(chuàng)建路徑中所有不存在的目錄
boolean mkdirs()    ;
//如果文件存在返回true并且刪除文件,否則返回false
boolean delete();
//在虛擬機(jī)終止時(shí),刪除File對(duì)象所表示的文件或目錄。
void deleteOnExit();
判斷方法
boolean canExecute()    ;//判斷文件是否可執(zhí)行
boolean canRead();//判斷文件是否可讀
boolean canWrite();//判斷文件是否可寫
boolean exists();//判斷文件是否存在
boolean isDirectory();//判斷是否是目錄
boolean isFile();//判斷是否是文件
boolean isHidden();//判斷是否是隱藏文件或隱藏目錄
boolean isAbsolute();//判斷是否是絕對(duì)路徑 文件不存在也能判斷

作者:Ruheng
鏈接:http://www.itdecent.cn/p/c58ed5ec7e4a
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
獲取參數(shù)方法
String getName();//返回文件或者是目錄的名稱
String getPath();//返回路徑
String getAbsolutePath();//返回絕對(duì)路徑
String getParent();//返回父目錄,如果沒有父目錄則返回null
long lastModified();//返回最后一次修改的時(shí)間
long length();//返回文件的長(zhǎng)度
File[] listRoots();// 列出所有的根目錄(Window中就是所有系統(tǒng)的盤符)
String[] list() ;//返回一個(gè)字符串?dāng)?shù)組,給定路徑下的文件或目錄名稱字符串
String[] list(FilenameFilter filter);//返回滿足過濾器要求的一個(gè)字符串?dāng)?shù)組
File[]  listFiles();//返回一個(gè)文件對(duì)象數(shù)組,給定路徑下文件或目錄
File[] listFiles(FilenameFilter filter);//返回滿足過濾器要求的一個(gè)文件對(duì)象數(shù)組

其中FilenameFileter 是一個(gè)文件過濾器。找到所有png圖片。

        file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".png");
            }
        });

三、IO流

Java的IO流是實(shí)現(xiàn)輸入/輸出的基礎(chǔ),它可以方便地實(shí)現(xiàn)數(shù)據(jù)的輸入/輸出操作,在Java中把不同的輸入/輸出源抽象表述為"流"。
流是一組有順序的字節(jié)集合,是對(duì)數(shù)據(jù)傳輸?shù)目偡Q或抽象。
流有輸入和輸出,輸入時(shí)是流從數(shù)據(jù)源流向程序。輸出時(shí)是流從程序傳向數(shù)據(jù)源,而數(shù)據(jù)源可以是內(nèi)存,文件,網(wǎng)絡(luò)或程序等。

四、分類

  • 按照流向不同,分為 輸入流、輸出流
  • 按照流對(duì)象不同,分為 字節(jié)流、字符流

字節(jié)流可以處理任意類型的數(shù)據(jù),而字符只能處理字符類型的數(shù)據(jù)

  • 按照處理過程不同,分為 節(jié)點(diǎn)流、處理流(一種典型的裝飾器模式)

五、4中基本方式的講解 和 實(shí)例

4種基本方式
  • inputStream
  • outputStream
  • Reader
  • Write
    四大抽象基類,其中inputStream,outputStream是字節(jié)流的基類,Reader,Write是字符流的基類。不能創(chuàng)建實(shí)例,但是為所有實(shí)現(xiàn)類提供了基礎(chǔ)的模板。
inputStream
inputStream.png
outputStream
outputStream.png
Reader
Reader.png
Write
Write.png

總結(jié):
從上面的方法中我可以看出。inputStreamreader,outputStreamwrite的函數(shù)都很相似,并且每次進(jìn)行了IO操作,要記得close,因?yàn)镮O資源并不屬于內(nèi)存資源,并不會(huì)被GC回收。所以需要顯示的 手動(dòng)的回收資源。對(duì)于輸出操作,close還會(huì)自動(dòng)flush。

六、RandomAccessFile的使用與簡(jiǎn)介

RandomAccessFile簡(jiǎn)介

我們?cè)趯?duì)文件的操作過程中,除了使用字節(jié)流和字符流的方式之外,我們還可以使用RandomAcessFile這個(gè)工具類來實(shí)現(xiàn)。

RandomAccessFile可以實(shí)現(xiàn)對(duì)文件的,但是他并不是繼承于以上4中基本虛擬類。

而且在對(duì)文件的操作中,RandomAccessFile有一個(gè)巨大的優(yōu)勢(shì),他可以支持文件的隨機(jī)訪問,程序快可以直接跳轉(zhuǎn)到文件的任意地方來讀寫數(shù)據(jù)。所以如果需要訪問文件的部分內(nèi)容,而不是把文件從頭讀到尾,使用RandomAccessFile將是更好的選擇。

RandomAccessFile的方法雖然多,但它有一個(gè)最大的局限,就是只能讀寫文件,不能讀寫其他IO節(jié)點(diǎn)。

RandomAccessFile的一個(gè)重要使用場(chǎng)景就是網(wǎng)絡(luò)請(qǐng)求中的多線程下載及斷點(diǎn)續(xù)傳。

構(gòu)造方法以及參數(shù)
構(gòu)造方法.png

mode中,有4中啟動(dòng)的方式
"r" 以只讀方式打開。調(diào)用結(jié)果對(duì)象的任何 write 方法都將導(dǎo)致拋出 IOException。
"rw" 打開以便讀取和寫入。如果該文件尚不存在,則嘗試創(chuàng)建該文件。

"rws" 打開以便讀取和寫入,對(duì)于 "rw",還要求對(duì)文件的內(nèi)容或元數(shù)據(jù)的每個(gè)更新都同步寫入到底層存儲(chǔ)設(shè)備。
"rwd" 打開以便讀取和寫入,對(duì)于 "rw",還要求對(duì)文件內(nèi)容的每個(gè)更新都同步寫入到底層存儲(chǔ)設(shè)備。

RandomAccessFile使用

讀取文件內(nèi)容

            RandomAccessFile raf = new RandomAccessFile(file,"r");
            String s = null;
            while ((s = raf.readLine())!=null){
                System.out.println(s);
            }
            raf.close();

寫入文件內(nèi)容

String text = "寫入的內(nèi)容 \n";
            RandomAccessFile raf = new RandomAccessFile(file,"rw");
            raf.seek(12);   //改變寫入偏移的位置,從地12個(gè)字節(jié)的位置開始寫入
            raf.write(text.getBytes());
            raf.close();

注意:RandomAccessFile雖然可以設(shè)置了偏移的方法,但他不能實(shí)現(xiàn)中間插入的效果,如果你需要實(shí)現(xiàn)文本中間插入的話,要先將后面的文件內(nèi)容拷貝,然后寫入,最后在寫入的寫一行,將拷貝的東西復(fù)制回來。

七、對(duì)象的序列化與反序列化

什么是序列化和反序列化呢?這是針對(duì)對(duì)象來說的,因?yàn)槲覀冊(cè)趯懭胛募臅r(shí)候,常常因?yàn)橐4娴氖且粋€(gè)對(duì)象,也就是一個(gè)obj,但是里面的變量又很多,我們不可能挨個(gè)申明,一個(gè)個(gè)寫入,這時(shí)候,我們就可以使用對(duì)象的序列化與反序列化。

序列化就是對(duì)象到保存文件的過程。
反序列化就是從保存的文件,轉(zhuǎn)換為對(duì)象的過程。

我們使用ObjectOutputStream和ObjectInputStream 實(shí)現(xiàn)對(duì)象的序列化和反序列化。

File file = new File("test.txt");

        MyService ms = new MyService();
        try {
            OutputStream os = new FileOutputStream(file);
            //創(chuàng)建時(shí),需要給予一個(gè)outputStream,這個(gè)很好理解,
            //因?yàn)閷?duì)象操作肯定是字節(jié)操作,不能使用字符操作
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(ms);
            oos.close();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        try {
            InputStream is = new FileInputStream(file);
            ObjectInputStream ios = new ObjectInputStream(is);
            MyService object = (MyService)ios.readObject();
            System.out.println(object.name);
            is.close();
            ios.close();    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容