将文本文件读入string数组(并写入)
读取(和写入)文本文件进出string数组的能力是我相信一个相当普遍的要求。 当从一种语言开始删除最初访问数据库的需要时,这也是非常有用的。 Golang是否存在?
例如func ReadLines(sFileName string, iMinLines int) ([]string, bool) {
和func WriteLines(saBuff[]string, sFilename string) (bool) {
。
我宁愿使用现有的而不是重复。
从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) } }
如果文件不是太大,可以使用ioutil.ReadFile
和strings.Split
函数来完成,如下ioutil.ReadFile
:
content, err := ioutil.ReadFile(filename) if err != nil { //Do something } lines := strings.Split(string(content), "\n")
您可以阅读关于ioutil和string包的文档。
无法更新第一个答案。
无论如何,在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) }
你可以使用os.File (它实现了io.Reader接口)和bufio包。 但是,这些软件包是build立在固定的内存使用情况下(无论文件有多大),而且速度相当快。
不幸的是,这使得将整个文件读入内存有点复杂。 如果超过行限制,可以使用bytes.Buffer来join行的部分。 无论如何,我build议你尝试直接在你的项目中使用线阅读器(特别是如果不知道文本文件有多大!)。 但是如果文件很小,下面的例子可能就足够了:
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()
)。
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) }