首页 文章

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

提问于
浏览
84

能够将文本文件读入(或写入)字符串数组的能力是我认为相当普遍的要求 . 当从最初需要访问数据库的语言开始时,它也非常有用 . Golang中是否存在一个?
例如

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

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

我宁愿使用现有的而不是复制 .

5 回答

  • 108

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

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

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

    您可以阅读ioutilstrings包中的文档 .

  • 30

    无法更新第一个答案 .
    无论如何,在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)
    }
    
  • 2

    您可以使用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一次读取整个文件,然后按行进行切片 . 我基本上不是't give you an explicit example of how to write the lines back to the file, but that',后跟一个类似于示例中的循环(参见 main() ) .

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

相关问题