Чтение текстового файла в массив строк (и запись)
возможность чтения (и записи) текстового файла в строковый массив и из него я считаю довольно распространенным требованием. Это также очень полезно при запуске с языка, удаляющего необходимость первоначально обращаться к базе данных. Нет в Golang?
например,
func ReadLines(sFileName string, iMinLines int) ([]string, bool) {
и
func WriteLines(saBuff[]string, sFilename string) (bool) {
Я бы предпочел использовать уже существующий, а не дублировать.
5 ответов:
по состоянию на Go1.1 релиз, есть bufio.Сканер API, который может легко читать строки из файла. Рассмотрим следующий пример сверху, переписанный с помощью сканера:
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) } }
Не удается обновить первый ответ.
В любом случае, после выпуска 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) }
можно использовать ОС.Файл (реализующий io.Читатель интерфейс) с bufio пакет для этого. Однако эти пакеты строятся с фиксированным использованием памяти (независимо от размера файла) и довольно быстро.
к сожалению, это делает чтение всего файла в память немного сложнее. Вы можете использовать байт.Буфер для соединения частей линии, если они превышают предел линии. Во Всяком Случае, Я рекомендуем попробовать использовать line reader непосредственно в вашем проекте (особенно если не знаете, насколько велик текстовый файл!). Но если файл небольшой, то вам может быть достаточно следующего примера:
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) }
Comments