溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

nodeJS中fs文件系統(tǒng)如何操作

發(fā)布時間:2021-11-24 11:00:18 來源:億速云 閱讀:168 作者:小新 欄目:網(wǎng)絡安全

這篇文章將為大家詳細講解有關nodeJS中fs文件系統(tǒng)如何操作  ,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

概述

  文件 I/O 是由簡單封裝的標準 POSIX 函數(shù)提供的。 通過 require('fs') 使用該模塊。 所有的方法都有異步和同步的形式。

  異步形式始終以完成回調作為它最后一個參數(shù)。 傳給完成回調的參數(shù)取決于具體方法,但第一個參數(shù)總是留給異常。 如果操作成功完成,則第一個參數(shù)會是 null 或 undefined

//異步示例var fs = require('fs');
fs.unlink('/tmp/hello', function(err){  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});

  當使用同步形式時,任何異常都會被立即拋出。 可以使用 try/catch 來處理異常,或讓它們往上冒泡

//同步示例var fs = require('fs');
fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');

  異步方法不保證執(zhí)行順序。 所以下面的例子容易出錯

fs.rename('/tmp/hello', '/tmp/world', function(err){  if (err) throw err;
  console.log('renamed complete');
});
fs.stat('/tmp/world', function(err, stats){  if (err) throw err;
  console.log('stats: ${JSON.stringify(stats)}');
});

  fs.stat 可能在 fs.rename 之前執(zhí)行。正確的方法是把回調鏈起來

fs.rename('/tmp/hello', '/tmp/world', function(err){  if (err) throw err;
  fs.stat('/tmp/world', function(err, stats){    if (err) throw err;
    console.log('stats: ${JSON.stringify(stats)}');
  });
});

  推薦開發(fā)者使用這些函數(shù)的異步版本。 同步版本會阻塞整個進程,直到它們完成(停止所有連接)

底層操作

1、打開文件【fs.open(path, flags[, mode], callback)】

  參數(shù)如下:

path <String> | <Buffer>flags <String> | <Number>mode <Integer> 設置文件模式(權限和 sticky 位),但只有當文件被創(chuàng)建時才有效。默認為 0666,可讀寫callback <Function> 該回調有兩個參數(shù) (err錯誤, fd文件標識,與定時器標識類似)

  flags可以是:

'r' - 以讀取模式打開文件。如果文件不存在則發(fā)生異常。'r+' - 以讀寫模式打開文件。如果文件不存在則發(fā)生異常。'rs+' - 以同步讀寫模式打開文件。命令操作系統(tǒng)繞過本地文件系統(tǒng)緩存。'w' - 以寫入模式打開文件。文件會被創(chuàng)建(如果文件不存在)或截斷(如果文件存在)。'wx' - 類似 'w',但如果 path 存在,則失敗。'w+' - 以讀寫模式打開文件。文件會被創(chuàng)建(如果文件不存在)或截斷(如果文件存在)。'wx+' - 類似 'w+',但如果 path 存在,則失敗。'a' - 以追加模式打開文件。如果文件不存在,則會被創(chuàng)建。'ax' - 類似于 'a',但如果 path 存在,則失敗。'a+' - 以讀取和追加模式打開文件。如果文件不存在,則會被創(chuàng)建。'ax+' - 類似于 'a+',但如果 path 存在,則失敗。

  [注意]使用'rs+'模式不會使fs.open()進入同步阻塞調用。如果那是你想要的,則應該使用fs.openSync()

var fs = require('fs');
fs.open('a.txt','r',function(err,fs){
    console.log(err);//null
    console.log(fs);//3})
var fs = require('fs');
fs.open('b.txt','r',function(err,fs){/*{ Error: ENOENT: no such file or directory, open 'D:\project\b.txt'
    at Error (native)
  errno: -4058,
  code: 'ENOENT',
  syscall: 'open',
  path: 'D:\\project\\b.txt' } */
    console.log(err);
    console.log(fs);//undefined})

  文件的回調函數(shù)中的第二個參數(shù)fd代表文件標識,與定時器標識類似,用于標識文件,且隨著文件的打開順序遞增

var fs = require('fs');
fs.open('1.txt','r',function(err,fs){
    console.log(fs);//3})
fs.open('2.txt','r',function(err,fs){
    console.log(fs);//4})

【fs.openSync(path, flags[, mode])】

  fs.open() 的同步版本。 返回一個表示文件描述符的整數(shù)

var fs = require('fs');var result = fs.openSync('1.txt','r');
console.log(result);//3

2、讀取文件【fs.read(fd, buffer, offset, length, position, callback)】

  參數(shù)如下:

fd <Integer> 通過 fs.open() 方法返回的文件描述符
buffer <String> | <Buffer> 數(shù)據(jù)將被寫入到buffer
offset <Integer> buffer中開始寫入的偏移量
length <Integer> 指定要讀取的字節(jié)數(shù)(整數(shù))
position <Integer> 指定從文件中開始讀取的位置(整數(shù))。 如果position為null,則數(shù)據(jù)從當前文件位置開始讀取
callback <Function> 回調有三個參數(shù) (err, bytesRead, buffer)。err為錯誤信息,bytesRead表示讀取的字節(jié)數(shù),buffer為緩沖區(qū)對象

  由于使用read()方法,會將文件內容讀取buffer對象中,所以需要提前先準備一個buffer對象

var fs = require('fs');
fs.open('1.txt','r',function(err,fd){    if(err){
        console.log('文件打開失敗');
    }else{        var bf = Buffer.alloc(5);
        fs.read(fd,bf,0,3,null,function(err,len,buffer){
            console.log(err);//null
            console.log(len);//3
            console.log(buffer);//<Buffer 61 61 61 00 00>        })
    }
});

【fs.readSync(fd, buffer, offset, length, position)】

  fs.read() 的同步版本,返回 bytesRead 的數(shù)量

var fs = require('fs');var fd = fs.openSync('1.txt','r');var bf = Buffer.alloc(5);var result = fs.readSync(fd,bf,0,3,null);
console.log(result);//3

3、寫入文件【fs.write(fd, buffer, offset, length[, position], callback)】

  參數(shù)如下

fd <Integer>  文件標識
buffer <String> | <Buffer> 要將buffer中的數(shù)據(jù)寫入到文件中
offset <Integer> buffer對象中要寫入的數(shù)據(jù)的起始位置
length <Integer> length是一個整數(shù),指定要寫入的字節(jié)數(shù)
position <Integer> 指定從文件開始寫入數(shù)據(jù)的位置的偏移量。 如果 typeof position !== 'number',則數(shù)據(jù)從當前位置寫入
callback <Function> 回調有三個參數(shù)(err, written, buffer),其中written指定從buffer寫入了多少字節(jié)

  [注意]多次對同一文件使用fs.write且不等待回調,是不安全的。對于這種情況,強烈推薦使用 fs.createWriteStream

  當我們要對打開的文件進行寫操作的時候,打開文件的模式應該是讀寫模式

var fs = require('fs');
fs.open('1.txt','r+',function(err,fd){    if(err){
        console.log('文件打開失敗');
    }else{        var bf = Buffer.from('test');
        fs.write(fd,bf,0,3,null,function(err,len,buffer){
            console.log(err);//null
            console.log(len);//3
            console.log(buffer);//<Buffer 74 65 73 74>        })
    }
});

nodeJS中fs文件系統(tǒng)如何操作

【fs.write(fd, data[, position[, encoding]], callback)】

  該方法寫入data到fd指定的文件。如果data不是一個Buffer實例,則該值將被強制轉換為一個字符串

  不同于寫入 buffer,該方法整個字符串必須被寫入。不能指定子字符串,這是因為結果數(shù)據(jù)的字節(jié)偏移量可能與字符串的偏移量不同

fd  <Integer> 文件標識
data <String> | <Buffer> 要將string或buffer中的數(shù)據(jù)寫入到文件中
position <Integer> 指向從文件開始寫入數(shù)據(jù)的位置的偏移量。 如果 typeof position !== 'number',則數(shù)據(jù)從當前位置寫入
encoding <String> 期望的字符串編碼
callback <Function> 回調有三個參數(shù)(err, written, str),其中written指定從str寫入了多少字節(jié)
var fs = require('fs');
fs.open('1.txt','r+',function(err,fd){    if(err){
        console.log('文件打開失敗');
    }else{
        fs.write(fd,'12345',function(err,len,str){
            console.log(err);//null
            console.log(len);//5
            console.log(str);//<Buffer 74 65 73 74>        })
    }
});

nodeJS中fs文件系統(tǒng)如何操作

【fs.writeSync()】

  fs.write() 的同步版本。返回寫入的字節(jié)數(shù)

var fs = require('fs');var fd = fs.openSync('1.txt','r+');var bf = Buffer.alloc(5);var result = fs.writeSync(fd,bf,0,3,null);
console.log(result);//3

nodeJS中fs文件系統(tǒng)如何操作

4、關閉文件【fs.close(fd, callback)】

  一個文件被操作后,要及時將該文件關閉

  參數(shù)如下:

fd - 通過 fs.open() 方法返回的文件描述符。
callback - 回調函數(shù),沒有參數(shù)。

nodeJS中fs文件系統(tǒng)如何操作

var fs = require('fs');
fs.open('1.txt','r+',function(err,fd){    if(err){
        console.log('文件打開失敗');
    }else{
        fs.close(fd, function(err){            if (err){
                console.log(err);
            } 
            console.log("文件關閉成功");
        });
    }
});

【fs.closeSync(fd)】

  fs.close(fd, callback)的同步版本,返回undefined

var fs = require('fs');var fd = fs.openSync('1.txt','r+');
fs.closeSync(fd);

File操作

  上一部分介紹的都是些底層的操作,接下來將介紹一些更便捷的文件操作。使用下列方法的時候,不需要再打開和關閉文件,直接操作即可

1、寫入文件

【fs.writeFile(file, data[, options], callback)】

  異步的將數(shù)據(jù)寫入一個文件,如果文件不存在則新建,如果文件原先存在,會被替換

  參數(shù)如下:

file - 文件名或文件描述符。
data - 要寫入文件的數(shù)據(jù),可以是 String(字符串) 或 Buffer(流) 對象。
options - 該參數(shù)是一個對象,包含 {encoding, mode, flag}。默認編碼為 utf8, 模式為 0666 , flag 為 'w'callback - 回調函數(shù),回調函數(shù)只包含錯誤信息參數(shù)(err),在寫入失敗時返回。
var fs = require('fs');var filename = '1.txt';
fs.writeFile(filename,'hello',function(err){
    console.log(err);//null})

nodeJS中fs文件系統(tǒng)如何操作

【fs.writeFileSync(file, data[, options])】

  fs.writeFile() 的同步版本。返回 undefined

var fs = require('fs');var filename = '1.txt';
fs.writeFileSync(filename,'abc');

nodeJS中fs文件系統(tǒng)如何操作

2、追加文件

【fs.appendFile(filename, data, [options], callback)】

  異步地追加數(shù)據(jù)到一個文件,如果文件不存在則創(chuàng)建文件。 data 可以是一個字符串或 buffer

  參數(shù)如下

file - 文件名或文件描述符。
data - 要寫入文件的數(shù)據(jù),可以是 String(字符串) 或 Buffer(流) 對象。
options - 該參數(shù)是一個對象,包含 {encoding, mode, flag}。默認編碼為 utf8, 模式為 0666 , flag 為 'w'callback - 回調函數(shù),回調函數(shù)只包含錯誤信息參數(shù)(err),在寫入失敗時返回。
var fs = require('fs');var filename = '1.txt';
fs.appendFile(filename,' world',function(err){
    console.log(err);//null})

nodeJS中fs文件系統(tǒng)如何操作

【fs.appendFileSync(file, data[, options])】

  fs.appendFile()的同步版本。返回undefined

var fs = require('fs');var filename = '1.txt';
fs.appendFileSync(filename,' lalala');

nodeJS中fs文件系統(tǒng)如何操作

3、讀取文件

【fs.readFile(file[, options], callback)】

  參數(shù)如下

file - 文件名或文件描述符
options - 該參數(shù)是一個對象,包含 {encoding, flag}。默認編碼為null,即如果字符編碼未指定,則返回原始的 buffer;flag默認為'r'callback - 回調函數(shù),回調有兩個參數(shù) (err, data),其中data是文件的內容(buffer對象),err是錯誤信息參數(shù),在寫入失敗時返回
var fs = require('fs');var filename = '1.txt';
fs.readFile(filename,function(err,data){    if(err){
        console.log('文件讀取失敗');
    }else{
        console.log(data);//<Buffer 61 62 63 20 77 6f 72 6c 64 20 6c 61 6c 61 6c 61>
        console.log(data.toString());//'abc world lalala'    }
});

【fs.readFileSync(file[, options])】

  fs.readFile的同步版本。返回file的內容

  如果指定了encoding選項,則該函數(shù)返回一個字符串,否則返回一個buffer

var fs = require('fs');var filename = '1.txt';var result = fs.readFileSync(filename);
console.log(result);//<Buffer 61 62 63 20 77 6f 72 6c 64 20 6c 61 6c 61 6c 61>console.log(result.toString());'abc world lalala'

4、刪除文件

【fs.unlink(path, callback)】

  參數(shù)如下:

path - 文件路徑。
callback - 回調函數(shù),沒有參數(shù)。
var fs = require('fs');var filename = '1.txt';
fs.unlink(filename, function(err) {   if (err) {       return console.log('刪除失敗');
   }
   console.log("刪除成功");
});

nodeJS中fs文件系統(tǒng)如何操作

【fs.unlinkSync(path)】

  fs.unlink(path, callback)的同步版本,返回值為undefined

var fs = require('fs');var filename = '1.txt';
fs.unlink(filename);

5、重命名

【fs.rename(oldPath, newPath, callback)】

  參數(shù)如下:

oldPath <String> | <Buffer>newPath <String> | <Buffer>callback <Function> 回調只有一個可能的異常參數(shù)
var fs = require('fs');var filename = 'a.txt';
fs.rename(filename,'2.new.txt',function(err){
    console.log(err);//null})

【fs.renameSync(oldPath, newPath)】

  fs.rename(oldPath, newPath, callback)的同步版本,返回undefined

var fs = require('fs');var filename = '2.new.txt';var result = fs.renameSync(filename,'a.txt');

6、文件信息

【fs.stat(path, callback)】

  fs.stat()執(zhí)行后,會將stats類的實例返回給其回調函數(shù)??赏ㄟ^stats類中的提供方法判斷文件的相關屬性

  參數(shù)如下:

path - 文件路徑。
callback - 回調函數(shù),帶有兩個參數(shù)如:(err, stats), stats 是 fs.Stats 對象
var fs = require('fs');var filename = 'a.txt';
fs.stat(filename,function(err,stats){
    console.log(err);//null/*{ dev: 223576,
  mode: 33206,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: undefined,
  ino: 7599824371527537,
  size: 0,
  blocks: undefined,
  atime: 2017-06-03T14:18:15.370Z,
  mtime: 2017-06-03T14:18:15.370Z,
  ctime: 2017-06-03T16:32:05.776Z,
  birthtime: 2017-06-03T14:18:15.370Z } */    
    console.log(stats);
});

  stats類中的方法有

stats.isFile()  如果是文件返回 true,否則返回 false。
stats.isDirectory() 如果是目錄返回 true,否則返回 false。
stats.isBlockDevice()   如果是塊設備返回 true,否則返回 false。
stats.isCharacterDevice()   如果是字符設備返回 true,否則返回 false。
stats.isSymbolicLink()  如果是軟鏈接返回 true,否則返回 false。
stats.isFIFO()  如果是FIFO,返回true,否則返回false。FIFO是UNIX中的一種特殊類型的命令管道。
stats.isSocket()    如果是 Socket 返回 true,否則返回 false。
var fs = require('fs');var filename = 'a.txt';
fs.stat(filename,function(err,stats){
    console.log(stats.isFile());//true});

【fs.statSync(path)】

  fs.stat(path, callback)方法的同步版本,返回一個 fs.Stats 實例

var fs = require('fs');var filename = 'a.txt';var result = fs.statSync(filename);/*{ dev: 223576,
  mode: 33206,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: undefined,
  ino: 7599824371527537,
  size: 0,
  blocks: undefined,
  atime: 2017-06-03T14:18:15.370Z,
  mtime: 2017-06-03T14:18:15.370Z,
  ctime: 2017-06-03T16:32:05.776Z,
  birthtime: 2017-06-03T14:18:15.370Z } */console.log(result);

7、監(jiān)聽

【fs.watch(filename[, options][, listener])】

  該方法用于監(jiān)視filename的變化,filename可以是一個文件或一個目錄。返回的對象是一個fs.FSWatcher

  參數(shù)如下

filename <String> | <Buffer>options <String> | <Object> 參數(shù)可選,如果options是一個字符串,則它指定了encoding。否則options應該以一個對象傳入
    persistent <Boolean> 指明如果文件正在被監(jiān)視,進程是否應該繼續(xù)運行。默認為true
    recursive <Boolean> 指明是否全部子目錄應該被監(jiān)視,或只是當前目錄。 適用于當一個目錄被指定時,且只在支持的平臺。默認為false
    encoding <String> 指定用于傳給監(jiān)聽器的文件名的字符編碼。默認為'utf8'listener <Function> 回調函數(shù)有兩個參數(shù) (eventType, filename)。 eventType可以是'rename'或'change',filename是觸發(fā)事件的文件的名稱

  回調中提供的 filename 參數(shù)僅在 Linux 和 Windows 系統(tǒng)上支持。 即使在支持的平臺中,filename 也不能保證提供。 因此,不要以為 filename 參數(shù)總是在回調中提供,如果它是空的,需要有一定的后備邏輯

fs.watch('somedir', (eventType, filename) => {
  console.log(`事件類型是: ${eventType}`);  if (filename) {
    console.log(`提供的文件名: ${filename}`);
  } else {
    console.log('未提供文件名');
  }
});
var fs = require('fs');var filename = '1.txt';
fs.watch(filename,function(eventType, _filename){
    console.log(eventType);//change
    if(_filename){
        console.log(_filename + '發(fā)生了改變');//'1.txt發(fā)生了改變'
    }else{
        console.log('...');
    }
    
})

  [注意]當一個文件出現(xiàn)或消失在一個目錄里時,'rename'也會被觸發(fā)

目錄操作

1、創(chuàng)建

【fs.mkdir(path[, mode], callback)】

  參數(shù)如下:

path - 文件路徑。
mode - 設置目錄權限,默認為 0777。
callback - 回調函數(shù),回調只有一個可能的異常參數(shù)
var fs = require('fs');
fs.mkdir('./1',function(err){
    console.log(err);//null})

【fs.mkdirSync(path[, mode])】

  fs.mkdir(path[, mode], callback)的同步版本,返回undefined

var fs = require('fs');
fs.mkdirSync('./2');

2、刪除

【fs.rmdir(path, callback)】

  參數(shù)如下:

path - 文件路徑。
callback - 回調函數(shù),回調只有一個可能的異常參數(shù)
var fs = require('fs');
fs.rmdir('./1',function(err){
    console.log(err);//null})

【fs.rmdirSync(path, callback)】

  fs.rmdir(path, callback)的同步版本,返回undefined

var fs = require('fs');
fs.rmdirSync('./2');

3、讀取

【fs.readdir(path[, options], callback)】

  參數(shù)如下:

path <String> | <Buffer>options <String> | <Object> 可選的 options 參數(shù)用于傳入回調的文件名,它可以是一個字符串并指定一個字符編碼,或是一個對象且由一個 encoding 屬性指定使用的字符編碼。 如果 encoding 設為 'buffer',則返回的文件名會被作為 Buffer 對象傳入
    encoding <String> 默認 = 'utf8'callback <Function> 回調有兩個參數(shù) (err, files),其中 files 是目錄中不包括 '.' 和 '..' 的文件名的數(shù)組
var fs = require('fs');
fs.readdir('./',function(err,data){
    console.log(err);//null/*[ '.csslintrc',
  '.jshintrc',
  'a.txt',
  'dist',
  'Gruntfile.js',
  'Gruntfile1.js',
  'index.html',
  'main.js',
  'node_modules',
  'package.json',
  'src' ] */
    console.log(data);
})
var fs = require('fs');
fs.readdir('./',function(err,data){
    data.forEach(function(item,index,arr){
        fs.stat(item,function(err,stats){            if(stats.isFile()){
                console.log('文件:' + item);
            }            if(stats.isDirectory()){
                console.log('目錄:' + item);
            }
        });    
    })

})/*文件:.jshintrc
文件:.csslintrc
目錄:dist
文件:Gruntfile.js
文件:index.html
文件:Gruntfile1.js
文件:main.js
目錄:node_modules
文件:package.json
文件:a.txt
目錄:src */

【fs.readdirSync(path[, options], callback)】

  fs.readdir(path[, options], callback)的同步版本,返回一個不包括 '.' 和 '..' 的文件名的數(shù)組

var fs = require('fs');var result = fs.readdirSync('./');/*[ '.csslintrc',
  '.jshintrc',
  'a.txt',
  'dist',
  'Gruntfile.js',
  'Gruntfile1.js',
  'index.html',
  'main.js',
  'node_modules',
  'package.json',
  'src' ] */console.log(result);

遍歷目錄

  遍歷目錄是操作文件時的一個常見需求。比如寫一個程序,需要找到并處理指定目錄下的所有JS文件時,就需要遍歷整個目錄

  遍歷目錄時一般使用遞歸算法,否則就難以編寫出簡潔的代碼。遞歸算法與數(shù)學歸納法類似,通過不斷縮小問題的規(guī)模來解決問題

function factorial(n) {    if (n === 1) {        return 1;
    } else {        return n * factorial(n - 1);
    }
}

  上邊的函數(shù)用于計算N的階乘(N!)??梢钥吹?,當N大于1時,問題簡化為計算N乘以N-1的階乘。當N等于1時,問題達到最小規(guī)模,不需要再簡化,因此直接返回1

  目錄是一個樹狀結構,在遍歷時一般使用深度優(yōu)先+先序遍歷算法。深度優(yōu)先,意味著到達一個節(jié)點后,首先接著遍歷子節(jié)點而不是鄰居節(jié)點。先序遍歷,意味著首次到達了某節(jié)點就算遍歷完成,而不是最后一次返回某節(jié)點才算數(shù)。因此使用這種遍歷方式時,下邊這棵樹的遍歷順序是A > B > D > E > C > F

          A         / \
        B   C       / \   \
      D   E   F

  了解了必要的算法后,我們可以簡單地實現(xiàn)以下目錄遍歷函數(shù)

function travel(dir, callback) {
    fs.readdirSync(dir).forEach(function (file) {        var pathname = path.join(dir, file);        if (fs.statSync(pathname).isDirectory()) {
            travel(pathname, callback);
        } else {
            callback(pathname);
        }
    });
}

  可以看到,該函數(shù)以某個目錄作為遍歷的起點。遇到一個子目錄時,就先接著遍歷子目錄。遇到一個文件時,就把文件的絕對路徑傳給回調函數(shù)。回調函數(shù)拿到文件路徑后,就可以做各種判斷和處理。因此假設有以下目錄

- /home/user/
    - foo/
        x.js    - bar/
        y.js
    z.css

  使用以下代碼遍歷該目錄時,得到的輸入如下

travel('/home/user', function (pathname) {
    console.log(pathname);
});------------------------
/home/user/foo/x.js/home/user/bar/y.js/home/user/z.css

  如果讀取目錄或讀取文件狀態(tài)時使用的是異步API,目錄遍歷函數(shù)實現(xiàn)起來會有些復雜,但原理完全相同。travel函數(shù)的異步版本如下

function travel(dir, callback, finish) {
    fs.readdir(dir, function (err, files) {
        (function next(i) {            if (i < files.length) {                var pathname = path.join(dir, files[i]);

                fs.stat(pathname, function (err, stats) {                    if (stats.isDirectory()) {
                        travel(pathname, callback, function () {
                            next(i + 1);
                        });
                    } else {
                        callback(pathname, function () {
                            next(i + 1);
                        });
                    }
                });
            } else {
                finish && finish();
            }
        }(0));
    });
}

關于“nodeJS中fs文件系統(tǒng)如何操作  ”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI