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

发布于 2024-11-05 08:04:36 字数 307 浏览 3 评论 0原文

我相信将文本文件读入(和写出)字符串数组的能力是一个相当常见的要求。当开始使用一种语言时,它也非常有用,消除了最初访问数据库的需要。 Golang 中存在吗?
例如

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

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

我更愿意使用现有的而不是重复的。

The ability to read (and write) a text file into and out of a string array is I believe a fairly common requirement. It is also quite useful when starting with a language removing the need initially to access a database. Does one exist in Golang?
e.g.

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

and

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

I would prefer to use an existing one rather than duplicate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

病女 2024-11-12 08:04:36

从 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)
    }
}

As of Go1.1 release, there is a bufio.Scanner API that can easily read lines from a file. Consider the following example from above, rewritten with 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)
    }
}
梦一生花开无言 2024-11-12 08:04:36

如果文件不太大,可以使用 ioutil.ReadFile/os.ReadFile 和 strings.Split 函数来完成,如下所示:

Go 1.16 之前

ioutil 从 Go 1.16 开始已被弃用。

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

Go1.16 或更高版本

从 Go 1.16 开始,您可以应用完全相同的代码,但使用 os 而不是 ioutil

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

您可以阅读 ioutilos 和 <一个href="https://pkg.go.dev/os" rel="nofollow noreferrer">字符串 包。

If the file isn't too large, this can be done with the ioutil.ReadFile/os.ReadFile and strings.Split functions like so:

Before Go 1.16

ioutil is deprecated as of Go 1.16.

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

Go1.16 or later

Starting with Go 1.16 you can apply the very same code, but utilizing os over ioutil.

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

You can read the documentation on ioutil, os, and strings packages.

一抹苦笑 2024-11-12 08:04:36

无法更新第一个答案。
不管怎样,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)
}

Cannot update first answer.
Anyway, after Go1 release, there are some breaking changes, so I updated as shown below:

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)
}
眼眸印温柔 2024-11-12 08:04:36

您可以使用 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())。

You can use os.File (which implements the io.Reader interface) with the bufio package for that. However, those packages are build with fixed memory usage in mind (no matter how large the file is) and are quite fast.

Unfortunately this makes reading the whole file into the memory a bit more complicated. You can use a bytes.Buffer to join the parts of the line if they exceed the line limit. Anyway, I recommend you to try to use the line reader directly in your project (especially if do not know how large the text file is!). But if the file is small, the following example might be sufficient for you:

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)
    }
}

Another alternative might be to use io.ioutil.ReadAll to read in the complete file at once and do the slicing by line afterwards. I don't give you an explicit example of how to write the lines back to the file, but that's basically an os.Create() followed by a loop similar to that one in the example (see main()).

悲喜皆因你 2024-11-12 08:04:36
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)
    }
func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    reader := bufio.NewReader(f)
    contents, _ := ioutil.ReadAll(reader)
    lines := strings.Split(string(contents), '\n')
}

or

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)
    }
烂柯人 2024-11-12 08:04:36

我更喜欢编写一个更简单的通用函数来从 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

I prefer to write a simpler generic function to read from an io.Reader (the generic interface implemented by any readable data stream including files, memory buffers, strings and byte slices, http request body etc.

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
}

Example of its use with a string.

const data = `
line 1
line 2
line 3  
`

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

run it here: https://go.dev/play/p/NcbEIVmGXpX

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文