Java高級- IO流

13.1.File類的使用

File類的使用
1.File類的一個對象,代表一個文件或一個文件目錄(俗稱: 文件夾)
2.File類聲明在java.io包下
3.File類中涉及到關于文件或文件目錄的創(chuàng)建,刪除,重命名,修改時間,文件大小等方法,
并未涉及到寫入或讀取文件內容的操作.若需要讀取或寫入文件內容,必須用IO流來完成.
4.后續(xù)File類的對象常會作為參數(shù)傳遞到流的構造器中,指明讀取或寫入的"終點"(:從哪讀或寫入到哪,或叫節(jié)點,這個點就用File來表示),真的要讀寫內容了,File類的對象主要指的是一個文件就不是文件目錄了

  • File類的實例化

1.如何創(chuàng)建File類的實例
File(String filePath)
File(String filePath, String childPath)
File(File parentFile, String childPath)
2.相對路徑: 相較于某個路徑下,指明的路徑
絕對路徑: 包含盤符在內的文件或文件目錄的路徑
3.路徑分隔符:
windows: \
unix: /

@Test
    public void test1(){
        // 構造器1
        File file1 = new File("hello.txt");// 路徑相對于當前module
        File file2 = new File("F:\\markdown\\JavaSE\\基礎語法\\src\\com\\JavaSenior\\IO\\he.txt");// 第二條斜杠表示避免轉義的意思
        // 這里還這是單元測試現(xiàn)在還不需要對應硬盤中的文件,此時就僅僅只是內存層面的對象,還沒有涉及到對文件中的數(shù)據(jù)的操作,現(xiàn)在就理解為內存層面對象而已
        System.out.println(file1);
        System.out.println(file2);
        // 構造器2,在上一層目錄下指定的可以是文件也可以是文件目錄
        File file3 = new File("F:\\markdown\\JavaSE\\基礎語法\\src\\com","JavaSenior");// 上一層目錄和下一層目錄
        System.out.println(file3);
        // 構造器3: 在file3的目下創(chuàng)建的文件
        File file4 = new File(file3, "hi.txt");
        System.out.println(file4);
    }
  • File類的常用方法
// File類的常用方法
    @Test
    public void test2(){
        File file1 = new File("hello.txt");
        File file2 = new File("F:\\markdown\\IO\\hi.txt");
        // 獲取絕對路徑
        System.out.println(file1.getAbsolutePath());
        // 獲取路徑
        System.out.println(file1.getPath());
        //獲取名字
        System.out.println(file1.getName());
        // 獲取上層文件目錄路徑,若無返回null
        System.out.println(file1.getParent());
        // 獲取文件長度(大小)(即:字節(jié)數(shù)).不能獲取目錄長度
        System.out.println(file1.length());
        // 獲取最后一次修改時間,毫秒值
        System.out.println(new Date(file1.lastModified()));
        System.out.println();
        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
        System.out.println(file2.getName());
        System.out.println(file2.getParent());
        System.out.println(file2.length());
        System.out.println(file2.lastModified());
    }
    // 如下的兩個方法適用于文件目錄:
    //public String[] list(): 獲取指定目錄下的所有文件或文件目錄的名稱數(shù)組
    // public File[] listFiles(): 獲取指定模流下的所有文件或文件目錄的File數(shù)組
    @Test
    public void test3(){
        File file = new File("F:\\markdown\\JavaSE");
        String[] list = file.list();// 獲取下一層目錄或文件
        for (String s : list) {
            System.out.println(s);
        }
        File[] files = file.listFiles();// 以絕對路徑方式獲取下一層文件或目錄
        for (File f : files) {
            System.out.println(f);
        }
    }
    /*
    public boolean renamTo(File dest): 把文件移動到指定文件路徑并重命名
    比如: file1.renameTo(file2)為例:
    要想保證返回true,要file1在硬盤中是存在的,且file2不能在硬盤中存在
     */
    @Test
    public void test4(){
        File file1 = new File("hello.txt");
        File file2 = new File("F:\\markdown\\IO\\hi.txt");
        boolean renameTo = file1.renameTo(file2);
        System.out.println(renameTo);
    }
    @Test
    public void test5(){
        File file1 = new File("hello.txt");
        System.out.println(file1.isDirectory());//是否為文件目錄
        System.out.println(file1.isFile());// 是否為文件
        System.out.println(file1.exists());//是否真正在硬盤中存在
        System.out.println(file1.canRead());//是否可讀
        System.out.println(file1.canWrite());//是否可寫
        System.out.println(file1.isHidden());//是否隱藏
        // 判斷文件呢目錄
        File file2 = new File("F:\\markdown\\IO");
        System.out.println(file2.isDirectory());
        System.out.println(file2.isFile());
        System.out.println(file2.exists());
        System.out.println(file2.canRead());
        System.out.println(file2.canWrite());
        System.out.println(file2.isHidden());
    }
    @Test
    public void test6() throws IOException {
        File file1 = new File("hi.txt");
        // 如果不存在
        if (!file1.exists()) {
            // 創(chuàng)建文件.若文件真實存在硬盤中,則不創(chuàng)建,返回false
            file1.createNewFile();
            System.out.println("創(chuàng)建成功");
        }else{// 文件存在
            // 刪除磁盤中的文件或文件目錄,java中的刪除不走回收站
            file1.delete();
            System.out.println("刪除成功");
        }
    }
    @Test
    public void test7(){
        // 文件目錄(夾)的創(chuàng)建
        File file1 = new File("F:\\markdown\\IO\\IO1\\IO3");// 上一層目錄存在
        // 創(chuàng)建文件目錄.如果此文件目錄存在,就不創(chuàng)建了.如果此文件目錄的上層目錄不存在,也不創(chuàng)建
        boolean mkdir = file1.mkdir();
        if (mkdir) {
            System.out.println("創(chuàng)建成功1");
        }
        File file2 = new File("F:\\markdown\\IO\\IO1\\IO4");
        // 創(chuàng)建文件目錄,若上層文件目錄不存在,一并創(chuàng)建
        boolean mkdirs = file2.mkdirs();
        if (mkdirs) {
            System.out.println("創(chuàng)建成功2");
        }
        // 文件刪除,要想成功,欲刪除的文件目錄下不能有子目錄或文件
        File file3 = new File("F:\\markdown\\IO\\IO1\\IO3");
        System.out.println(file3.delete());
    }

File類的練習

public class FileDemo {
    // 在
    @Test
    public void test1() throws IOException {
        // 創(chuàng)建一個與file同目錄下的另一個文件,名為"haha.txt"
        File file = new File("F:\\markdown\\IO\\IO1\\hello.txt");
        File destFile = new File(file.getParent(), "haha.txt");
        boolean newFile = destFile.createNewFile();
        if (newFile) {
            System.out.println("創(chuàng)建成功");
        }
    }
    // 打印出指定目錄所有文件名稱,包括子文件目錄中的文件
    @Test
    public void test4(){
        // 創(chuàng)建目錄對象
        File dir = new File("F:\\markdown\\JavaSE");
        printSubFile(dir);
    }
    public static void printSubFile(File dir){
        // 打印目錄子文件
        File[] subFiles = dir.listFiles();
        // 循環(huán)每個子文件
        for (File f : subFiles) {
            // 判斷子文件是否文件目錄
            // 是文件夾,遞歸打印文件目錄方法
            if (f.isDirectory()) {
                printSubFile(f);
            }else{
                // 不是文件夾,輸出每個文件的絕對地址
                System.out.println(f.getAbsolutePath());
            }
        }
    }
}

13.2.IO流原理及流的分類

image.png
image.png
image.png
  • 字節(jié)流: 以一個byte(8bit)為基本單位傳輸?shù)牧?適合處理非文本數(shù)據(jù)
  • 字符流: 以一個char(兩個字節(jié):16bit)為基本單位傳輸?shù)?適合處理文本數(shù)據(jù)
  • 節(jié)點流: 直接作用在文件上的流
  • 處理流: 作用在已有節(jié)點流處理之上的
  • IO流的體系結構

一.流的分類:
1.操作的數(shù)據(jù)單位: 字節(jié)流,字符流
2.數(shù)據(jù)的流向: 輸入流,輸出流
3.流的角色: 節(jié)點流,處理流
二.流的體系結構

抽象基類 節(jié)點流(或文件流) 緩沖流(處理流的一種)
InputStream FileInputStream (read(byte[] buffer)) BufferedInputStream (read(byte[] buffer))
OutputStream FileOutputStream (write(byte[] buffer,0,len)) BufferedOutputStream (write(byte[] buffer,0,len))/ flush()
Reader FileReader (read(char[] cbuf)) BufferedReader (read(char[] cbuf))
Writer FileWriter (write(char[] cbuf,0,len)) BufferedWriter (write(char[] cbuf,0,len))/ flush()

13.3.節(jié)點流(或文件流).

  • FileReader讀入數(shù)據(jù)的基本操作
public class FileReaderWriterTest {
    public static void main(String[] args) {
        // 用絕對路徑可以無視main和單元測試
        // 相較于當前工程: F:\markdown\JavaSE\hello.txt
        File file = new File("hello.txt");
        System.out.println(file.getAbsolutePath());
        File file1 = new File("IO\\hello.txt");// 地址這要寫就可以相較于當前module下
        System.out.println(file1.getAbsolutePath());
    }
    /*
    將IOmodule下的hello.txt文件內容讀入程序中,并輸出到控制臺,實現(xiàn)讀取硬盤中文件的操作
    說明點:
    1.read()的理解: 返回讀入的一個字符.如果達到文件末尾,返回-1
    2.異常處理: 為了保證流資源一定可以執(zhí)行關閉操作.要使用try-catch-finally處理
    3.讀入的文件一定要存在,否則就會報FileNotFoundException
     */
    @Test // 單元測試,歸具體的module所有
    public void testFileReader() {
        // 異常處理用try-catch比throws好,假如流的對象創(chuàng)建好了沒有拋異常,但是下面read的時候出現(xiàn)阻塞讀不過來拋了一個IOException
        // 出現(xiàn)了異常就會創(chuàng)建一個異常對象,默認情況下就拋出程序了,相當于程序后面就不執(zhí)行了,這個時候流就沒關,資源就浪費了,存在內存泄露
        // 為了保證即使出現(xiàn)了read異常也要能執(zhí)行流的資源能執(zhí)行關閉操作,所以不要用過throws處理,流資源的關閉放在finally是為了防止中途return退出
        FileReader fr = null; // 因為外部要使用,所以這里要先定義
        try {
            // 1.實例化File類的對象,指明要操作的文件
            File file = new File("hello.txt");// 相較于當前module:F:\markdown\JavaSE\基礎語法\hello.txt
            // 2.提供具體的字符流來操作文件,相當于給文件提供一個管道來輸出數(shù)據(jù)
            fr = new FileReader(file);// 參數(shù)提供文件的路徑或名字,上面的file文件一定要存在,否則就會報異常
            // 打開管道的開關,讓數(shù)據(jù)流出
            // 3.數(shù)據(jù)的讀入
            // read(): 返回讀入的一個字符.如果達到文件末尾,返回-1,讀的是char類型但返回的是字符的int型值
            // int data = fr.read();// 讀取文件返回單個字符,文件讀完(讀取字符末尾結束時)返回-1,文件有多個字符就要用到循環(huán)
            // 如果文件是空的,上來就是-1,所以先要做判斷,并且有好多字符要讀,用while循環(huán)
        /*while (data != -1) {
            // 以字符形式輸出每個字符
            System.out.print((char) data);
            // 再讀一個看看是不是-1
            data = fr.read();//像迭代器一樣
        }*/
            // 方式二: 把方法直接寫到循環(huán)體表達式匯總
            int data;
            while ((data = fr.read()) != -1) {
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 4.手動關閉流的操作,防止內存泄露
        /*try {
            // 假如文件流對象沒有實例化出現(xiàn)了異常,這里關閉會出現(xiàn)空指針異常,所以造了對象才要關閉
            if (fr != null)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        // 或
        if (fr != null) {
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • FileReader使用read(char[ ] cbuf)讀入數(shù)據(jù)
// 對read()操作升級: 使用read的重載方法
    @Test
    public void testFileReader1() {
        FileReader fr = null;
        try {
            // 1.File類的實例化(創(chuàng)建文件)
            File file = new File("hello.txt");
            // 2.FileReader流的實例化(創(chuàng)建讀取文件的流對象)
            fr = new FileReader(file);
            // 3.讀入的操作
            // read(char[] cubf): 返回每次到底寫入cbuf數(shù)組中的字符的個數(shù).如果達到文件末尾,返回-1
            // 先創(chuàng)建一個數(shù)組用來緩存要讀數(shù)據(jù)的個數(shù)
            char[] cbuf = new char[5];// 可以存放5個字符的數(shù)組
            int len;// 定義每次讀數(shù)據(jù)的個數(shù)
            // 判斷每次讀數(shù)據(jù)的個數(shù),并且每讀一次數(shù)據(jù)都會覆蓋一次數(shù)組,可以理解為數(shù)組元素的替換
            while ((len = fr.read(cbuf)) != -1) {
                // 如果遍歷的長度為cbuf.length,輸出的結果就是123ld,因為最后一次只有3個字符,無法完全覆蓋上一次 最后2個字符就留下了,所以不能是
                // 方式一:
                // 錯誤的寫法
            /*for (int i = 0; i < cbuf.length; i++) {

            }*/
                // 正確寫法: 每次讀進去幾個就遍歷幾個,不要過多的取后面的
                /*for (int i = 0; i < len; i++) {
                    System.out.print(cbuf[i]);
                }*/
                // 方式二:
                // 錯誤,對應著方式一的錯誤寫法
                // 這里cbuf第三次讀取還是保留最后的ld的,相當于數(shù)組有什么就全取出來了,其實跟cbuf.length一樣
                /*String str = new String(cbuf);// char型數(shù)組轉成String型數(shù)組
                System.out.print(str);*/
                // 正確寫法: 用String的重載構造器,從頭開始取,取到第len個
                String str = new String(cbuf, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally { // 寫在finally里防止try的時候return
            // 4.資源的關閉
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • FileWriter寫出數(shù)據(jù)的操作

從內存中寫出數(shù)據(jù)到硬盤的文件里
說明:
1.輸出操作,對應的File可以不存在的.
File對應的硬盤中的文件若不存在,在輸出過程中,會自動創(chuàng)建此文件
若存在:
如果流用的構造器是: FileWriter(file,false) / FileWriter(file): 會對原有文件進行覆蓋
如果流用的構造器是: FileWriter(file,true): 不會對原有文件覆蓋, 而是在原有文件基礎上追加內容

@Test
    public void testFileWriter() throws IOException {
        FileWriter fw = null;
        try {
            // 1.提供File類的對象,指明寫出的文件
            File file = new File("hello1.txt");
            // 2.提供FileWriter類(數(shù)據(jù)流)的對象,用于數(shù)據(jù)的寫出
            fw = new FileWriter(file, true);// 第二個參數(shù)的意思: 是否在原有文件上添加,表示對原有文件的覆蓋,默認為false
            // 3.寫出操作
            fw.write("have dream\n");
            fw.write("have dream");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                // 4.流資源關閉
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 用FileReader和FileWriter實現(xiàn)文本文件的復制
@Test
    public void testFileReaderFileWriter() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            // 1.創(chuàng)建File類的對象,指明讀取和寫出的文件
            // 不能用字符流處理圖片等字節(jié)數(shù)據(jù)
            File srcFile = new File("hello.txt");
            File destFile = new File("hello2.txt");
            // 2.創(chuàng)建輸入流和輸出流的對象
            fr = new FileReader(srcFile);// 對于輸入流,文件一定要存在
            fw = new FileWriter(destFile);// 文件可以不存在
            // 3.讀入內存和寫出硬盤操作
            // 一次讀多個先創(chuàng)建一個數(shù)組
            char[] cbuf = new char[5];
            int len;// 記錄每次讀入到cbuf數(shù)組中字符的個數(shù)
            // 循環(huán)讀入: fr流對象讀入到cbuf數(shù)組返回讀入了幾個 如果不是-1就還有數(shù)據(jù)
            while ((len = fr.read(cbuf)) != -1) {
                // 把數(shù)據(jù)寫出到硬盤當中
                // 錯誤:若這樣寫 每次5個5個就把數(shù)據(jù)讀出來了
                // fw.write(cbuf);
                // 正確: 讀進去幾個就寫出幾個
                fw.write(cbuf, 0, len);// 每次從0開始寫出len個字符
                // 循環(huán)結束返回-1
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            // 4.關閉流資源,建議從下往上關
            // 兩個操作并列寫就可以了(也可以用finally),因為就算中途出現(xiàn)異常也已經(jīng)catch掉了,不影響try以外的代碼運行,try里面代碼出現(xiàn)異常,內部接著往下的才不執(zhí)行
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 字符流不能處理圖片文件的測試

  • 用FileInputStream不能讀取文本文件的測試

  • 用FileInputStream和FileOutputStream讀寫非文本文件

  • 用FileInputStream和FileOutputStream復制文件的測試

13.4.緩沖流

  • 緩沖流(字節(jié)型)實現(xiàn)非文本文件的復制

13.5.轉換流

  • 轉換流概述與InputStreamReader的使用

  • 轉換流實現(xiàn)文件的讀入和寫出

13.6.標準輸入輸出流

13.7.打印流

13.8.數(shù)據(jù)流

13.9.對象流

image.png
image.png
  • 對象流序列化與反序列化字符串操作

對象流的使用
1.ObjectInputStream 和 ObjectOutputStream
2.作用:用于存儲和讀取基本數(shù)據(jù)類型數(shù)據(jù)或對象的處理流逼龟。他的強大之處就是可以把Java中的對象寫入到數(shù)據(jù)源中,也能把對象從數(shù)據(jù)源中還原回來
3.要想一個java對象是可序列化的垃它,需要滿足相應的要求。見Person.java

public class ObjectInputOutputStreamTest {
    /*
    序列化過程:將內存中的java對象保存到磁盤中或通過網(wǎng)絡傳輸出去
    使用ObjectOutPutStream輸出實現(xiàn)
     */
    @Test
    public void testObjectOutputStream(){
        ObjectOutputStream oos = null;
        try {
            // 1.造一個對象處理流包住一個節(jié)點流,造文件和流寫在一起
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            // 2.寫出到磁盤的對象
            // 一開始內存當中有個對象就是這個String,隨時可能會被回收,就把他持久化保存起來,
            // 或者可以不生成文件,通過網(wǎng)絡把它傳出去也行,傳出去以后再另外一端又可以把它還原成字符串
            oos.writeObject(new String("我愛天安門"));
            // 顯式的刷新操作
            oos.flush();
            oos.writeObject(new Person("王敏", 23));// 被持久化到Object.dat文件里
            oos.flush();
            // 序列化自定義類,該類的屬性也全都要可序列化
            oos.writeObject(new Person("張帥", 21,1001,new Account(5000)));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (oos != null) {
                // 3.流關閉
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /*
    反序列化過程: 將磁盤文件中的對象還原為內存中的一個java對象,或通過網(wǎng)絡方式獲取到流,把網(wǎng)絡中的流的數(shù)據(jù)還原為java層面的對象
    使用ObjectInputStream來實現(xiàn)
     */
    @Test
    public void testInputStream(){
        ObjectInputStream ois = null;
        try {
            // 1.造文件和流對象
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            // 2.寫出磁盤操作,一般寫入的都是同一個類型的
            Object obj = ois.readObject();// 通常往里放的都是同類型的對象
            String str = (String) obj;// 這個對象其實是個字符串所以可以強轉
            Person p = (Person) ois.readObject();
            Person p1 = (Person) ois.readObject();
            // 還原為內存層面
            System.out.println(str);
            System.out.println(p);
            System.out.println(p1);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            // 3.流關閉
            try {
                if (ois != null)
                    ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Person類要滿足如下的需求,方可序列化
1.要實現(xiàn)標識接口: Serializable
2.當前類要提供一個全局常量: serialVersionUID(版本序列號)
如果不添加這個全局常量,給這個類的對象序列化了,存儲在磁盤中,緊接著對Person類修改了,修改后,自動生成的serialVersionUID就變了,
變了再去還原的話就找不到當初序列化的全局常量對應的Person,在還原時候就出問題了(報異常)
3.除了當前Person類需要實現(xiàn)Serializable接口之外,還必須保證其內部所有屬性也必須是可序列化的弱判。(默認情況下岔乔,基本數(shù)據(jù)類型是可序列化的)
補充: ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變量
static屬于類的資源不歸對象所有所以不能序列化琉苇,transient是瞬態(tài)的
transient:被修飾的成員屬性變量不能被序列化
4.對象序列化機制允許把內存中的Java對象轉換成平臺無關的二進制流匕垫,
從而允許把這種二進制流持久地保存在磁盤上狰腌,或通過網(wǎng)絡將這種二進制流傳輸?shù)搅硪粋€網(wǎng)絡節(jié)點除破。
當其它程序獲取了這種二進制流,就可以恢復成原來的Java對象

public class Person implements Serializable {
    public static final long serialVersionUID = 451615182L;
    private static String name;
    private transient int age;
    private int id;
    private Account acct;// 自定義類屬性也要是可序列化的,
    public Person(String name, int age, int id, Account acct) {
        this.name = name;
        this.age = age;
        this.id = id;
        this.acct = acct;
    }

    public Person(String name, int age, Account acct) {
        this.name = name;
        this.age = age;
        this.acct = acct;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", acct=" + acct +
                '}';
    }
}
class Account implements Serializable{
    // 加上唯一的全局靜態(tài)常量避免反序列化報異常
    public static final long serialVersionUID = 4515182L;
    private double balance;
    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }
}

13.10.隨機存取文件流

RandomAccessFile的使用
1.RandomAccessFile直接繼承于java.Lang.Object類琼腔,實現(xiàn)了DataInput和DataOutput接口
2.RandomAccessFile既可以作為一個輸入流,又可以作為一個輸出流
3.如果RandomAccessFile作為輸出流時,寫出到的文件若不存在,則在執(zhí)行過程中自動創(chuàng)建
若寫出到的文件存在,則會對原有文件內容進行覆蓋.(默認情況下,從頭覆蓋,能覆蓋多少算多少)
4.可以通過把指定指針位置后的內容緩存起來,然后再在指定指針位置插入新值,再把緩存的內容追加回原來的文件,實現(xiàn)RandomAccessFile"插入"數(shù)據(jù)的效果

public class RandomAccessFileTest {
    @Test
    public void test11() throws FileNotFoundException {
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            // 1.造流的對象
            raf1 = new RandomAccessFile(new File("pic.jpg"), "r");// 只讀模式
            raf2 = new RandomAccessFile(new File("pic3.jpg"), "rw");// 可讀可寫模式
            // 2.讀入寫出操作
            byte[] buffer = new byte[1024];
            int len;
            while ((len = raf1.read(buffer)) != -1) {
                raf2.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 3.流關閉
            if (raf2 != null) {
                raf2.close();
            }
            if (raf1 != null) {
                raf1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void test2() throws IOException {
        // 創(chuàng)建寫出流的對象和文件對象
        RandomAccessFile raf1 = new RandomAccessFile("hello4.txt", "rw");
        // 寫出操作
        raf1.seek(3);// 將指針調到角標為3的位置
        raf1.write("xyz".getBytes());// 覆蓋掉原來文件里的頭三個字符
        // 流關閉
        raf1.close();
    }
    /*
    用RandomAccessFile實現(xiàn)數(shù)據(jù)的插入效果
     */
    @Test
    public void test3() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("hello4.txt", "rw");
        raf1.seek(3);// 將指針調到下標為3的位置
        // 將讀取的數(shù)據(jù)存入一個數(shù)組,將數(shù)組長度先設置為文件長度的大小避免擴容,提高效率,length()返回一個long類型的值
        // 保存指針角標3后面的所有數(shù)據(jù)到StringBuilder中
        StringBuilder builder = new StringBuilder((int) new File("hello4.txt").length());//新造數(shù)組的大小要么比原文件小,要么和源文件一樣大
        // 讀取操作
        byte[] buffer = new byte[20];
        int len;
        while ((len = raf1.read(buffer)) != -1) {
            // 把每次遍歷的字符放入builder數(shù)組中
            builder.append(new String(buffer, 0, len));
        }
        // 此時指針自動跑到最后了,將指針調回角標為3的位置
        raf1.seek(3);
        // 插入"xyz"的數(shù)據(jù),相當于對原有內容進行覆蓋
        raf1.write("xyz".getBytes());// 這里write返回byte[]類型,所以要用getBytes()
        // 寫出后不用再調指針了,指針已經(jīng)在z的后面了
        // 將builder中的數(shù)據(jù)寫入到文件中
        raf1.write(builder.toString().getBytes());
        // 關閉流
        raf1.close();
    }
}

13.11.NIO.2中Path,Paths,Files類的使用

  • 用第三方jar包實現(xiàn)數(shù)據(jù)讀寫

14.1.網(wǎng)絡編程概述

14.2.網(wǎng)絡通信要素概述

14.3.通信要素1: IP和端口號

  • 端口號的理解
image.png
public class InetAddressTest {
    public static void main(String[] args) {
        // 創(chuàng)建一個對象,其對應的ip就是方法的參數(shù)
        // 類似于File file = new File("hello.txt");
        // 內存中的file對象對應著hello.txt路徑的文件
        try {
            InetAddress inet1 = InetAddress.getByName("192.168.10.14");// 參數(shù)host代表主機名
            System.out.println(inet1);
            InetAddress inet2 = InetAddress.getByName("www.taobao.com");
            System.out.println(inet2);
            InetAddress inet3 = InetAddress.getByName("127.0.0.1");
            System.out.println(inet3);
            // 直接獲取本地IP地址的方法
            InetAddress inet4 = InetAddress.getLocalHost();
            System.out.println(inet4);
            // getHostName(): 獲取域名
            System.out.println(inet2.getHostName());
            // getHostAddress(): 獲取主機地址
            System.out.println(inet2.getHostAddress());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

14.4.通信要素2: 網(wǎng)絡協(xié)議

  • TCP和UDP網(wǎng)絡通信協(xié)議的對比
  • 三次握手: 應該這樣理解:1.A發(fā)送請求 2.B告訴A已經(jīng)收到請求(ACK確認)3.A確認B收到了A的請求 4.A開始數(shù)據(jù)傳輸

14.5.TCP網(wǎng)絡編程

  • TCP網(wǎng)絡編程例題:

14.6.udp網(wǎng)絡編程

  • UDP編程舉例

14.7.url編程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末瑰枫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丹莲,更是在濱河造成了極大的恐慌光坝,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甥材,死亡現(xiàn)場離奇詭異盯另,居然都是意外死亡,警方通過查閱死者的電腦和手機洲赵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門鸳惯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人板鬓,你說我怎么就攤上這事悲敷。” “怎么了俭令?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵后德,是天一觀的道長。 經(jīng)常有香客問我抄腔,道長瓢湃,這世上最難降的妖魔是什么理张? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮绵患,結果婚禮上雾叭,老公的妹妹穿的比我還像新娘。我一直安慰自己落蝙,他們只是感情好织狐,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筏勒,像睡著了一般移迫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上管行,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天厨埋,我揣著相機與錄音,去河邊找鬼捐顷。 笑死荡陷,一個胖子當著我的面吹牛,可吹牛的內容都是我干的迅涮。 我是一名探鬼主播废赞,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逗柴!你這毒婦竟也來了蛹头?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤戏溺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屠尊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旷祸,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年讼昆,在試婚紗的時候發(fā)現(xiàn)自己被綠了托享。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡浸赫,死狀恐怖闰围,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情既峡,我是刑警寧澤羡榴,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站运敢,受9級特大地震影響校仑,放射性物質發(fā)生泄漏忠售。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一迄沫、第九天 我趴在偏房一處隱蔽的房頂上張望稻扬。 院中可真熱鬧,春花似錦羊瘩、人聲如沸泰佳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逝她。三九已至,卻和暖如春摇予,著一層夾襖步出監(jiān)牢的瞬間汽绢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工侧戴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宁昭,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓酗宋,卻偏偏與公主長得像积仗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蜕猫,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容