IO

IO結(jié)構(gòu)

IO流:用于處理設(shè)備上的數(shù)據(jù),即:InputStream在孝,OutputStream

IO流的具體分類:
1,根據(jù)處理的數(shù)據(jù)類型不同分為:字節(jié)流與字符流
2,根據(jù)流的方向不同分為:輸出流與輸入流

字符流的由來(lái):
因?yàn)槲募木幋a不同蕊唐,而有了對(duì)字符進(jìn)行高效操作的字符流對(duì)象
原理:其實(shí)就是基于字節(jié)流讀取數(shù)據(jù)時(shí),去查了 指定編碼表

字節(jié)流與字符流的區(qū)別
1烁设,字節(jié)流讀取的 時(shí)候替梨,讀取一個(gè)字節(jié)就返回一個(gè)字節(jié),
字符流使用了字節(jié)流讀取到一個(gè)或多個(gè)字節(jié)流時(shí)署尤,先去查指定的編碼 表耙替,將查到的字符返回
2,字節(jié)流能夠讀取所有的類型數(shù)據(jù)曹体,而字符流只能處理字符類型

一.File

  • 目錄列表
    假設(shè)我們想查看目錄列表俗扇,可使用list()方法查看File對(duì)象下所有的目錄,但是如果想查看類型為.java類的文件箕别,那么我們就使用“目錄過(guò)濾器”
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
public class DirList {
    public static void main(String[] args) {
        File file = new File(".");
        String[] list;
        list = file.list(new DirFilter(".*"));
        Arrays.sort(list,String.CASE_INSENSITIVE_ORDER);
        for(String str : list){
            System.out.println(str);
        }
    }
}
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
public class DirFilter implements FilenameFilter{
    private Pattern pattern;
    public DirFilter(String filenName){
        pattern = Pattern.compile(filenName);
    }
    @Override
    public boolean accept(File dir, String name) {
        return pattern.matcher(name).matches();
    }
}

DirFilter 這個(gè)類存在的原因就是把a(bǔ)ccept() 方法提供給 list() 使用铜幽,使list()可以回調(diào)accept() 進(jìn)而決定哪些文件包含在列表里 這就是策略模式的體現(xiàn)
list()方法會(huì)為此目錄下的所有的方法都調(diào)用accept()方法,來(lái)判斷此文件是否在內(nèi)

  • 目錄的檢查及創(chuàng)建
    File 類不僅僅只代表存在的目錄串稀,也可以用File對(duì)象來(lái)創(chuàng)建不存在的目錄除抛,也可以用File查看文件的各種特性

輸入流 InputStream

InputStream

每一種數(shù)據(jù)源都有相應(yīng)的InputStream子類,因?yàn)镮nputStream是個(gè)處于頂層的類母截,用來(lái)處理各種數(shù)據(jù)源的類都繼承了InputStream類到忽,我們來(lái)看看這些類:
ByteArrayInputStream:處理字節(jié)數(shù)組的類,允許將內(nèi)存的緩沖區(qū)當(dāng)做InputStream使用清寇。
StringBufferInputStream:將String轉(zhuǎn)換成InputStream喘漏,內(nèi)部實(shí)現(xiàn)用的是StringBuffer。
FileInputStream:從文件中讀取數(shù)據(jù)华烟。
PipedInputStream:用于從管道中讀取數(shù)據(jù)翩迈。
SequenceInputStream:將多個(gè)流對(duì)象轉(zhuǎn)化成一個(gè)InputStream。
FilterInputStream:裝飾器類盔夜,為其它InputStream類提供功能负饲。

  • 讀取文件內(nèi)容
 package InputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedInputFile2 {
    public static String read(String fileName) throws IOException{
        BufferedReader br = new BufferedReader(new FileReader(fileName));
        StringBuilder sb =  new StringBuilder();
        String s = "";
        while((s = br.readLine())!=null){
            sb.append(s+"\n");
        }
        if(br!=null){
            br.close();
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        try {
    System.out.println(read("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
* DataInputStream類
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       DataInputStream input = new DataInputStream(new FileInputStream(file));
       char[] ch = new char[10];
       int count = 0;
       char temp;
       while((temp = input.readChar()) != 'C'){
           ch[count++] = temp;
       }
       System.out.println(ch);
    }
}

輸出流 OutputStream

outputstream

OutputStream 是所有的輸出字節(jié)流的父類堤魁,它是一個(gè)抽象類。
ByteArrayOutputStream返十、FileOutputStream是兩種基本的介質(zhì)流妥泉,它們分別向Byte 數(shù)組、和本地文件中寫入數(shù)據(jù)吧慢。PipedOutputStream 是向與其它線程共用的管道中寫入數(shù)據(jù)涛漂,
ObjectOutputStream 和所有FilterOutputStream的子類都是裝飾流。具體例子跟InputStream是對(duì)應(yīng)的检诗。

  • 文件復(fù)制
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       if(args.length!=2){
           System.out.println("命令行參數(shù)輸入有誤匈仗,請(qǐng)檢查");
           System.exit(1);
       }
       File file1=new File(args[0]);
       File file2=new File(args[1]);
       if(!file1.exists()){
           System.out.println("被復(fù)制的文件不存在");
           System.exit(1);
       }
       InputStream input=new FileInputStream(file1);
       OutputStream output=new FileOutputStream(file2);
       if((input!=null)&&(output!=null)){
           int temp=0;
           while((temp=input.read())!=(-1)){
                output.write(temp);
           }
       }
       input.close();
       output.close();
    }
}
* DataOutputStream
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       char[] ch = { 'A', 'B', 'C' };
       DataOutputStream out = null;
       out = new DataOutputStream(new FileOutputStream(file));
       for(char temp : ch){
           out.writeChar(temp);
       }
       out.close();
    }
}

添加屬性和有用的接口

java IO 類庫(kù)需要多種不同功能的組合,這正是使用裝飾器模式的理由所在
這也是java IO類庫(kù)里存在filter(過(guò)濾器)的原因所在逢慌,抽象類filter是所有裝飾器的基類悠轩。裝飾器類必須和它所裝飾的類具有相同的接口,但它也可以擴(kuò)展
裝飾器在給我們提供許多靈活性的時(shí)候也給我們帶來(lái)了復(fù)雜性攻泼,我們必須創(chuàng)建許多類 才能得到我們需要的單個(gè)的IO對(duì)象

Reader 和 Writer

Reader 是所有的輸入字符流的父類火架,它是一個(gè)抽象類。
Writer 是所有的輸出字符流的父類忙菠,它是一個(gè)抽象類
設(shè)計(jì)Reader和Writer主要是為了國(guó)際化何鸡,老的IO流僅支持8位的字節(jié)流,不能很好的支持16位的牛欢,所以添加Reader和Writer就是為了所有的IO操作中能很好地 支持Unicode
InputStreamReader 可以把 InputStream 轉(zhuǎn)化為 Reader
OutoutStreamWrite 可以把OutputStream轉(zhuǎn)化為Write

  • 從文件中讀取數(shù)據(jù)
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName="D:"+File.separator+"hello.txt";
       File f=new File(fileName);
       char[] ch=new char[100];
       Reader read=new FileReader(f);
       int temp=0;
       int count=0;
       while((temp=read.read())!=(-1)){
           ch[count++]=(char)temp;
       }
       read.close();
       System.out.println("內(nèi)容為"+new String(ch,0,count));
    }
}
  • BufferedReader
    注意:BufferedReader只能接受字符流的緩沖區(qū)骡男,因?yàn)槊恳粋€(gè)中文需要占據(jù)兩個(gè)字節(jié),所以需要將System.in這個(gè)字節(jié)輸入流變?yōu)樽址斎肓?/li>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferedReaderDemo{
   public static void main(String[] args){
       BufferedReader buf = new BufferedReader(
                newInputStreamReader(System.in));
       String str = null;
       System.out.println("請(qǐng)輸入內(nèi)容");
       try{
           str = buf.readLine();
       }catch(IOException e){
           e.printStackTrace();
       }
       System.out.println("你輸入的內(nèi)容是:" + str);
    }
}

字節(jié)流與字符流的轉(zhuǎn)換

InputStreamReader:字節(jié)到字符的橋梁
OutputStreamWriter:字符到字節(jié)的橋梁
這兩個(gè)流對(duì)象是字符體系中的成員傍睹,它們有轉(zhuǎn)換作用隔盛,本身又是字符流,所以在構(gòu)造的時(shí)候需要傳入字節(jié)流對(duì)象進(jìn)來(lái)拾稳。

//將字節(jié)輸出流轉(zhuǎn)化為字符輸出流
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Writer out=new OutputStreamWriter(new FileOutputStream(file));
       out.write("hello");
       out.close();
    }
//將字節(jié)輸入流變?yōu)樽址斎肓?import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Reader read=new InputStreamReader(new FileInputStream(file));
       char[] b=new char[100];
       int len=read.read(b);
       System.out.println(new String(b,0,len));
       read.close();
    }
}

標(biāo)準(zhǔn)IO流

標(biāo)準(zhǔn)IO模型吮炕,java提供了System.in,System.out,System.err
其中System.err和System.out都已報(bào)裝成了PrintStream 但是System.in
卻是一個(gè)未被報(bào)裝過(guò)的InputStream,所以在System.in之前要對(duì)其進(jìn)行包裝

package OutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Echo {
    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String c = "";
        try {
            while((c=reader.readLine())!=null&&c.length()!=0){
                System.out.println(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 將System.out 轉(zhuǎn)換為PrintWrite
    System.out 是一個(gè)PrintStream 而PrintStream 是一個(gè)OutputStream 而PrintWrite有一個(gè)可以接受OutputStream 參數(shù)的構(gòu)造器
PrintWriter out = new PrintWriter(System.out,true);
        out.println("hello ");

壓縮

  • 利用GZIP進(jìn)行簡(jiǎn)單的壓縮
    GZIP接口非常的簡(jiǎn)單,如果要對(duì)單個(gè)的數(shù)據(jù)流進(jìn)行壓縮访得,GZIP就很合適
package zip;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GIZPcomress {
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(
                    new FileReader(
                            "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            BufferedOutputStream os = new BufferedOutputStream(
                    new GZIPOutputStream(
                            new FileOutputStream(
                                    "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java")));
            System.out.println("write file");
            int c;
            while ((c = br.read()) != -1) {
                os.write(c);
            }
            br.close();
            os.close();
            System.out.println("read file");
            BufferedReader br2 = new BufferedReader(
                    new InputStreamReader(
                            new GZIPInputStream(
                                    new FileInputStream(
                                            "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java"))));
            String s = "";
            while ((s = br2.readLine()) != null) {
                System.out.println(s);
            }
        } catch (Exception e) { 
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
  • 用zip 進(jìn)行壓縮 解壓
package zip;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
//壓縮
public class ZipCompress {
    public static void main(String[] args) {
        try {
            FileOutputStream fos = new FileOutputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
            CheckedOutputStream cs = new CheckedOutputStream(fos, new Adler32());
            ZipOutputStream zs = new ZipOutputStream(fos);
            BufferedOutputStream bos = new BufferedOutputStream(zs);
            zs.setComment("this is zip file");
            System.out.println("開(kāi)始?jí)嚎s");
            BufferedReader reader = new BufferedReader(new FileReader("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            zs.putNextEntry(new ZipEntry("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            int s = 0;
            while((s=reader.read())!=-1){
                bos.write(s);
            }
            bos.close();
            System.out.println("checkNum:"+cs.getChecksum().getValue());
            System.out.println("開(kāi)始讀文件");
            FileInputStream fis = new FileInputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
            CheckedInputStream cis = new CheckedInputStream(fis, new Adler32());
            ZipInputStream zi = new ZipInputStream(fis);
            BufferedInputStream bis = new BufferedInputStream(zi);
            ZipEntry zn = null;
            while((zn = zi.getNextEntry())!=null){
                System.out.println("this file:"+zn);
                int n = 0;
                while((n = bis.read())!=-1){
                    System.out.write(n);
                }
            }
            System.out.println("checkNum:"+cs.getChecksum().getValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

序列化

Java平臺(tái)允許我們?cè)趦?nèi)存中創(chuàng)建可復(fù)用的Java對(duì)象龙亲,但一般情況下,只有當(dāng)JVM處于運(yùn)行時(shí)悍抑,這些對(duì)象才可能存在鳄炉,即,這些對(duì)象的生命周期不會(huì)比JVM的生命周期更長(zhǎng)传趾。但在現(xiàn)實(shí)應(yīng)用中迎膜,就可能要求在JVM停止運(yùn)行之后能夠保存(持久化)指定的對(duì)象泥技,并在將來(lái)重新讀取被保存的對(duì)象浆兰。Java對(duì)象序列化就能夠幫助我們實(shí)現(xiàn)該功能磕仅。java 的對(duì)象的序列化將那些實(shí)現(xiàn)了Serializable接口的對(duì)象轉(zhuǎn)換成字節(jié)序列,并且能夠在以后將字節(jié)序列恢復(fù)為原來(lái)的對(duì)象
什么時(shí)候用序列化:
a)當(dāng)你想把的內(nèi)存中的對(duì)象保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中時(shí)候;
b)當(dāng)你想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;
c)當(dāng)你想通過(guò)RMI傳輸對(duì)象的時(shí)候纱兑;

package Serializable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class A {
    private static int i = 10;
    private transient static String s = "java";
    public static void main(String[] args) {
        try {
            User user = new User();
            user.setSex('男');
            user.setUsername("小李");
            user.setUserpass("123");
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.out"));
            oos.writeObject(user);
            oos.close();
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.out"));
            User user2 = (User)ois.readObject();
            //String ss = ois.readUTF();
            //System.out.println(ss);
            System.out.println(user2.getUsername());
            System.out.println(user2.getSex());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
  • 序列化的控制
    有時(shí)候我們不想整個(gè)對(duì)象都序列化讼渊,只需要對(duì)象的一部分序列化,此時(shí)就應(yīng)該用到:Externalizable
    Externalizable 是一個(gè)接口 需要實(shí)現(xiàn)兩個(gè)方法writeExternal(),readExternal()
package Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Bilp1 implements Externalizable{
    private User user;
    public Bilp1(){
        System.out.println("Bilp1()");
    }
    public Bilp1(User user){
        this.user = user;
    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // TODO Auto-generated method stub
        //out.writeObject(user);
        System.out.println("writeExternal()");
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        // TODO Auto-generated method stub
        System.out.println("readExternal()");
    }
}
  • transient關(guān)鍵字
    當(dāng)某個(gè)字段被聲明為transient后肚医,默認(rèn)序列化機(jī)制就會(huì)忽略該字段。此處將User類中的username字段聲明為transient
private transient String username;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市两嘴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌族壳,老刑警劉巖憔辫,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仿荆,居然都是意外死亡贰您,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門拢操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锦亦,“玉大人,你說(shuō)我怎么就攤上這事令境「茉埃” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵展父,是天一觀的道長(zhǎng)返劲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)栖茉,這世上最難降的妖魔是什么篮绿? 我笑而不...
    開(kāi)封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吕漂,結(jié)果婚禮上亲配,老公的妹妹穿的比我還像新娘。我一直安慰自己惶凝,他們只是感情好吼虎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著苍鲜,像睡著了一般思灰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上混滔,一...
    開(kāi)封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天洒疚,我揣著相機(jī)與錄音歹颓,去河邊找鬼。 笑死油湖,一個(gè)胖子當(dāng)著我的面吹牛巍扛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乏德,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撤奸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了喊括?” 一聲冷哼從身側(cè)響起胧瓜,我...
    開(kāi)封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎郑什,沒(méi)想到半個(gè)月后贷痪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦误,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年劫拢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片强胰。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舱沧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出偶洋,到底是詐尸還是另有隱情熟吏,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布玄窝,位于F島的核電站牵寺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恩脂。R本人自食惡果不足惜帽氓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俩块。 院中可真熱鬧黎休,春花似錦、人聲如沸玉凯。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漫仆。三九已至捎拯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盲厌,已是汗流浹背署照。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工座菠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藤树。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拓萌,于是被迫代替她去往敵國(guó)和親岁钓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容