在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 12.2 文件讀寫(xiě)
4.7 strings 和 strconv 包
13.6 啟動(dòng)外部命令和程序
?# 11.4 類(lèi)型判斷:type-switch
12.1 讀取用戶(hù)的輸入
10.6 方法
12.2 文件讀寫(xiě)
13 錯(cuò)誤處理與測(cè)試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個(gè)例子:使用 Sorter 接口排序
?# 11.5 測(cè)試一個(gè)值是否實(shí)現(xiàn)了某個(gè)接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語(yǔ)言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時(shí)異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說(shuō)明
7.2 切片
8.0 Map
3.1 Go 開(kāi)發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見(jiàn)性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測(cè)試和基準(zhǔn)測(cè)試
6.8 閉包
4.9 指針
13.1 錯(cuò)誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過(guò) Git 打包和安裝
2.7 Go 運(yùn)行時(shí)(runtime)
10.7 類(lèi)型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動(dòng)態(tài)類(lèi)型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識(shí)符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對(duì)調(diào)
6.11 計(jì)算函數(shù)執(zhí)行時(shí)間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開(kāi)發(fā)環(huán)境與其它工具
13.8 測(cè)試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類(lèi)型的切片
3.9 與其它語(yǔ)言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長(zhǎng)參數(shù)
13.9 用(測(cè)試數(shù)據(jù))表驅(qū)動(dòng)測(cè)試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫(kù)
3.3 調(diào)試器
4.5 基本類(lèi)型和運(yùn)算符
?# 11.8 第二個(gè)例子:讀和寫(xiě)
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計(jì)算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯(cuò)誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類(lèi)型斷言:如何檢測(cè)和轉(zhuǎn)換接口變量的類(lèi)型
5.4 for 結(jié)構(gòu)
4.8 時(shí)間和日期
2.3 在 Linux 上安裝 Go
12 讀寫(xiě)數(shù)據(jù)
6.12 通過(guò)內(nèi)存緩存來(lái)提升性能
9.1 標(biāo)準(zhǔn)庫(kù)概述
12.6 用切片讀寫(xiě)文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯(cuò)誤的模式
3.2 編輯器和集成開(kāi)發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測(cè)試多返回值函數(shù)的錯(cuò)誤
6.7 將函數(shù)作為參數(shù)
8.2 測(cè)試鍵值對(duì)是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺(tái)與架構(gòu)
5.3 switch 結(jié)構(gòu)

12.2 文件讀寫(xiě)

12.2.1 讀文件

在 Go 語(yǔ)言中,文件使用指向 os.File 類(lèi)型的指針來(lái)表示的,也叫做文件句柄。我們?cè)谇懊嬲鹿?jié)使用到過(guò)標(biāo)準(zhǔn)輸入 os.Stdin 和標(biāo)準(zhǔn)輸出 os.Stdout,他們的類(lèi)型都是 *os.File。讓我們來(lái)看看下面這個(gè)程序:

示例 12.4 fileinput.go

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

func main() {
    inputFile, inputError := os.Open("input.dat")
    if inputError != nil {
        fmt.Printf("An error occurred on opening the inputfile\n" +
            "Does the file exist?\n" +
            "Have you got acces to it?\n")
        return // exit the function on error
    }
    defer inputFile.Close()

    inputReader := bufio.NewReader(inputFile)
    for {
        inputString, readerError := inputReader.ReadString('\n')
        fmt.Printf("The input was: %s", inputString)
        if readerError == io.EOF {
            return
        }      
    }
}

變量 inputFile*os.File 類(lèi)型的。該類(lèi)型是一個(gè)結(jié)構(gòu),表示一個(gè)打開(kāi)文件的描述符(文件句柄)。然后,使用 os 包里的 Open 函數(shù)來(lái)打開(kāi)一個(gè)文件。該函數(shù)的參數(shù)是文件名,類(lèi)型為 string。在上面的程序中,我們以只讀模式打開(kāi) input.dat 文件。

如果文件不存在或者程序沒(méi)有足夠的權(quán)限打開(kāi)這個(gè)文件,Open函數(shù)會(huì)返回一個(gè)錯(cuò)誤:inputFile, inputError = os.Open("input.dat")。如果文件打開(kāi)正常,我們就使用 defer inputFile.Close() 語(yǔ)句確保在程序退出前關(guān)閉該文件。然后,我們使用 bufio.NewReader 來(lái)獲得一個(gè)讀取器變量。

通過(guò)使用 bufio 包提供的讀取器(寫(xiě)入器也類(lèi)似),如上面程序所示,我們可以很方便的操作相對(duì)高層的 string 對(duì)象,而避免了去操作比較底層的字節(jié)。

接著,我們?cè)谝粋€(gè)無(wú)限循環(huán)中使用 ReadString('\n')ReadBytes('\n') 將文件的內(nèi)容逐行(行結(jié)束符 '\n')讀取出來(lái)。

注意: 在之前的例子中,我們看到,Unix和Linux的行結(jié)束符是 \n,而Windows的行結(jié)束符是 \r\n。在使用 ReadStringReadBytes 方法的時(shí)候,我們不需要關(guān)心操作系統(tǒng)的類(lèi)型,直接使用 \n 就可以了。另外,我們也可以使用 ReadLine() 方法來(lái)實(shí)現(xiàn)相同的功能。

一旦讀取到文件末尾,變量 readerError 的值將變成非空(事實(shí)上,常量 io.EOF 的值是 true),我們就會(huì)執(zhí)行 return 語(yǔ)句從而退出循環(huán)。

其他類(lèi)似函數(shù):

1) 將整個(gè)文件的內(nèi)容讀到一個(gè)字符串里:

如果您想這么做,可以使用 io/ioutil 包里的 ioutil.ReadFile() 方法,該方法第一個(gè)返回值的類(lèi)型是 []byte,里面存放讀取到的內(nèi)容,第二個(gè)返回值是錯(cuò)誤,如果沒(méi)有錯(cuò)誤發(fā)生,第二個(gè)返回值為 nil。請(qǐng)看示例 12.5。類(lèi)似的,函數(shù) WriteFile() 可以將 []byte 的值寫(xiě)入文件。

示例 12.5 read_write_file1.go

package main
import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    inputFile := "products.txt"
    outputFile := "products_copy.txt"
    buf, err := ioutil.ReadFile(inputFile)
    if err != nil {
        fmt.Fprintf(os.Stderr, "File Error: %s\n", err)
        // panic(err.Error())
    }
    fmt.Printf("%s\n", string(buf))
    err = ioutil.WriteFile(outputFile, buf, 0644) // oct, not hex
    if err != nil {
        panic(err.Error())
    }
}

2) 帶緩沖的讀取

在很多情況下,文件的內(nèi)容是不按行劃分的,或者干脆就是一個(gè)二進(jìn)制文件。在這種情況下,ReadString()就無(wú)法使用了,我們可以使用 bufio.ReaderRead(),它只接收一個(gè)參數(shù):

buf := make([]byte, 1024)
...
n, err := inputReader.Read(buf)
if (n == 0) { break}

變量 n 的值表示讀取到的字節(jié)數(shù).

3) 按列讀取文件中的數(shù)據(jù)

如果數(shù)據(jù)是按列排列并用空格分隔的,你可以使用 fmt 包提供的以 FScan 開(kāi)頭的一系列函數(shù)來(lái)讀取他們。請(qǐng)看以下程序,我們將 3 列的數(shù)據(jù)分別讀入變量 v1、v2 和 v3 內(nèi),然后分別把他們添加到切片的尾部。

示例 12.6 read_file2.go

package main
import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("products2.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var col1, col2, col3 []string
    for {
        var v1, v2, v3 string
        _, err := fmt.Fscanln(file, &v1, &v2, &v3)
        // scans until newline
        if err != nil {
            break
        }
        col1 = append(col1, v1)
        col2 = append(col2, v2)
        col3 = append(col3, v3)
    }

    fmt.Println(col1)
    fmt.Println(col2)
    fmt.Println(col3)
}

輸出結(jié)果:

[ABC FUNC GO]
[40 56 45]
[150 280 356]

注意: path 包里包含一個(gè)子包叫 filepath,這個(gè)子包提供了跨平臺(tái)的函數(shù),用于處理文件名和路徑。例如 Base() 函數(shù)用于獲得路徑中的最后一個(gè)元素(不包含后面的分隔符):

import "path/filepath"
filename := filepath.Base(path)

練習(xí) 12.3read_csv.go

文件 products.txt 的內(nèi)容如下:

"The ABC of Go";25.5;1500
"Functional Programming with Go";56;280
"Go for It";45.9;356
"The Go Way";55;500

每行的第一個(gè)字段為 title,第二個(gè)字段為 price,第三個(gè)字段為 quantity。內(nèi)容的格式基本與 示例 12.3c 的相同,除了分隔符改成了分號(hào)。請(qǐng)讀取出文件的內(nèi)容,創(chuàng)建一個(gè)結(jié)構(gòu)用于存取一行的數(shù)據(jù),然后使用結(jié)構(gòu)的切片,并把數(shù)據(jù)打印出來(lái)。

關(guān)于解析 CSV 文件,encoding/csv 包提供了相應(yīng)的功能。具體請(qǐng)參考 http://golang.org/pkg/encoding/csv/

12.2.2 compress包:讀取壓縮文件

compress包提供了讀取壓縮文件的功能,支持的壓縮文件格式為:bzip2、flate、gzip、lzw 和 zlib。

下面的程序展示了如何讀取一個(gè) gzip 文件。

示例 12.7 gzipped.go

package main

import (
    "fmt"
    "bufio"
    "os"
    "compress/gzip"
)

func main() {
    fName := "MyFile.gz"
    var r *bufio.Reader
    fi, err := os.Open(fName)
    if err != nil {
        fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName,
            err)
        os.Exit(1)
    }
    fz, err := gzip.NewReader(fi)
    if err != nil {
        r = bufio.NewReader(fi)
    } else {
        r = bufio.NewReader(fz)
    }

    for {
        line, err := r.ReadString('\n')
        if err != nil {
            fmt.Println("Done reading file")
            os.Exit(0)
        }
        fmt.Println(line)
    }
}

12.2.3 寫(xiě)文件

請(qǐng)看以下程序:

示例 12.8 fileoutput.go

package main

import (
    "os"
    "bufio"
    "fmt"
)

func main () {
    // var outputWriter *bufio.Writer
    // var outputFile *os.File
    // var outputError os.Error
    // var outputString string
    outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)
    if outputError != nil {
        fmt.Printf("An error occurred with file opening or creation\n")
        return  
    }
    defer outputFile.Close()

    outputWriter := bufio.NewWriter(outputFile)
    outputString := "hello world!\n"

    for i:=0; i<10; i++ {
        outputWriter.WriteString(outputString)
    }
    outputWriter.Flush()
}

除了文件句柄,我們還需要 bufioWriter。我們以只寫(xiě)模式打開(kāi)文件 output.dat,如果文件不存在則自動(dòng)創(chuàng)建:

outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)

可以看到,OpenFile 函數(shù)有三個(gè)參數(shù):文件名、一個(gè)或多個(gè)標(biāo)志(使用邏輯運(yùn)算符“|”連接),使用的文件權(quán)限。

我們通常會(huì)用到以下標(biāo)志:

  • os.O_RDONLY:只讀
  • os.O_WRONLY:只寫(xiě)
  • os.O_CREATE:創(chuàng)建:如果指定文件不存在,就創(chuàng)建該文件。
  • os.O_TRUNC:截?cái)啵喝绻付ㄎ募汛嬖?,就將該文件的長(zhǎng)度截為0。

在讀文件的時(shí)候,文件的權(quán)限是被忽略的,所以在使用 OpenFile 時(shí)傳入的第三個(gè)參數(shù)可以用0。而在寫(xiě)文件時(shí),不管是 Unix 還是 Windows,都需要使用 0666。

然后,我們創(chuàng)建一個(gè)寫(xiě)入器(緩沖區(qū))對(duì)象:

outputWriter := bufio.NewWriter(outputFile)

接著,使用一個(gè) for 循環(huán),將字符串寫(xiě)入緩沖區(qū),寫(xiě) 10 次:outputWriter.WriteString(outputString)

緩沖區(qū)的內(nèi)容緊接著被完全寫(xiě)入文件:outputWriter.Flush()

如果寫(xiě)入的東西很簡(jiǎn)單,我們可以使用 fmt.Fprintf(outputFile, "Some test data.\n") 直接將內(nèi)容寫(xiě)入文件。fmt 包里的 F 開(kāi)頭的 Print 函數(shù)可以直接寫(xiě)入任何 io.Writer,包括文件(請(qǐng)參考章節(jié)12.8)。

程序 filewrite.go 展示了不使用 fmt.FPrintf 函數(shù),使用其他函數(shù)如何寫(xiě)文件:

示例 12.8 filewrite.go

package main

import "os"

func main() {
    os.Stdout.WriteString("hello, world\n")
    f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0666)
    defer f.Close()
    f.WriteString("hello, world in a file\n")
}

使用 os.Stdout.WriteString("hello, world\n"),我們可以輸出到屏幕。

我們以只寫(xiě)模式創(chuàng)建或打開(kāi)文件"test",并且忽略了可能發(fā)生的錯(cuò)誤:f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0666)

我們不使用緩沖區(qū),直接將內(nèi)容寫(xiě)入文件:f.WriteString( )

練習(xí) 12.4wiki_part1.go

(這是一個(gè)獨(dú)立的練習(xí),但是同時(shí)也是為章節(jié)15.4做準(zhǔn)備)

程序中的數(shù)據(jù)結(jié)構(gòu)如下,是一個(gè)包含以下字段的結(jié)構(gòu):

type Page struct {
    Title string
    Body  []byte
}

請(qǐng)給這個(gè)結(jié)構(gòu)編寫(xiě)一個(gè) save 方法,將 Title 作為文件名、Body作為文件內(nèi)容,寫(xiě)入到文本文件中。

再編寫(xiě)一個(gè) load 函數(shù),接收的參數(shù)是字符串 title,該函數(shù)讀取出與 title 對(duì)應(yīng)的文本文件。請(qǐng)使用 *Page 做為參數(shù),因?yàn)檫@個(gè)結(jié)構(gòu)可能相當(dāng)巨大,我們不想在內(nèi)存中拷貝它。請(qǐng)使用 ioutil 包里的函數(shù)(參考章節(jié)12.2.1)。

鏈接