Go语言 将文本文件读入字符串数组(并写入)

lo8azlld  于 2023-08-01  发布在  Go
关注(0)|答案(6)|浏览(142)

我认为,在字符串数组中读写文本文件的能力是一个相当常见的需求。当从一种语言开始时,它也非常有用,最初不需要访问数据库。有一个在Golang吗?
例如。

func ReadLines(sFileName string, iMinLines int) ([]string, bool) {

字符串
和/或

func WriteLines(saBuff[]string, sFilename string) (bool) {


我宁愿使用现有的一个,而不是重复。

pb3skfrl

pb3skfrl1#

从Go1.1版本开始,有一个bufio.Scanner API可以轻松地从文件中读取行。考虑上面的以下示例,用Scanner重写:

package main

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

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var lines []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
    }
    return lines, scanner.Err()
}

// writeLines writes the lines to the given file.
func writeLines(lines []string, path string) error {
    file, err := os.Create(path)
    if err != nil {
        return err
    }
    defer file.Close()

    w := bufio.NewWriter(file)
    for _, line := range lines {
        fmt.Fprintln(w, line)
    }
    return w.Flush()
}

func main() {
    lines, err := readLines("foo.in.txt")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    for i, line := range lines {
        fmt.Println(i, line)
    }

    if err := writeLines(lines, "foo.out.txt"); err != nil {
        log.Fatalf("writeLines: %s", err)
    }
}

字符串

8i9zcol2

8i9zcol22#

注意:ioutil从Go 1.16开始被弃用。

如果文件不是太大,可以使用ioutil.ReadFilestrings.Split函数来完成:

content, err := ioutil.ReadFile(filename)
if err != nil {
    //Do something
}
lines := strings.Split(string(content), "\n")

字符串
您可以阅读有关ioutilstrings软件包的文档。

vktxenjb

vktxenjb3#

无法更新第一个答案。
无论如何,在Go1发布后,有一些突破性的变化,所以我更新了如下所示:

package main

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

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 0))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == io.EOF {
        err = nil
    }
    return
}

func writeLines(lines []string, path string) (err error) {
    var (
        file *os.File
    )

    if file, err = os.Create(path); err != nil {
        return
    }
    defer file.Close()

    //writer := bufio.NewWriter(file)
    for _,item := range lines {
        //fmt.Println(item)
        _, err := file.WriteString(strings.TrimSpace(item) + "\n"); 
        //file.Write([]byte(item)); 
        if err != nil {
            //fmt.Println("debug")
            fmt.Println(err)
            break
        }
    }
    /*content := strings.Join(lines, "\n")
    _, err = writer.WriteString(content)*/
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
    //array := []string{"7.0", "8.5", "9.1"}
    err = writeLines(lines, "foo2.txt")
    fmt.Println(err)
}

字符串

eivgtgni

eivgtgni4#

您可以将os.File(它实现了io.Reader接口)与bufio包一起使用。但是,这些包是在考虑固定内存使用的情况下构建的(无论文件有多大),并且速度相当快。
不幸的是,这使得将整个文件读入内存变得有点复杂。如果行的各个部分超过行限制,则可以使用bytes.Buffer来连接它们。无论如何,我建议你尝试在你的项目中直接使用行阅读器(特别是如果不知道文本文件有多大!)。但如果文件很小,下面的示例可能就足够了:

package main

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

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err os.Error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 1024))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == os.EOF {
        err = nil
    }
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
}

字符串
另一种方法是使用io.ioutil.ReadAll一次读入整个文件,然后逐行切片。我没有给予一个如何将行写回文件的显式示例,但这基本上是一个os.Create(),后面跟着一个类似于示例中的循环(参见main())。

bf1o4zei

bf1o4zei5#

func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    reader := bufio.NewReader(f)
    contents, _ := ioutil.ReadAll(reader)
    lines := strings.Split(string(contents), '\n')
}

字符串

func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    slice := make([]string,0)

    reader := bufio.NewReader(f)

    for{

    str, err := reader.ReadString('\n')
    if err == io.EOF{
        break
    }

        slice = append(slice, str)
    }

ovfsdjhp

ovfsdjhp6#

我更喜欢写一个更简单的泛型函数来读取io.Reader(由任何可读数据流实现的泛型接口,包括文件,内存缓冲区,字符串和字节片,http请求体等)

func ReadLines(r io.Reader) ([]string, error) {
    var lines []string
    s := bufio.NewScanner(r)
    for s.Scan() {
        lines = append(lines, s.Text())
    }
    if err := s.Err(); err != nil {
        return nil, err
    }
    return lines, nil
}

字符串
它与字符串一起使用的示例。

const data = `
line 1
line 2
line 3  
`

lines, _ := ReadLines(strings.NewReader(data))
fmt.Println(lines)


在这里运行:https://go.dev/play/p/NcbEIVmGXpX

相关问题