主頁 > 後端開發 > Java學習-第一部分-第二階段-第八節:IO流

Java學習-第一部分-第二階段-第八節:IO流

2022-09-06 08:36:43 後端開發

IO流

筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

IO流體系圖

image

檔案

什么是檔案

檔案.對我們并不陌生,檔案是保存資料的地方,比如大家經常使用的word檔案,txt檔案.excel檔案...都是檔案,它既可以保存一張圖片,也可以保持視頻,聲音.…

檔案流-File()

檔案在程式中是以流的形式來操作的

image

流:資料在資料源(檔案)和程式(記憶體)之間經歷的路徑

輸入流:資料從資料源(檔案)到程式(記憶體)的路徑

輸出流:資料從程式(記憶體)到資料源(檔案)的路徑

創建檔案物件相關構造器和方法

相關方法

new File(String pathname)//根據路徑構建一個File物件

new File(File parent,String child)//根據父目錄檔案+子路徑構建

new File(String parent,String child)//根據父目錄+子路徑構建

createNewFile 創建新檔案

創建檔案物件相關構造器和方法

應用案例演示FileCreate.java

請在D盤下,創建檔案news1.txt、news2.txt、news3.txt,用三種不同方式創建

//方式1 new File(String pathname)
public void create01() {
    String filePath = "d:\\news1.txt";
    File file = new File(filePath);
    try {
        file.createNewFile();
        System.out.println("檔案創建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//方式2 new File(File parent , String child)//根據父目錄檔案+子路徑構建
// d:\\news2.txt
public void create02() {
    File parentFile = new File("d:\\");
    String fileName = "news2.txt";
    //這里的file物件,在java程式中,只是一個物件
    //只有執行了createNewFile 方法,才會真正的,在磁盤創建該檔案
    File file = new File(parentFile, fileName);
    try {
        file.createNewFile();
        System.out.println("創建成功~");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//方式3 new File(String parent , String child)
// 根據父目錄+子路徑構建
public void creat03() {
    // String parentPath = "D:\\";
    String parentPath = "D:/";//兩種路徑方式都行
    String fileName = "news4.txt";
    File file = new File(parentPath, fileName);
    try {
        file.createNewFile();
        System.out.println("創建成功~");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

獲取檔案的相關資訊

getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory

//先創建檔案物件
File file = new File("D:\\NEW\\news1.txt");
try {
    file.createNewFile();
    System.out.println("檔案創建成功");
} catch (IOException e) {
    e.printStackTrace();
}
//呼叫相應的方法,得到對應資訊
System.out.println("檔案名字=" + file.getName());
//getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
System.out.println("檔案絕對路徑=" + file.getAbsolutePath());
System.out.println("檔案父級目錄=" + file.getParent());
System.out.println("檔案大小(位元組)=" + file.length());
System.out.println("檔案是否存在=" + file.exists());//T
System.out.println("是不是一個檔案=" + file.isFile());//T
System.out.println("是不是一個目錄=" + file.isDirectory());//F

目錄的操作和檔案洗掉

mkdir創建一級目錄、mkdirs創建多級目錄、delete洗掉空目錄或檔案

應用案例演示

  1. 判斷d:\\news1.txt是否存在,如果存在就洗掉

    //判斷 d:\\news1.txt是否存在,如果存在就洗掉
    String filePath = "d:\\news1.txt";
    File file = new File(filePath);
    if (file.exists()) {
        if (file.delete()) {//洗掉檔案
            System.out.println(filePath + "洗掉成功");
        } else {
            System.out.println(filePath + "洗掉失敗");
        }
    } else {
        System.out.println("該檔案不存在...");
    }
    
  2. 判斷D:\\demo02是否存在,存在就洗掉,否則提示不存在.

    //判斷D:\\demo02是否存在,存在就洗掉,否則提示不存在.
    //這里我們需要體會到,在java編程中,目錄也被當做一種特殊的檔案
    String filePath = "d:\\demo02";
    File file = new File(filePath);
    if (file.exists()) {
        if (file.delete()) {//洗掉目錄
            System.out.println(filePath + "洗掉成功");
        } else {
            System.out.println(filePath + "洗掉失敗");
        }
    } else {
        System.out.println("該目錄不存在...");
    }
    
  3. 判斷D:\\demo\\a\\b\\c目錄是否存在,如果存在就提示已經存在,否則就創建

    //判斷D:\\demo\\a\\b\\c目錄是否存在,如果存在就提示已經存在,否則就創建
    String filePath = "D:\\demo\\a\\b\\c";
    File file = new File(filePath);
    if (file.exists()) {
            System.out.println(filePath + "已存在");
    } else {
        if (file.mkdirs()){//創建一級目錄使用mkdir(),創建多級目錄使用mkdirs()
            System.out.println("目錄創建成功");
        }else {
            System.out.println("目錄創建失敗");
        }
    }
    

IO流原理及流的分類

Java IO流原理

  1. I/O是Input/Output的縮寫,I/O技術是非常實用的技術,用于處理資料傳輸,如讀/寫檔案,網路通訊等,

  2. Java程式中,對于資料的輸入/輸出操作以”流(stream)”的方式進行,

  3. java.io包下提供了各種“流”類和介面,用以獲取不同種類的資料,并通過方法輸入或輸出資料

  4. 輸入input:讀取外部資料(磁盤、光碟等存盤設備的資料)到程式(記憶體)中,

  5. 輸出output:將程式(記憶體)資料輸出到磁盤、光碟等存盤設備中

流的分類

√按操作資料單位不同分為:位元組流(8 bit)二進制檔案,字符流(按字符)文本檔案

√按資料流的流向不同分為:輸入流,輸出流

√按流的角色的不同分為:節點流,處理流/包裝流

(抽象基類) 位元組流 字符流
輸入流 lnputStream Reader
輸出流 OutputStream Writer
  1. Java的lO流共涉及40多個類,實際上非常規則,都是從如上4個抽象基類派生的
  2. 由這四個類派生出來的子類名稱都是以其父類名作為子類名后綴,

節點流和處理流

●基本介紹

  1. 節點流可以從一個特定的資料源讀寫資料,如FileReader、 FileWriter [原始碼]

  2. 處理流(也叫包裝流)是“連接”在已存在的流(節點流或處理流)之上,為程式提供更為強大的讀寫功能,如BufferedReader、BufferedWriter [原始碼]

img

節點流和處理流的區別和聯系

  1. 節點流是底層流/低級流,直接跟資料源相接,
  2. 處理流(包裝流)包裝節點流,既可以消除不同節點流的實作差異,也可以提供更方便的方法來完成輸入輸出,[原始碼理解]
  3. 處理流(也叫包裝流)對節點流進行包裝,使用了修飾器設計模式,不會直接與資料源相連[模擬修飾器設計模式]

處理流的功能主要體現在以下兩個方面:

  1. 性能的提高:主要以增加緩沖的方式來提高輸入輸出的效率,
  2. 操作的便捷:處理流可能提供了一系列便捷的方法來一次輸入輸出大批量的資料,使用更加靈活方便

標準輸入輸出流

>介紹

編譯型別 運行型別 默認設備
System.in標準輸入 InputStream BufferedInputStream 鍵盤
System.out標準輸出 PrintStream PrintStream 顯示幕

輸入流

lnputStream

image

FilelnputStream

構造方法摘要
FileInputStream(File file)通過打開與實際檔案的連接創建一個 FileInputStream ,該檔案由檔案系統中的 File物件 file命名,
FileInputStream(FileDescriptor fdObj)創建 FileInputStream通過使用檔案描述符 fdObj ,其表示在檔案系統中的現有連接到一個實際的檔案,
FileInputStream(String name)通過打開與實際檔案的連接來創建一個 FileInputStream ,該檔案由檔案系統中的路徑名 name命名,
Modifier and Type 方法摘要 Method and Description
int available()回傳從此輸入流中可以讀取(或跳過)的剩余位元組數的估計值,而不會被下一次呼叫此輸入流的方法阻塞,
void close()關閉此檔案輸入流并釋放與流相關聯的任何系統資源,
protected void finalize()確保當這個檔案輸入流的 close方法沒有更多的參考時被呼叫,
FileChannel getChannel()回傳與此檔案輸入流相關聯的唯一的FileChannel物件,
FileDescriptor getFD()回傳表示與此 FileInputStream正在使用的檔案系統中實際檔案的連接的 FileDescriptor物件,
int read()從該輸入流讀取一個位元組的資料,
int read(byte[] b)從該輸入流讀取最多 b.length個位元組的資料為位元組陣列,
int read(byte[] b, int off, int len)從該輸入流讀取最多 len位元組的資料為位元組陣列,
long skip(long n)跳過并從輸入流中丟棄 n位元組的資料,

FilelnputStream應用實體

要求:請使用FilelnputStream 讀取 hello.txt 檔案,并將檔案內容顯示到控制臺.

//單個位元組讀取,效率比較低

String filePath="d:\\hello.txt";
int readData=https://www.cnblogs.com/wenjie2000/archive/2022/09/05/0;
FileInputStream fileInputStream=null;
try {
    //創建FileInputstream物件,用于讀取檔案
    fileInputStream=new FileInputStream(filePath);
    //從該輸入流讀取一個位元組的資料,如果沒有輸入可用,此方法將阻止,
    // 如果回傳-1,表示讀取完畢
    while ((readData=fileInputStream.read())!=-1){
        System.out.print((char)readData);//轉成char顯示
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //關閉檔案流釋放資源
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//相對于上面代碼,從read()改為read(byte[] b),一次讀多個位元組,效率提高

String filePath="d:\\hello.txt";
int readLen=0;
//位元組陣列
byte[] buf = new byte[8];//一次讀取8個位元組.
        FileInputStream fileInputStream=null;
try {
    //創建FileInputstream物件,用于讀取檔案
    fileInputStream=new FileInputStream(filePath);
    //從該輸入流讀取最多b.length位元組的資料到位元組陣列, 此方法將阻塞,直到某些輸入可用,
    //如果回傳-1 ,表示讀取宗華
    //如果讀取正常,回傳實際讀取的位元組數
    while ((readLen=fileInputStream.read(buf))!=-1){
        System.out.print(new String(buf,0,readLen));//轉成char顯示
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //關閉檔案流釋放資源
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedInputStream

略,看BufferedOutputStream部分筆記

objectlnputStream

看一個需求

  1. 將int num = 100這個int資料保存到檔案中,注意不是100數字,而是int 100,并且,能夠從檔案中直接恢復int 100
  2. 將Dog dog = new Dog(“小黃”,3)這個dog物件保存到檔案中,并且能夠從檔案恢復.
  3. 上面的要求,就是能夠將基本資料型別或者物件進行序列化和反序列化操作

序列化和反序列化

  1. 序列化就是在保存資料時,保存資料的值和資料型別

  2. 反序列化就是在恢復資料時,恢復資料的值和資料型別

  3. 需要讓某個物件支持序列化機制,則必須讓其類是可序列化的,為了讓某個類是可序列化的該類必須實作如下兩個介面之一:

    >Serializable //這是一個標記介面,沒有方法 (推薦使用)

    >Externalizable //該介面有方法需要實作,因此我們一般實作上面的 Serializable介面

基本介紹

  1. 功能:提供了對基本型別或物件型別的序列化和反序列化的方法
  2. ObjectOutputStream提供序列化功能
  3. ObjectlnputStream提供反序列化功能

應用案例

  1. 使用ObjectlnputStream 讀取 data.dat并反序列化恢復資料 (如果需要data.dat,可運行下方ObjectOutputStream部分的應用案例1的代碼)

    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            //指定反序列化的檔案
            String filePath = "d:\\data.dat";
    
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
    
            //讀取
            // 解讀
            //1.讀取(反序列化)的順序需要和你保存資料(序列化)的順序一致
            //2.否則會出現例外
            System.out.println(ois.readInt());
            System.out.println(ois.readBoolean());
            System.out.println(ois.readChar());
            System.out.println(ois.readDouble());
            System.out.println(ois.readUTF());
    
            //dog的編譯型別是 Object , dog的運行型別是Dog
            Object dog = ois.readObject();
            System.out.println("運行型別=" + dog.getClass());
            System.out.println("dog資訊=" + dog);//底層 Object -> Dog
            //這里是特別重要的細節:
            //1.如果我們希望呼叫Dog的方法,需要向下轉型
            //2.需要我們將Dog類的定義,放到可以參考的位置(Dog類保存和讀取檔案時該類的位置必須一致)
            Dog dog2 = (Dog) dog;
            System.out.println(dog2.getName());//旺財..
            //關閉流,關閉外層流即可,底層會關閉 FileInputStream 流
            ois.close();
        }
    }
    
    class Dog implements Serializable {
        private String name;
        private int age;
    
        public Dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

注意事項和細節說明

  1. 讀寫順序要一致
  2. 要求序列化或反序列化物件,需要實作Serializable
  3. 序列化的類中建議添加SerialVersionUID,為了提高版本的兼容性(private static final long erialVersionUID = 1L;//當類發生修改后會序列化與反序列化被認定是類的版本修改,而不會認為是一個新的類)
  4. 序列化物件時,默認將里面所有屬性都進行序列化,但除了static或transient修飾的成員
  5. 序列化物件時,要求里面屬性的型別也需要實作序列化介面
  6. 序列化具備可繼承性,也就是如果某類已經實作了序列化,則它的所有子類也已經默認實作了序列化

Reader

FileReader

image

FileReader相關方法:

  1. new FileReader(File/String)
  2. read:每次讀取單個字符,回傳該字符,如果到檔案末尾回傳-1
  3. read(char[]):批量讀取多個字符到陣列,回傳讀取到的字符數,如果到檔案末尾回傳-1

相關API:

  1. new String(char[]):將char[]轉換成String
  2. new String(char[],off,len):將char[]的指定部分轉換成String

應用案例

要求:

  1. 使用FileReader 從 story.txt 讀取內容,并顯示

    //使用read()
    String filePath="d:\\NEW\\story.txt";
    FileReader fileReader=null;
    int data=https://www.cnblogs.com/wenjie2000/archive/2022/09/05/0;
    try {
        fileReader=new FileReader(filePath);
        while ((data=fileReader.read())!=-1){
            System.out.print((char)data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //使用read(char[])
    String filePath="d:\\NEW\\story.txt";
    FileReader fileReader=null;
    char[] buf=new char[8];
    int len=0;
    try {
        fileReader=new FileReader(filePath);
        while ((len=fileReader.read(buf))!=-1){
            System.out.print(new String(buf,0,len));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

BufferedReader

應用案例

  1. 使用BufferedReader讀取文本檔案,并顯示在控制臺
public static void main(String[] args) throws IOException {
    String filePath = "D:\\a.txt";
    //創建bufferedReader
    BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
    //讀取
    String line;//按行讀取,效率高
    // 說明
    //1. bufferedReader.readLine()是按行讀取檔案
    //2. 當回傳null時,表示檔案讀取完畢
    while ((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
    }
    //關閉流,這里注意,只需要關閉BufferedReader ,因為底層會自動的去關閉節點流FileReader
    bufferedReader.close();
}

InputStreamReader

先看一個檔案亂碼問題,引出學習轉換流必要性

//讀取e: l\a.txt檔案到程式//思路
//1,創建字符輸入流 BufferedReader[處理流]
//2,使用 BufferedReader物件讀取a.txt
//3,默認情況下,讀取檔案是按照utf-8編碼
//如果檔案使用的其他編碼方式很可能出現亂碼 例如讀取到的內容:Hhello,worldba????漲??
String filePath = "d:\\a.txt";
BufferedReader br = new BufferedReader(new FileReader(filePath));
String s = br.readLine();
System.out.println("讀取到的內容:" + s);
br.close();

介紹

  1. InputStreamReader:Reader的子類,可以將InputStream(位元組流)包裝成(轉換)Reader(字符流)

  2. 當處理純文本資料時,如果使用字符流效率更高,并且可以有效解決中文問題,所以建議將位元組流轉換成字符流

  3. 可以在使用時指定編碼格式(比如utf-8, gbk , gb2312, ISO8859-1等)

應用案例

  1. 編程將位元組流FilelnputStream 包裝成(轉換成)字符流InputStreamReader,對檔案進行讀取(按照utf-8/gbk格式),進而再包裝成BufferedReader

    public static void main(String[] args) throws IOException {
        //演示使用InputStreamReader轉換流解決中文亂碼問題
        //將位元組流FileInputStream轉成字符流InputStreamReader,指定編碼 gbk/utf-8
        String filePath = "D:\\a.txt";//解讀
        //1,把FileInputStream轉成InputStreamReader
        //2,指定編碼gbk
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3,把InputStreamReader傳入 BufferedReader
        BufferedReader br = new BufferedReader(isr);
        //4,讀取
        String s = br.readLine();
        System.out.println("讀取內容=" + s);
        //5,關閉外層流
        br.close();
    }
    

輸出流

OutputStream

FileOutputStream

構造方法摘要
FileOutputStream(File file)創建檔案輸出流以寫入由指定的 File物件表示的檔案,
FileOutputStream(File file, boolean append)創建檔案輸出流以寫入由指定的 File物件表示的檔案,
FileOutputStream(FileDescriptor fdObj)創建檔案輸出流以寫入指定的檔案描述符,表示與檔案系統中實際檔案的現有連接,
FileOutputStream(String name)創建檔案輸出流以指定的名稱寫入檔案,
FileOutputStream(String name, boolean append)創建檔案輸出流以指定的名稱寫入檔案,
Modifier and Type 方法摘要 Method and Description
void close()關閉此檔案輸出流并釋放與此流相關聯的任何系統資源,
protected void finalize()清理與檔案的連接,并確保當沒有更多的參考此流時,將呼叫此檔案輸出流的 close方法,
FileChannel getChannel()回傳與此檔案輸出流相關聯的唯一的FileChannel物件,
FileDescriptor getFD()回傳與此流相關聯的檔案描述符,
void write(byte[] b)b.length個位元組從指定的位元組陣列寫入此檔案輸出流,
void write(byte[] b, int off, int len)len位元組從位于偏移量 off的指定位元組陣列寫入此檔案輸出流,
void write(int b)將指定的位元組寫入此檔案輸出流,

FileOutputStream應用實體1

要求:請使用FileOutputStream在a.txt檔案,中寫入“hello, world”.

[代碼演示],如果檔案不存在,會創建檔案(注意:前提是目錄已經存在.)

//創建FileOutPutStream物件
String filePath="D:\\a.txt";
FileOutputStream fileOutputStream=null;

try {
    //1. new FileOutputStream(filePath)創建方式,當寫入內容是,會覆寫原來的檔案內容
    //2. new FileOutputStream(filePath,true)創建方式,當寫入內容是,是追加到檔案后面
    fileOutputStream=new FileOutputStream(filePath);
    //寫入一個位元組
    fileOutputStream.write('H');
    //寫入字串
    String str="hello,world";
    //str.getBytes()可以把字串->位元組陣列
    fileOutputStream.write(str.getBytes());
    //write(byte[] b, int off, int len) 將 `len`位元組從位于偏移量 `off`的指定位元組陣列寫入此檔案輸出流,
    fileOutputStream.write("aba".getBytes(),1,2);

} catch (IOException e) {
    e.printStackTrace();
}finally {
    try {
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

FileOutputStream應用實體2

要求:編程完成圖片/音樂的拷貝.

FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;

String filepath1="d:\\(1).png";
String filepath2="d:\\NEW\\(1).png";

try {
    fileInputStream=new FileInputStream(filepath1);
    fileOutputStream=new FileOutputStream(filepath2,true);
    byte[] bytes = new byte[1000];
    while (fileInputStream.read(bytes)!=-1){
        fileOutputStream.write(bytes);
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    try {
        fileInputStream.close();
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedOutputStream

應用案例

要求:編程完成圖片/音樂的拷貝(要求使用Buffered..流).[代碼演示]

//可以完成二進制檔案拷貝
int stringLine;
String filePath1 = "D:\\(1).png";
String filePath2 = "D:\\(2).png";
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try {
    bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath1));
    bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath2,true));
    byte[] bytes = new byte[1024];
    while ((stringLine=bufferedInputStream.read(bytes))!=-1){
        bufferedOutputStream.write(bytes,0,stringLine);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        bufferedInputStream.close();
        bufferedOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

objectOutputStream

基本介紹看筆記上方objectlnputStream部分

應用案例

  1. 使用ObjectOutputStream序列化基本資料型別和一個 Dog物件(name, age),并保存到data.dat檔案中

    public class Test {
        public static void main(String[] args) throws IOException{
            //序列化后,保存的檔案格式,不是存文本,而是按照他的格式來保存
            String filePath = "d:\\data.dat" ;
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
            //序列化資料到 e:\data.dat
            oos.writeInt(100);// int -> Integer(實作了Serializable)
            oos.writeBoolean(true) ;// boolean -> Boolean(實作了 Serializable)
            oos.writeChar('a');// char -> Character〔實作了Serializable)
            oos.writeDouble(9.5);// double -> Double (實作了Serializable)
            oos.writeUTF("hello,worldd一二三");//String
            //保存一個dog物件
            oos.writeObject(new Dog("旺財",10));
            
            oos.close();
            System.out.println("資料保存完畢(序列化形式)");
        }
    }
    class Dog implements Serializable {
        private String name;
        private int age;
    
        public Dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

PrintStream

列印流只有輸出流,沒有輸入流

public static void main(String[] args) throws IOException {
    PrintStream out = System.out;
    //在默認情況下,PrintStream輸出資料的位置是標準輸出,即顯示幕
    /*
    public void print(String s) {
        if (s == null){
            s = "null";}
        write(s);
    }
    */
    out.print("john,hello");
    //因為print底層使用的是write,所以我們可以直接呼叫write進行列印/輸出
    out.write("你好".getBytes());
    out.close();

    //我們可以去修改列印流輸出的位置/設備//修改成到"d:\\f1.txt")
    //public static void setOut(PrintStream out) {
    //    checkIO();
    //    setOut0(out);// native方法,修改了out
    //}
    System.setOut(new PrintStream("d:\\f1.txt"));
    System.out.println("hello,world");
}

Writer

image

Writer下的所有類都是呼叫close()后才會將資料寫入到檔案

FileWriter

FileWriter常用方法

  1. new FileWriter(FiIe/String):覆寫模式,相當于流的指標在首端
  2. new FileWriter(File/String,true):追加模式,相當于流的指標在尾端
  3. write(int):寫入單個字符
  4. write(char[]):寫入指定陣列
  5. write(char[],off,len):寫入指定陣列的指定部分
  6. write (string):寫入整個字串
  7. write(string,off,len):寫入字串的指定部分

相關API:String類:toCharArray將String轉換成char[]

注意:

FileWriter使用后,必須要關閉(close)或重繪(flush),否則寫入不到指定的檔案!

案例

//創建FileOutPutStream物件
String filePath="D:\\a.txt";
FileWriter fileWriter=null;

try {
    fileWriter=new FileWriter(filePath);
    //1) write(int):寫入單個字符
    fileWriter.write('H');
    //2) write(char[]):寫入指定陣列
    char[] chars={'a','b','c','v'};
    fileWriter.write(chars);
    //3) write(char[],off,len):寫入指定陣列的指定部分
    fileWriter.write(chars,1,3);
    //4) write (string):寫入整個字串
    String str="hello,world";
    fileWriter.write(str);
    //5) write(string,off,len):寫入字串的指定部分
    fileWriter.write("aba",1,2);
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //對應FileWriter ,一定要關閉流,或者flush才能真正的把資料寫入到檔案
    //看原始碼就知道原因,
    try {
        fileWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedWriter

應用案例

  1. 使用BufferedWriter 將”hello”,寫入到檔案中

    public static void main(String[] args) throws IOException {
        String filePath = "D:\\b.txt";
        //創建bufferedWriter
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        bufferedWriter.write("hello");
        bufferedWriter.newLine();//插入一個和系統相關的換行
        bufferedWriter.write("hello,發的發斯蒂芬改");
        bufferedWriter.write("hello");
    
        //關閉流,這里注意,只需要關閉BufferedReader ,因為底層會自動的去關閉節點流FileWrite
        bufferedWriter.close();
    }
    
  2. 綜合使用BufferedReader 和 BufferedWriter完成文本檔案拷貝,注意檔案編碼

    //1.BufferedReader和 BufferedWriter是安裝字符操作
    //2.不要去操作二進制檔案,可能造成檔案損壞
    String stringLine;
    String filePath1 = "D:\\b.txt";
    String filePath2 = "D:\\b2.txt";
    BufferedReader bufferedReader = null;
    BufferedWriter bufferedWriter = null;
    try {
        bufferedReader = new BufferedReader(new FileReader(filePath1));
        bufferedWriter = new BufferedWriter(new FileWriter(filePath2,true));
        while ((stringLine=bufferedReader.readLine())!=null){
            bufferedWriter.write(stringLine);
            bufferedWriter.newLine();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bufferedReader.close();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

OutputStreamWriter

OutputStreamWriter:Writer的子類,實作將OutputStream(位元組流)包裝成Writer(字符流)

應用案例

  1. 編程將位元組流 FileOutputStream包裝成(轉換成)字符流OutputStreamWriter,對檔案進行寫入(按照gbk格式,可以指定其他,比如utf-8)

    public static void main(String[] args) throws IOException {
        String filePath = "D:\\ab.txt";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "utf-8");
        osw.write("hello一二三");
        //5.關閉外層流
        osw.close();//flush +關閉流,才會將資料寫入到檔案..
        System.out.println("檔案保存成功");
    }
    

PrintWriter

public static void main(String[] args) throws IOException {
    //PrintWriter printWriter = new PrintWriter(System.out);//輸出到顯示幕上
    PrintWriter printWriter = new PrintWriter(new FileWriter("d:\\f2.txt"));
    printWriter.print("hi,北京你好~~~~");
    printWriter.close();//flush +關閉流,才會將資料寫入到檔案..
}

Properties類

看一個需求

程式操作資料庫,需要獲取用戶名和密碼,不能將檔案寫死,就需要保存資料到組態檔,

如下一個組態檔mysql.properties

ip=192.168.0.13
user=root
pwd=12345

請問編程讀取ip、user 和pwd的值是多少

√分析

  1. 傳統的方法

    public static void main(String[] args) throws IOException {
        //讀取mysql.properties 檔案,并得到ip,user和 pwd
        BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));
        String line = "";
        while ((line = br.readLine()) != null) {//回圈讀取
            //比較麻煩
            String[] split = line.split("=");
            System.out.println(split[0] + "值是: " + split[1]);
        }
        br.close();
    }
    
  2. 使用Properties類可以方便實作

基本介紹

  1. 專門用于讀寫組態檔的集合類
    組態檔的格式:
    鍵=值
    鍵=值

  2. 注意:鍵值對不需要有空格,值不需要用引號一起來,默認型別是String

  3. Properties的常見方法

    load:加載組態檔的鍵值對到Properties物件

    list:將資料顯示到指定設備/流物件

    getProperty(key):根據鍵獲取值

    setProperty(key,value):設定鍵值對到Properties物件

    store:將Properties中的鍵值對存盤到組態檔,在idea中,保存資訊到組態檔,如果含有中文,會存盤為unicode碼

應用案例

  1. 使用Properties類完成對 mysql.properties的讀取,看代碼演示

    public static void main(String[] args) throws IOException {
        //使用Properties 類來讀取mysql. properties 檔案
        //1,創建Properties物件
        Properties properties = new Properties();//2,加載指定組態檔
        properties.load(new FileReader("src\\mysql.properties"));//3.把k-v顯示控制臺
        properties.list(System.out);//4,根據key 獲取對應的值
        String user = properties.getProperty("user");
        String pwd = properties.getProperty("pwd");
        System.out.println("用戶名=" + user);
        System.out.println("密碼是=" + pwd);
    }
    
  2. 使用Properties類添加key-val 到新檔案mysql2.properties中

    public static void main(String[] args) throws IOException {
        //使用Properties類來創建組態檔,修改組態檔內容
        Properties properties = new Properties();
        //創建
        properties.setProperty("charset", "utf8");
        properties.setProperty("user", "湯姆");//注意保存時,是中文的 unicode碼值
        properties.setProperty("pwd" , "abc111");
    
        //將k-v存盤檔案中即可
        properties.store(new FileOutputStream("src\\mysql2.properties"), null);//其中null可換為字串,為保存的properties檔案的頭部注釋
        System.out.println("保存組態檔成功~");
    }
    
  3. 使用Properties類完成對 mysql.properties的讀取,并修改某個key-val

    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileReader("src\\mysql2.properties"));
        properties.setProperty("user","1111222");
        properties.store(new FileWriter("src\\mysql2.properties"),null);
    }
    

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/504145.html

標籤:其他

上一篇:django的基本介紹與操作

下一篇:Python學習:基礎練習題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more