關(guān)于Go語(yǔ)言中的IO操作詳解
在現(xiàn)代軟件開(kāi)發(fā)中,高效的輸入輸出(I/O)操作是提高程序性能的關(guān)鍵之一。Go語(yǔ)言提供了豐富的I/O操作接口,使得文件讀寫(xiě)、網(wǎng)絡(luò)通信等任務(wù)變得簡(jiǎn)單而高效。
Go語(yǔ)言的I/O操作主要通過(guò)標(biāo)準(zhǔn)庫(kù)中的io包和os包實(shí)現(xiàn)。o包提供了一系列用于輸入和輸出操作的基本接口和原語(yǔ)。這些接口和原語(yǔ)構(gòu)成了Go語(yǔ)言中處理I/O操作的基礎(chǔ),支持多種I/O設(shè)備的讀寫(xiě)操作,包括文件、網(wǎng)絡(luò)連接、內(nèi)存緩沖區(qū)等。而os包則提供了對(duì)操作系統(tǒng)功能的封裝,包括文件操作、進(jìn)程管理等。
一、os包簡(jiǎn)介
os包是Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的一個(gè)重要包,提供了操作系統(tǒng)相關(guān)的功能接口。通過(guò)os包,我們可以執(zhí)行各種底層操作,如讀取和寫(xiě)入文件、獲取系統(tǒng)信息、執(zhí)行外部命令等。
二、常用函數(shù)與示例
1. 文件操作
1.1 獲取文件信息
Stat:獲取文件信息對(duì)象,符號(hào)鏈接會(huì)跳轉(zhuǎn)。
Lstat:獲取文件信息對(duì)象,符號(hào)鏈接不跳轉(zhuǎn)。
package main import ( "fmt" "os" ) //看下fileinfo接口 // file // fileInfo /* type FileInfo interface { Name() string // base name of the file Size() int64 // length in bytes for regular files; system-dependent for others Mode() FileMode // file mode bits : 權(quán)限 ModTime() time.Time // modification time IsDir() bool // abbreviation for Mode().IsDir() // 獲取更加詳細(xì)的文件信息, *syscall.Stat_t 反射來(lái)獲取 Sys() any // underlying data source (can return nil) */ func main() { // 獲取某個(gè)文件的狀態(tài) //func Stat(name string) (FileInfo, error) fileinfo, err := os.Stat("F:\\goworks\\src\\jingtian\\yufa\\type別名\\type別名.go") if err != nil { fmt.Println(err) return } fmt.Println(fileinfo.Name()) // 文件名 demo01.go fmt.Println(fileinfo.IsDir()) // 是否目錄 false fmt.Println(fileinfo.ModTime()) // 文件的修改時(shí)間 2024-09-26 10:03:01.0946679 +0800 CST fmt.Println(fileinfo.Size()) // 文件大小 1542 字節(jié)數(shù) fmt.Println(fileinfo.Mode()) // 權(quán)限 -rw-rw-rw- }
1.2 創(chuàng)建文件
Create:創(chuàng)建文件,如果文件存在,則清空原文件。
package main import ( "fmt" "os" ) func main() { //創(chuàng)建文件,文件不存在就創(chuàng)建文件,如果文件存在,則清空原文件。 // func Create(name string) (*File, error) file, err := os.Create("example.txt") if err != nil { fmt.Println(err) return } //關(guān)閉文件,延遲執(zhí)行 defer file.Close() //向文件中寫(xiě)內(nèi)容 // func (f *File) WriteString(s string) (n int, err error) _, err = file.WriteString("Hello, World!") if err != nil { fmt.Println(err) } fmt.Println("File created successfully") }
文件創(chuàng)建,并且寫(xiě)入成功
創(chuàng)建的文件默認(rèn)權(quán)限是0666
1.3 刪除文件
Remove:刪除文件或目錄(單一文件)只能刪除空文件夾,文件不存在會(huì)報(bào)錯(cuò)。如果文件夾中有文件也刪不掉
RemoveAll:遞歸刪除文件或目錄,文件或目錄不存在不報(bào)錯(cuò),返回nil。
package main import ( "fmt" "os" ) func main() { // 刪除文件 // func Remove(name string) error //文件不存在會(huì)報(bào)錯(cuò) err := os.Remove("example.txt") if err != nil { fmt.Println(err) } else { fmt.Println("File removed successfully") } // 遞歸刪除目錄 // func RemoveAll(path string) error //目錄不存在返回nil 不會(huì)報(bào)錯(cuò) //可以刪除指定目錄下的目錄或文件 err = os.RemoveAll("testdir\\mydir.go") if err != nil { fmt.Println(err) } else { fmt.Println("Directory removed successfully") } }
1.4 重命名或移動(dòng)文件
Rename:重命名文件或移動(dòng)文件。
package main import ( "fmt" "os" ) func main() { // 重命名文件 // func Rename(oldpath, newpath string) error err := os.Rename("張三.txt", "新張三.txt") if err != nil { fmt.Println(err) } else { fmt.Println("File renamed successfully") } // 移動(dòng)文件 err = os.Rename("新張三.txt", "testdir\\新張三.txt") if err != nil { fmt.Println(err) } else { fmt.Println("File moved successfully") } }
1.5 打開(kāi)文件
使用os.Open函數(shù)可以打開(kāi)一個(gè)文件,返回一個(gè)*os.File類型的文件對(duì)象。如果文件打開(kāi)失敗,會(huì)返回一個(gè)錯(cuò)誤。
package main import ( "fmt" "os" ) func main() { //func Open(name string) (*File, error) file, err := os.Open("example.txt") if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() fmt.Println("File opened successfully") //打印打開(kāi)的文件,是個(gè)內(nèi)存地址 fmt.Println("Reading file:", file) }
打開(kāi)文件常用方式二:os.OpenFile
在Go語(yǔ)言中,文件的讀寫(xiě)操作是使用非常頻繁的功能之一。os.OpenFile函數(shù)是Go標(biāo)準(zhǔn)庫(kù)中用于打開(kāi)文件的強(qiáng)大工具,它允許以多種模式打開(kāi)文件,并可以設(shè)置文件的權(quán)限。
os.OpenFile函數(shù)簡(jiǎn)介
os.OpenFile函數(shù)用法如下:
func OpenFile(name string, flag int, perm FileMode) (File, error)
name:要打開(kāi)的文件名或路徑。
flag:打開(kāi)文件的模式,可以是多個(gè)標(biāo)志的按位或組合。常見(jiàn)的標(biāo)志包括:
os.O_RDONLY:只讀模式。
os.O_WRONLY:只寫(xiě)模式。
os.O_RDWR:讀寫(xiě)模式。
os.O_APPEND:追加模式,在文件末尾寫(xiě)入數(shù)據(jù)而不覆蓋原有數(shù)據(jù)。只要有這個(gè)參數(shù),就會(huì)采用追加模式
os.O_CREATE:如果文件不存在則創(chuàng)建文件。
os.O_EXCL:與O_CREATE一起使用,可執(zhí)行權(quán)限。
os.O_SYNC:同步模式,將文件更改刷新到磁盤(pán)。
os.O_TRUNC:截?cái)嗄J?,清空文件?nèi)容。
perm:文件權(quán)限,表示文件的讀寫(xiě)權(quán)限,默認(rèn)為0666(即所有用戶都可讀寫(xiě))。
返回值是一個(gè)指向打開(kāi)文件的File對(duì)象和一個(gè)可能出現(xiàn)的錯(cuò)誤。如果文件打開(kāi)成功,則可以通過(guò)該文件對(duì)象進(jìn)行讀取和寫(xiě)入操作。
使用os.OpenFile寫(xiě)文件
以下是一個(gè)使用os.OpenFile函數(shù)寫(xiě)文件的示例:
package main import ( "fmt" "os" ) func main() { // 以追加、創(chuàng)建、讀寫(xiě)模式打開(kāi)文件 file, err := os.OpenFile("./example.txt", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666) if err != nil { fmt.Println("打開(kāi)文件失敗:", err) return } defer file.Close() // 確保在函數(shù)執(zhí)行完畢后關(guān)閉文件 // 寫(xiě)入文件 _, err = file.Write([]byte("Hello, Go!\n")) if err != nil { fmt.Println("寫(xiě)入文件失敗:", err) return } fmt.Println("文件寫(xiě)入成功") }
將內(nèi)容追加到文件中
1.6 讀取文件
使用os.File對(duì)象的Read方法可以從文件中讀取數(shù)據(jù)。Read方法會(huì)將數(shù)據(jù)讀取到一個(gè)字節(jié)切片中,并返回讀取的字節(jié)數(shù)和可能發(fā)生的錯(cuò)誤。
需要借助 file.Read([]byte)讀取 ,將file中的數(shù)據(jù)讀取到 []byte 中, n,err n讀取到的行數(shù),err 錯(cuò)誤,EOF錯(cuò)誤,就代表文件讀取完畢了
一直調(diào)用read,就代表光標(biāo)往后移動(dòng)…
以下是一個(gè)使用os.Open函數(shù)讀文件的示例:
package main import ( "fmt" "os" ) // 讀取文件數(shù)據(jù) func main() { // 我們習(xí)慣于在建立連接時(shí)候通過(guò)defer來(lái)關(guān)閉連接,保證程序不會(huì)出任何問(wèn)題,或者忘記關(guān)閉 // 建立連接 file, _ := os.Open("example.txt") // 關(guān)閉連接 defer file.Close() // 讀代碼 ,Go 的錯(cuò)誤機(jī)制,讓我們專心可以寫(xiě)業(yè)務(wù)代碼。 // 1、創(chuàng)建一個(gè)容器 (二進(jìn)制文本文件--0100101010 => 讀取流到一個(gè)容器 => 讀取容器的數(shù)據(jù)) //一次性讀取的內(nèi)容長(zhǎng)度為切片的長(zhǎng)度,切片長(zhǎng)度為2,容量為1024 bs := make([]byte, 2, 1024) // 緩沖區(qū),可以接受我們讀取的數(shù)據(jù) 這里設(shè)置的是一次性讀取兩個(gè)字節(jié) fmt.Printf("字節(jié)切片數(shù)據(jù)類型%T\n", bs) // 2、讀取到緩沖區(qū)中。 // 漢字一個(gè)漢字占 3個(gè)字節(jié) // func (f *File) Read(b []byte) (n int, err error) 返回讀到的字節(jié)數(shù)和錯(cuò)誤 // At end of file, Read returns 0, io.EOF. 讀到文件末尾返回0和io.EOF n, err := file.Read(bs) fmt.Println(n) fmt.Println(err) //每次讀取光標(biāo)移動(dòng)切片的長(zhǎng)度,將讀取的內(nèi)容存到切片中。如果讀取的文件是文本數(shù)據(jù),可以通過(guò)string方法將切片中的內(nèi)容轉(zhuǎn)換為字符串 //如果是MP4呀,音樂(lè),圖片等文件,就不要用string轉(zhuǎn)換了 fmt.Println(string(bs)) // 讀取到的字符串 ab //繼續(xù)往下讀 // 光標(biāo)不停的向下去指向,讀取出來(lái)的內(nèi)容就存到我們的容器中。 file.Read(bs) fmt.Println(string(bs)) // 讀取到的字符串 cd file.Read(bs) fmt.Println(string(bs)) // 讀取到的字符串 e //讀到文件末尾,得到的n是0,err是EOF n, err = file.Read(bs) fmt.Println(n) fmt.Println(err) // EOF ,讀取到了文件末尾。err就會(huì)返回EOF。 //最后讀到了e,將原來(lái)切片中的cd的c覆蓋了,得到的最終結(jié)果是ed fmt.Println(string(bs)) // 讀取到的字符串 }
1.7 IO寫(xiě)
寫(xiě)的話,要考慮文件的權(quán)限問(wèn)題,大致流程如下
建立連接 (設(shè)置權(quán)限:可讀可寫(xiě),擴(kuò)充這個(gè)文件的append) os.OpenFile
關(guān)閉連接
寫(xiě)入文件常用的方法
- file.Write
- file.WriteString
先看下example.txt文件
package main import ( "fmt" "os" ) func main() { fileName := "example.txt" // 權(quán)限:如果我們要向一個(gè)文件中追加內(nèi)容, O_APPEND, 如果沒(méi)有,就是從頭開(kāi)始寫(xiě) file, _ := os.OpenFile(fileName, os.O_WRONLY|os.O_RDONLY|os.O_APPEND, os.ModePerm) defer file.Close() // 操作 字節(jié)切片寫(xiě)入 bs := []byte{65, 66, 67, 68, 69} // A B C D E ASCII編碼 // func (f *File) Write(b []byte) (n int, err error) //write方法 寫(xiě)入的是二進(jìn)制數(shù)據(jù)字節(jié)流,即字節(jié)切片 n, err := file.Write(bs) if err != nil { fmt.Println(err) } fmt.Println(n) // string類型的寫(xiě)入,可以直接將字符串寫(xiě)入到文件中 n, err = file.WriteString("hhahahahah哈哈哈哈哈哈哈") if err != nil { fmt.Println(err) } fmt.Println(n) }
再看下example.txt文件,可以看到我們寫(xiě)入的內(nèi)容全部追加到文件末尾
如果打開(kāi)文件的方式不包含os.O_APPEND 則是將源文件覆蓋寫(xiě)。os.O_APPEND的意思是,在打開(kāi)文件時(shí),將光標(biāo)移動(dòng)到文件末尾
2. 目錄操作
2.1 創(chuàng)建目錄
Mkdir:使用指定的權(quán)限和名稱創(chuàng)建一個(gè)目錄,目錄存在會(huì)報(bào)錯(cuò)。
MkdirAll:遞歸創(chuàng)建目錄,包括任何必要的上級(jí)目錄,目錄存在不報(bào)錯(cuò)。
package main import ( "fmt" "os" ) func main() { // 創(chuàng)建單個(gè)目錄 // func Mkdir(name string, perm FileMode) error // os.ModePerm 是0777的權(quán)限 //mkidr創(chuàng)建目錄,目錄存在的情況下,會(huì)報(bào)錯(cuò) Cannot create a file when that file already exists. err := os.Mkdir("singledir", os.ModePerm) if err != nil { fmt.Println(err) } else { fmt.Println("Single directory created successfully") } // 遞歸創(chuàng)建目錄,目錄存在不報(bào)錯(cuò) // func MkdirAll(path string, perm FileMode) error err = os.MkdirAll("nested/dirs/test", os.ModePerm) if err != nil { fmt.Println(err) } else { fmt.Println("Nested directories created successfully") } }
2.2 更改當(dāng)前工作目錄
Getwd:獲取當(dāng)前工作目錄。
Chdir:修改當(dāng)前工作目錄。
package main import ( "fmt" "os" ) func main() { // 獲取當(dāng)前工作目錄 path, err := os.Getwd() if err != nil { fmt.Println(err) return } fmt.Println("Current working directory:", path) // 修改當(dāng)前工作目錄 err = os.Chdir("../") if err != nil { fmt.Println(err) return } path, err = os.Getwd() if err != nil { fmt.Println(err) return } fmt.Println("New working directory:", path) }
3. 環(huán)境變量
3.1 獲取環(huán)境變量
Environ:返回所有的環(huán)境變量,格式為“key=value”的字符串切片。
Getenv:檢索并返回名為key的環(huán)境變量的值,如果不存在則返回空字符串。
Setenv:
函數(shù)定義:func Setenv(key, value string) error
功能:設(shè)置名為key的環(huán)境變量,如果出錯(cuò)會(huì)返回該錯(cuò)誤。
package main import ( "fmt" "os" "strings" ) func main() { // 設(shè)置環(huán)境變量 err := os.Setenv("MY_ENV_VAR", "my_value") if err != nil { fmt.Println(err) } else { fmt.Println("Environment variable set successfully") } // 獲取并打印剛設(shè)置的環(huán)境變量 value := os.Getenv("MY_ENV_VAR") fmt.Println("MY_ENV_VAR:", value) //查看所有環(huán)境變量 envs := os.Environ() for _, env := range envs { cache := strings.Split(env, "=") fmt.Printf("key=%v value=%v\n", cache[0], cache[1]) } // 清除所有環(huán)境變量(謹(jǐn)慎使用) // err = os.Clearenv() // if err != nil { // fmt.Println(err) // } else { // fmt.Println("All environment variables cleared") // } }
4. 程序退出
Exit:讓當(dāng)前程序以給出的狀態(tài)碼code退出。一般來(lái)說(shuō),狀態(tài)碼0表示成功,非0表示出錯(cuò)。程序會(huì)立刻終止,并且defer的函數(shù)不會(huì)被執(zhí)行。
package main import ( "fmt" "os" ) func main() { // 正常退出 fmt.Println("Exiting the program successfully") //os.Exit(0) // 異常退出(不會(huì)執(zhí)行到這里的代碼) fmt.Println("This line will not be executed") os.Exit(1) }
5. 獲取系統(tǒng)信息
Hostname:返回內(nèi)核提供的主機(jī)名。
Getuid:返回調(diào)用者的用戶ID。
Getgid:返回調(diào)用者的組ID。
Getpid:返回調(diào)用者所在進(jìn)程的進(jìn)程ID。
package main import ( "fmt" "os" ) func main() { // 獲取主機(jī)名 hostname, err := os.Hostname() if err != nil { fmt.Println(err) return } fmt.Println("Hostname:", hostname) // 獲取用戶ID uid := os.Getuid() fmt.Println("User ID:", uid) // 獲取組ID gid := os.Getgid() fmt.Println("Group ID:", gid) // 獲取進(jìn)程ID pid := os.Getpid() fmt.Println("Process ID:", pid) }
6. 執(zhí)行外部命令
os/exec包用于執(zhí)行外部命令,它提供了更高級(jí)別的接口來(lái)創(chuàng)建和管理進(jìn)程。
1. 執(zhí)行簡(jiǎn)單命令
package main import ( "fmt" "os/exec" ) func main() { //查看系統(tǒng)中是否安裝有該命令 cmd_path, err := exec.LookPath("ipconfig") if err != nil { fmt.Println(err) return } fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path) //Command每個(gè)參數(shù)都不能包含空格。多個(gè)參數(shù),用引號(hào)包裹,逗號(hào)隔開(kāi) cmd := exec.Command("ipconfig") // 如果不需要命令的輸出,直接調(diào)用cmd.Run()即可 err2 := cmd.Run() if err2 != nil { fmt.Println("Error:", err2) } else { fmt.Println("Command executed successfully") } }
使用exec.Command函數(shù)創(chuàng)建一個(gè)代表外部命令的Cmd對(duì)象,然后使用Run方法執(zhí)行命令并等待其完成。
我們使用 exec.Command() 創(chuàng)建了一個(gè)執(zhí)行 ipconfig 命令的 *exec.Cmd,然后使用 Run() 方法啟動(dòng)了命令。
請(qǐng)注意,使用 exec.Command() 創(chuàng)建的命令默認(rèn)不會(huì)有任何輸出。如果我們想獲取命令的標(biāo)準(zhǔn)輸出,我們可以使用 Output() 或 CombinedOutput() 方法。如果我們想獲取命令的標(biāo)準(zhǔn)錯(cuò)誤輸出,我們需要單獨(dú)設(shè)置 Cmd.Stderr 字段。
2. 獲取命令輸出
使用Output方法運(yùn)行命令并返回其標(biāo)準(zhǔn)輸出的內(nèi)容。
package main import ( "fmt" "os/exec" ) func main() { //查看系統(tǒng)中是否安裝有該命令 cmd_path, err := exec.LookPath("ipconfig") if err != nil { fmt.Println(err) return } fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path) cmd := exec.Command("ipconfig") output, err := cmd.Output() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Command output:", string(output)) } }
3. 處理標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
CombinedOutput
func (c *Cmd) CombinedOutput() ([]byte, error)
說(shuō)明:運(yùn)行命令并返回組合到一起的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
package main import ( "fmt" "os/exec" ) func main() { //查看系統(tǒng)中是否安裝有該命令 cmd_path, err := exec.LookPath("ping") if err != nil { fmt.Println(err) return } fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path) // 創(chuàng)建一個(gè)新的命令,例如運(yùn)行dir命令 cmd := exec.Command("ping", "www.baidu.com") //獲取標(biāo)準(zhǔn)輸出 out, err := cmd.CombinedOutput() if err != nil { fmt.Println(err) return } fmt.Println("標(biāo)準(zhǔn)輸出為:", string(out)) }
三、文件復(fù)制
文件復(fù)制需要考慮的問(wèn)題:
1、拿到需求,分析需求,編輯函數(shù) copy()
2、編寫(xiě)參數(shù)(源文件,目標(biāo)地址,緩沖區(qū)大小)
3、讀取源文件,保存到緩沖區(qū)中
4、讀取緩沖區(qū)的內(nèi)容,將內(nèi)容寫(xiě)入到新文件中
5、確保源文件讀取完畢了,使用到for()循環(huán)。循環(huán)結(jié)束標(biāo)志 io.EOF或者讀取到的字節(jié)數(shù)為0
1. 自定義的文件復(fù)制實(shí)現(xiàn)
我們創(chuàng)建個(gè)目錄utils。里面創(chuàng)建個(gè)copy.go
package utils import ( "fmt" "io" "os" ) // Copy 方法需要參數(shù)為:source 源文件 ,destination 目標(biāo)文件,緩沖區(qū)大小 func Copy(source, destination string, bufferSize int) { // 讀取文件,讀文件open方法就可以 sourceFile, err := os.Open(source) if err != nil { fmt.Println("Open錯(cuò)誤:", err) } // 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建 destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm) if err != nil { fmt.Println("OpenFile錯(cuò)誤:", err) } // 關(guān)閉連接 defer sourceFile.Close() defer destinationFile.Close() // 專注業(yè)務(wù)代碼,拷貝 // 創(chuàng)建緩沖區(qū)大小 buf := make([]byte, bufferSize) // 循環(huán)讀取,寫(xiě)入 for { //一次讀取設(shè)置的緩沖區(qū)大小的數(shù)據(jù) n, err := sourceFile.Read(buf) // 循環(huán)結(jié)束標(biāo)志 if n == 0 || err == io.EOF { fmt.Println("讀取完畢源文件,復(fù)制完畢") break } else if err != nil { fmt.Println("讀取錯(cuò)誤:", err) return // 錯(cuò)誤之后,必須要return終止函數(shù)執(zhí)行。 } // 將緩沖區(qū)的東西寫(xiě)出到目標(biāo)文件 // 因?yàn)檠h(huán)寫(xiě)入過(guò)程中沒(méi)有關(guān)閉文件,所以可以持續(xù)寫(xiě)入 //根據(jù)實(shí)際讀取的長(zhǎng)度寫(xiě)入,防止最后一次讀取時(shí),讀取的少于緩沖區(qū)長(zhǎng)度 _, err = destinationFile.Write(buf[:n]) if err != nil { fmt.Println("寫(xiě)出錯(cuò)誤:", err) } } }
調(diào)用我們的copy方法,實(shí)現(xiàn)文件copy
package main import "jingtian/yufa/io操作/utils" func main() { source := "C:\\Users\\dell\\Desktop\\appsearch.zip" dest := "F:\\goworks\\src\\jingtian\\yufa\\io操作\\目標(biāo)文件.zip" utils.Copy(source, dest, 1024) }
運(yùn)行,可以將源文件復(fù)制到目標(biāo)地址
2. 使用系統(tǒng)自帶的io.Copy()方法復(fù)制
// Copy2 使用系統(tǒng)自帶的io.Copy方法 func Copy2(source, destination string) { // 讀取文件 sourceFile, err := os.Open(source) if err != nil { fmt.Println("Open錯(cuò)誤:", err) } // 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建 destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm) if err != nil { fmt.Println("OpenFile錯(cuò)誤:", err) } // 關(guān)閉 defer sourceFile.Close() defer destinationFile.Close() // 具體的實(shí)現(xiàn) // 不用我們自己寫(xiě)循環(huán)讀取寫(xiě)入了,直接調(diào)用系統(tǒng)的io.Copy()方法 // func Copy(dst Writer, src Reader) (written int64, err error) 返回寫(xiě)入的字節(jié)數(shù)和錯(cuò)誤 written, err := io.Copy(destinationFile, sourceFile) if err != nil { fmt.Println("復(fù)制時(shí)出現(xiàn)錯(cuò)誤", err) return } fmt.Println("文件的字節(jié)大小:", written) }
3. 使用os.ReadFile和os.WriteFile來(lái)實(shí)現(xiàn)讀取寫(xiě)入,從而實(shí)現(xiàn)復(fù)制
// Copy3 使用os.ReadFile和os.WriteFile來(lái)實(shí)現(xiàn)讀取寫(xiě)入,從而實(shí)現(xiàn)復(fù)制 func Copy3(source, destination string) { // func ReadFile(name string) ([]byte, error) fileBuffer, _ := os.ReadFile(source) //func WriteFile(name string, data []byte, perm FileMode) error err := os.WriteFile(destination, fileBuffer, 0644) if err != nil { fmt.Println(err) return } fmt.Println("文件復(fù)制完成") }
4. io.CopyBuffer() 適合大文件復(fù)制
// Copy4 io.CopyBuffer() 適合大文件 func Copy4(source, destination string, bufferSize int) { // 讀取文件 sourceFile, err := os.Open(source) if err != nil { fmt.Println("Open錯(cuò)誤:", err) } // 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建 destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm) if err != nil { fmt.Println("OpenFile錯(cuò)誤:", err) } // 關(guān)閉 defer sourceFile.Close() defer destinationFile.Close() // 具體的實(shí)現(xiàn) // 創(chuàng)建緩沖區(qū)大小 buf := make([]byte, bufferSize) // 不用我們自己寫(xiě)循環(huán)讀取寫(xiě)入了,直接調(diào)用系統(tǒng)的io.Copy()方法 //io.copy這個(gè)適合小文件,大文件使用io.CopyBuffer // func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) written, err := io.CopyBuffer(destinationFile, sourceFile, buf) if err != nil { fmt.Println("復(fù)制時(shí)出現(xiàn)錯(cuò)誤", err) return } fmt.Println("文件的字節(jié)大小:", written) }
以上就是關(guān)于Go語(yǔ)言中的IO操作詳解的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言IO操作的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go?modules?replace解決Go依賴引用問(wèn)題
這篇文章主要為大家介紹了Go?modules?replace解決Go依賴引用問(wèn)題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Golang中的關(guān)鍵字(defer、:=、go?func())詳細(xì)解讀
這篇文章主要介紹了Golang中的關(guān)鍵字(defer、:=、go?func())詳細(xì)解讀,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04golang中的io.ReadCloser與ioutil.NopCloser使用
這篇文章主要介紹了golang中的io.ReadCloser與ioutil.NopCloser使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03Go語(yǔ)言調(diào)用ffmpeg-api實(shí)現(xiàn)音頻重采樣
最近對(duì)golang處理音視頻很感興趣,對(duì)golang音視頻常用庫(kù)goav進(jìn)行了一番研究。自己寫(xiě)了一個(gè)wav轉(zhuǎn)采樣率的功能。給大家分享一下,中間遇到了不少坑,解決的過(guò)程中還是蠻有意思的,希望大家能喜歡2022-12-12