java基礎(chǔ)io流——字符流的變革(深入淺出)

亂碼導(dǎo)火索:

在io流里,先誕生了字節(jié)流,但是字節(jié)流讀取數(shù)據(jù)會(huì)有亂碼的問(wèn)題(讀中文會(huì)亂碼)。比如:

FileInputStream fis = new FileInputStream("a.txt");
//        int by = 0;
//        while ((by=fis.read() )!= -1) {
//            System.out.print((char)by);//bcdbcdbcdbcdbcdbcdhello ??-???
//            //因?yàn)檫€正常,中文就亂碼了,有什么辦法解決嗎,有,就是有點(diǎn)麻煩
//        }

從文件中讀取中文會(huì)有亂碼,當(dāng)然字節(jié)流有解決措施。

FileInputStream fis = new FileInputStream("a.txt");
byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes)) != -1) {
            System.out.println(new String(bytes,0,len));//bcdbcdbcdbcdbcdbcdhello 中國(guó)
            //查看new String()的源碼,this.value = StringCoding.decode(bytes, offset, length);
            //點(diǎn)進(jìn)decode,循序漸進(jìn)發(fā)現(xiàn),默認(rèn)編碼是UTF-8
            //通過(guò)源碼,也看到了這個(gè)方法public String(byte bytes[], int offset, int length, String charsetName)

        }

但是解碼這并不是字節(jié)流做的,而是String的功能。查看String的源碼,構(gòu)造方法有解碼功能,并且默認(rèn)編碼是utf-8。

聊到了亂碼,我覺(jué)得有必要聊一下編碼的知識(shí)。

String(byte[] bytes, String charsetName):通過(guò)指定的字符集解碼字節(jié)數(shù)組
byte[] getBytes(String charsetName):使用指定的字符集合把字符串編碼為字節(jié)數(shù)組

編碼:把看得懂的變成看不懂的
String -- byte[]

解碼:把看不懂的變成看得懂的
byte[] -- String

因此字節(jié)流讀取的數(shù)據(jù)是編碼過(guò)的數(shù)據(jù),我們解碼就行了。

編碼問(wèn)題簡(jiǎn)單,只要編碼解碼的格式是一致的。

計(jì)算機(jī)只能識(shí)別二進(jìn)制數(shù)據(jù),早期由來(lái)是電信號(hào)。為了方便應(yīng)用計(jì)算機(jī),讓它可以識(shí)別各個(gè)國(guó)家的文字。就將各個(gè)國(guó)家的文字用數(shù)字來(lái)表示,并一一對(duì)應(yīng),形成一張表。

     ASCII:美國(guó)標(biāo)準(zhǔn)信息交換碼。
     用一個(gè)字節(jié)的7位可以表示。
     ISO8859-1:拉丁碼表。歐洲碼表
     用一個(gè)字節(jié)的8位表示。
     GB2312:中國(guó)的中文編碼表。
     GBK:中國(guó)的中文編碼表升級(jí),融合了更多的中文文字符號(hào)。
     GB18030:GBK的取代版本
     BIG-5碼 :通行于臺(tái)灣、香港地區(qū)的一個(gè)繁體字編碼方案,俗稱“大五碼”。
     Unicode:國(guó)際標(biāo)準(zhǔn)碼,融合了多種文字。
     所有文字都用兩個(gè)字節(jié)來(lái)表示,Java語(yǔ)言使用的就是unicode
     UTF-8:最多用三個(gè)字節(jié)來(lái)表示一個(gè)字符。

     UTF-8不同,它定義了一種“區(qū)間規(guī)則”,這種規(guī)則可以和ASCII編碼保持最大程度的兼容:
     它將Unicode編碼為00000000-0000007F的字符,用單個(gè)字節(jié)來(lái)表示?
     它將Unicode編碼為00000080-000007FF的字符用兩個(gè)字節(jié)表示 
     它將Unicode編碼為00000800-0000FFFF的字符用3字節(jié)表示 

示例:

        String s = "你好";
        byte[] bytes1 = s.getBytes();
        System.out.println(Arrays.toString(bytes1));//[-28, -67, -96, -27, -91, -67]  默認(rèn)編碼utf-8

        byte[] bytes2 = s.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));//[-60, -29, -70, -61]
        byte[] bytes3 = s.getBytes("UTF-8");
        System.out.println(Arrays.toString(bytes3));//[-28, -67, -96, -27, -91, -67]

        String s1 = new String(bytes1);
        System.out.println(s1);//你好
        String s2 = new String(bytes2,"GBK");
        System.out.println(s2);//你好

        String s3 = new String(bytes2,"gbk");
        System.out.println(s3);//你好

        String s4 = new String(bytes3);
        System.out.println(s4);//你好

        String s5 = new String(bytes3,"gbk");
        System.out.println(s5);//浣犲ソ

雖然字節(jié)流有解決亂碼的方案,但并不方便,所以java io流就設(shè)計(jì)出了轉(zhuǎn)換流,一場(chǎng)亂碼引發(fā)的變革。
(OutputStreamWriter、InputStreamReader)

OutputStreamWriter(OutputStream out):根據(jù)默認(rèn)編碼把字節(jié)流的數(shù)據(jù)轉(zhuǎn)換為字符流

OutputStreamWriter(OutputStream out,String charsetName):根據(jù)指定編碼把字節(jié)流數(shù)據(jù)轉(zhuǎn)換為字符流
把字節(jié)流轉(zhuǎn)換為字符流。

//創(chuàng)造對(duì)象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));//查看源碼,java8 默認(rèn)utf-8
//寫數(shù)據(jù)
osw.write("中國(guó)");
//釋放資源
osw.close();//close包含了close和flush的作用

一般默認(rèn)編碼就夠了。

查看源碼,發(fā)現(xiàn)OutputStreamWriter有5個(gè)write方法。

/*
 * OutputStreamWriter的方法:
 * public void write(int c):寫一個(gè)字符
 * public void write(char[] cbuf):寫一個(gè)字符數(shù)組
 * public void write(char[] cbuf,int off,int len):寫一個(gè)字符數(shù)組的一部分
 * public void write(String str):寫一個(gè)字符串
 * public void write(String str,int off,int len):寫一個(gè)字符串的一部分
 *
 * 面試題:close()和flush()的區(qū)別?
 * A:close()關(guān)閉流對(duì)象,但是先刷新一次緩沖區(qū)。關(guān)閉之后,流對(duì)象不可以繼續(xù)再使用了。
 * B:flush()僅僅刷新緩沖區(qū),刷新之后,流對(duì)象還可以繼續(xù)使用。
 */
 
 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c.txt"));//查看源碼,java8 默認(rèn)utf-8
       //寫一個(gè)字符
        osw.write('a');
        osw.write(97);
        osw.write('中');
        // 為什么數(shù)據(jù)沒(méi)有進(jìn)去呢?
        // 原因是:字符 = 2字節(jié)
        // 文件中數(shù)據(jù)存儲(chǔ)的基本單位是字節(jié)。
        // void flush()
        osw.flush();
        //寫一個(gè)字符數(shù)組
        char[] chars = {'a','b','中','國(guó)'};
        osw.write(chars);
        osw.flush();
        //寫一個(gè)字符數(shù)組的一部分
        osw.write(chars,2,2);
        osw.flush();
        //寫一個(gè)字符串
        osw.write("\n\r中國(guó)");
        //寫一個(gè)字符串的一部分
        osw.write("中國(guó)你好",2,2);
        osw.close();

InputStreamReader(InputStream is):用默認(rèn)的編碼讀取數(shù)據(jù),默認(rèn)utf-8

InputStreamReader(InputStream is,String charsetName):
用指定的編碼讀取數(shù)據(jù)

//創(chuàng)建對(duì)象
InputStreamReader isr = new InputStreamReader(new FileInputStream("b.txt"));//默認(rèn)編碼utf-8
InputStreamReader isr1 = new InputStreamReader(new FileInputStream("b.txt"),"gbk");//可指定編碼

//讀數(shù)據(jù)
int ch = 0;
while ((ch = isr.read()) != -1) {
    System.out.print((char)ch);//中國(guó)
}
//釋放資源
isr.close();
//只有文檔的編碼和讀取的編碼一致才不會(huì)亂碼。

查看源碼知道InputStreamReader有2個(gè)read方法。

/*
 * InputStreamReader的方法:
 * int read():一次讀取一個(gè)字符
 * int read(char[] chs):一次讀取一個(gè)字符數(shù)組
 */

InputStreamReader isr = new InputStreamReader(new FileInputStream("c.txt"));
        //讀一個(gè)字符
//        int ch = 0;
//        while ((ch = isr.read()) != -1) {
//            System.out.print((char) ch);//9797200139798200132226920013222691020013222692032022909/
//            //aa中ab中國(guó)中國(guó)
//            //中國(guó)你好
//        }
        //isr.close();
        //讀一個(gè)字符數(shù)組
        char[] chars =new char[1024];
        int len = 0;
        while ((len = isr.read(chars)) != -1) {
            System.out.println(chars.length);//1024
            System.out.println(new String(chars,0,len));
            //aa中ab中國(guó)中國(guó)
            //中國(guó)你好
        }
        isr.close();

現(xiàn)在我們可以通過(guò)轉(zhuǎn)換流升級(jí)字節(jié)流復(fù)制文件的方式了。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("e:\\a.txt"));
char [] chars = new char[1024];
int len  = 0 ;
while ((len = isr.read(chars)) != -1) {
    osw.write(chars,0,len);
    osw.flush();
}
osw.close();
isr.close();

字符流的誕生:

轉(zhuǎn)換流已經(jīng)是字符流了,但是他們的名字太長(zhǎng)了,Java就提供了其子類供我們使用。

FileWriter 、FileReader 繼承了其父類的所有方法。

字符流=字節(jié)流+編碼表

OutputStreamWriter = FileOutputStream + 編碼表(GBK)

FileWriter = FileOutputStream + 編碼表(GBK)

InputStreamReader = FileInputStream + 編碼表(GBK)

FileReader = FileInputStream + 編碼表(GBK)

復(fù)制改寫:

FileWriter fw  = new FileWriter("e:\\b.txt");
FileReader fr = new FileReader("b.txt");
char[] chars =new char[1024];
int len = 0;
while ((len = fr.read(chars)) != -1) {
    fw.write(chars,0,len);
    fw.flush();
    }
fw.close();
fr.close();
   /**
     * 總結(jié),到現(xiàn)在為止,加上字節(jié)流,復(fù)制文本的方式有8種,但是復(fù)制圖片視頻等文件只有四種字節(jié)流的方式,因?yàn)椴荒苡米址鲝?fù)制圖片視頻mp3等
     */

字符流學(xué)習(xí)前輩字節(jié)流的經(jīng)驗(yàn),也設(shè)計(jì)了字符緩沖流。

BufferedReader、
BufferedWriter

和字節(jié)緩沖流的設(shè)計(jì)基本一樣,也有兩個(gè)構(gòu)造方法,但是我們只要默認(rèn)的緩沖大小的構(gòu)造方法就可以了。

用字符緩沖流改寫復(fù)制功能:

BufferedReader br = new BufferedReader(new FileReader("c.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\d.txt"));
char[] chars = new char[1024];
int len = 0 ;
while ((len = br.read(chars)) != -1) {
    bw.write(chars,0,len);
    bw.flush();
}
br.close();
bw.close();

然而字符緩沖流還有自己特殊的讀寫功能。

BufferedWriter :void newLine() 換行

BufferedReader :String readLine() 讀一行數(shù)據(jù)

public static void main(String args[]) throws IOException {
       // write();
        read();
}

    private static void read() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
            //readLine不會(huì)讀取換行符
            //讀到末尾返回null
        }
        br.close();
    }

    private static void write() throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
        for (int i = 0; i <10 ; i++) {
            bw.write("你好哈哈哈哈哈");
            bw.newLine();//換行,并且自動(dòng)檢測(cè)不同系統(tǒng)的換行符
            bw.flush();
            //一般三個(gè)連用
        }
        bw.close();
    }

用字符緩沖流的特殊方式升級(jí)復(fù)制功能:

BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\bw.txt"));

String line = null;
while ((line = br.readLine()) != null) {
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
bw.close();
br.close();


    //總結(jié)  字符流復(fù)制文本有5種方式

字符流的基礎(chǔ)基本就聊完了,還有一個(gè)比較常用的類LineNumberReader

查看源碼可知LineNumberReader繼承自BufferedReader,并且增加了行號(hào)的操作。

LineNumberReader lnr = new LineNumberReader(new FileReader("a.txt"));
String line = null;
while ((line = lnr.readLine()) != null) {
    System.out.println(lnr.getLineNumber()+":"+line);
}

1:A
2:S
3:F

但是LineNumberWriter。源碼很簡(jiǎn)單,更多的操作請(qǐng)看源碼。

io流總結(jié):

image

java 中文api :
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

查看api源碼,深入理解io設(shè)計(jì)理念。

io流面試題:

題一:復(fù)制單級(jí)文件夾
/**
 * 封裝
 * 新建文件夾
 * 獲得源文件夾下文件列表
 * 復(fù)制文件到新文件夾
 */
public class copyFolder {
    public static void main(String args[]) throws IOException {
        File file1 = new File("F:\\湯包\\IT時(shí)代\\java基礎(chǔ)\\day21\\code\\demo");
        File file2 = new File("e:\\demo");
        //判斷文件夾是否存在
        if (!file2.exists()){
            file2.mkdir();
        }

        //獲取源文件夾下文件列表

        File[] files = file1.listFiles();
        for (File file : files) {
            File newfile = new File(file2,file.getName());
            copyFun(file,newfile);
        }
    }

    private static void copyFun(File file1,File file2) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file1));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2));
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes,0,len);
        }
        bis.close();
        bos.close();
    }
}
題二:復(fù)制多極文件夾
/*
 * 需求:復(fù)制多極文件夾
 *
 * 數(shù)據(jù)源:F:\湯包\IT時(shí)代\java基礎(chǔ)\day21\code\demos
 * 目的地:E:\\
 *
 * 分析:
 *      A:封裝數(shù)據(jù)源File
 *      B:封裝目的地File
 *      C:判斷該File是文件夾還是文件
 *          a:是文件夾
 *              就在目的地目錄下創(chuàng)建該文件夾
 *              獲取該File對(duì)象下的所有文件或者文件夾File對(duì)象
 *              遍歷得到每一個(gè)File對(duì)象
 *              回到C
 *          b:是文件
 *              就復(fù)制(字節(jié)流)
 */

public class copyFolder2 {

    public static void main(String args[]) throws IOException {
        File file1 = new File("F:\\湯包\\IT時(shí)代\\java基礎(chǔ)\\day21\\code\\demos");
        File file2 = new File("e:\\");
        copyFolder(file1,file2);
    }

    private static void copyFolder(File srcFile, File destFile) throws IOException {
        if (srcFile.isDirectory()){
            File newFolder = new File(destFile, srcFile.getName());
            newFolder.mkdir();
            File[] files = srcFile.listFiles();
            for (File file1 : files) {
                copyFolder(file1,newFolder);
            }
        }else {
            File newFile = new File(destFile,srcFile.getName());
            copyFile(srcFile,newFile);
        }

    }

    private static void copyFile(File file1,File file2) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file1));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2));
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes,0,len);
        }
        bis.close();
        bos.close();
    }
}

復(fù)制多級(jí)文件夾,構(gòu)思用到了遞歸,可知遞歸真的很重要,之后也會(huì)總結(jié)一下遞歸的知識(shí)。

題三:鍵盤錄入5個(gè)學(xué)生信息(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)),按照總分從高到低打印到控制臺(tái)。

Student.java

public class Student {
    // 姓名
    private String name;
    // 語(yǔ)文成績(jī)
    private int chinese;
    // 數(shù)學(xué)成績(jī)
    private int math;
    // 英語(yǔ)成績(jī)
    private int english;

    public Student() {
        super();
    }

    public Student(String name, int chinese, int math, int english) {
        super();
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    public String getName() {
        return name;
    }

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

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    public int getSum() {
        return this.chinese + this.math + this.english;
    }
}

StendentDemo.java

/*
 * 鍵盤錄入5個(gè)學(xué)生信息(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)),按照總分從高到低存入文本文件
 *
 * 分析:
 *      A:創(chuàng)建學(xué)生類
 *      B:創(chuàng)建集合對(duì)象
 *          TreeSet<Student>
 *      C:鍵盤錄入學(xué)生信息存儲(chǔ)到集合
 *      D:遍歷集合,把數(shù)據(jù)寫到文本文件
 */
public class StendentDemo {
    public static void main(String args[]) throws IOException {
        TreeSet<Student> students = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //s1-s2升序,s2-s1降序
                int num = s2.getSum() - s1.getSum();
                int num1 = num == 0 ?s2.getChinese()-s1.getChinese():num;
                int num2 = num1 ==0 ?s2.getMath()-s1.getMath():num1;
                int num3 = num2 ==0 ?s2.getEnglish()-s1.getEnglish():num2;
                int num4 = num3 == 0?s1.getName().compareTo(s2.getName()):num3;//按字母順序
                return num4;
            }
        });
        for (int i = 0; i <5 ; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("錄入學(xué)生成績(jī):");
            System.out.println("姓名:");
            String name = sc.nextLine();
            System.out.println("語(yǔ)文成績(jī):");
            int chinese = sc.nextInt();
            System.out.println("數(shù)學(xué)成績(jī):");
            int math = sc.nextInt();
            System.out.println("英語(yǔ)成績(jī):");
            int english = sc.nextInt();
            Student student = new Student(name,chinese,math,english);
            students.add(student);
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter("grade.txt"));
        bw.write("學(xué)生信息如下:");
        bw.newLine();
        bw.flush();
        bw.write("姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)");
        bw.newLine();
        bw.flush();
        for (Student student : students) {
            StringBuilder sb = new StringBuilder();
            sb.append(student.getName()).append(student.getChinese()).append(student.getMath()).append(student.getEnglish());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();






    }
}
題四:已知s.txt文件中有這樣的一個(gè)字符串:“hcexfgijkamdnoqrzstuvwybpl”,請(qǐng)編寫程序讀取數(shù)據(jù)內(nèi)容,把數(shù)據(jù)排序后寫入ss.txt中。
/*
 * 已知s.txt文件中有這樣的一個(gè)字符串:“hcexfgijkamdnoqrzstuvwybpl”
 * 請(qǐng)編寫程序讀取數(shù)據(jù)內(nèi)容,把數(shù)據(jù)排序后寫入ss.txt中。
 * 
 * 分析:
 *      A:把s.txt這個(gè)文件給做出來(lái)
 *      B:讀取該文件的內(nèi)容,存儲(chǔ)到一個(gè)字符串中
 *      C:把字符串轉(zhuǎn)換為字符數(shù)組
 *      D:對(duì)字符數(shù)組進(jìn)行排序
 *      E:把排序后的字符數(shù)組轉(zhuǎn)換為字符串
 *      F:把字符串再次寫入ss.txt中
 */
public class StringDemo {
    public static void main(String[] args) throws IOException {
        // 讀取該文件的內(nèi)容,存儲(chǔ)到一個(gè)字符串中
        BufferedReader br = new BufferedReader(new FileReader("s.txt"));
        String line = br.readLine();
        br.close();

        // 把字符串轉(zhuǎn)換為字符數(shù)組
        char[] chs = line.toCharArray();

        // 對(duì)字符數(shù)組進(jìn)行排序
        Arrays.sort(chs);

        // 把排序后的字符數(shù)組轉(zhuǎn)換為字符串
        String s = new String(chs);

        // 把字符串再次寫入ss.txt中
        BufferedWriter bw = new BufferedWriter(new FileWriter("ss.txt"));
        bw.write(s);
        bw.newLine();
        bw.flush();

        bw.close();
    }
}
題五:用Reader模擬BufferedReader的readLine()功能
/*
 * 用Reader模擬BufferedReader的readLine()功能
 *
 * readLine():一次讀取一行,根據(jù)換行符判斷是否結(jié)束,只返回內(nèi)容,不返回?fù)Q行符
 */
public class MyBufferedReader {
    private Reader reader;

    public MyBufferedReader(Reader reader){
        this.reader=reader;
    }
    public String readLine() throws IOException {
        StringBuilder sb = new StringBuilder();
        int ch = 0;
        while((ch=reader.read())!=-1) {
            if (ch=='\r'){
                continue;
            }
            if (ch=='\n'){
                return  sb.toString();
            }else {
                sb.append((char)ch);
            }
        }

        if (sb.length()>0){
            return sb.toString();
        }
        return null;
    }

    public  void  close() throws IOException {
        this.reader.close();
    }
}

測(cè)試:

MyBufferedReader mbr = new MyBufferedReader(new FileReader("a.txt"));

        String line = null;
        while ((line = mbr.readLine()) != null) {
            System.out.println((line));
        }

        mbr.close();

通過(guò)自己實(shí)現(xiàn)readLine()方法,并且查看源碼可知,字符緩沖流的readLine()也用到了StringBuilder,并且也要判斷\n和\r,最后關(guān)閉的流就是Reader。

以上是本人學(xué)習(xí)筆記整理,重溫java經(jīng)典,歡迎各位同道中人批評(píng)指正。

學(xué)習(xí)心得:
再次學(xué)習(xí)io流,看了好多源碼,體驗(yàn)了其架構(gòu)思想的強(qiáng)大,邏輯的縝密。發(fā)現(xiàn)io流的讀和寫都是線程安全的。所以線程得再次研究下,設(shè)計(jì)模式得了解下。

源碼碼云地址:
https://gitee.com/stefanpy/java

夢(mèng)回io流完整目錄:

java基礎(chǔ)io流——File告白(重溫經(jīng)典)

java基礎(chǔ)io流——OutputStream和InputStream的故事(溫故知新)

java基礎(chǔ)io流——字符流的變革(深入淺出)

java基礎(chǔ)io流——配角也風(fēng)流(不求甚解)

最后編輯于
?著作權(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)容