88

Khả năng đọc (và ghi) một tệp văn bản vào và ra khỏi một chuỗi chuỗi là tôi tin rằng một yêu cầu khá phổ biến. Nó cũng khá hữu ích khi bắt đầu với một ngôn ngữ loại bỏ nhu cầu ban đầu để truy cập cơ sở dữ liệu. Có ai tồn tại ở Golang không?
ví dụ

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

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

Tôi thích sử dụng một cái hiện có hơn là trùng lặp.

|
105

Kể từ phiên bản Go1.1, có API bufio.Scanner có thể dễ dàng đọc các dòng từ một tệp. Xem xét ví dụ sau từ phía trên, viết lại bằng 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)
    }
}
|
113

Nếu tệp không quá lớn, điều này có thể được thực hiện với các chức năng ioutil.ReadFilestrings.Splitnhư vậy:

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

Bạn có thể đọc tài liệu về các gói ioutilchuỗi .

|
32

Không thể cập nhật câu trả lời đầu tiên.
Dù sao, sau khi phát hành Go1, có một số thay đổi đột phá, vì vậy tôi đã cập nhật như hình dưới đây:

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

Bạn có thể sử dụng os.File (thực hiện giao diện io.Reader ) với gói bufio cho điều đó. Tuy nhiên, các gói đó được xây dựng với mục đích sử dụng bộ nhớ cố định (cho dù tệp có lớn đến đâu) và khá nhanh.

Thật không may, điều này làm cho việc đọc toàn bộ tập tin vào bộ nhớ phức tạp hơn một chút. Bạn có thể sử dụng byte.Buffer để nối các phần của dòng nếu chúng vượt quá giới hạn dòng. Dù sao, tôi khuyên bạn nên thử sử dụng trình đọc dòng trực tiếp trong dự án của bạn (đặc biệt là nếu không biết tệp văn bản lớn đến mức nào!). Nhưng nếu tệp nhỏ, ví dụ sau có thể đủ cho bạn:

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

Một cách khác có thể là sử dụng io.ioutil.Read ALL để đọc trong tệp hoàn chỉnh cùng một lúc và thực hiện cắt theo dòng sau đó. Tôi không cung cấp cho bạn một ví dụ rõ ràng về cách viết các dòng trở lại tệp, nhưng về cơ bản os.Create()đó là một vòng lặp tương tự như vòng lặp trong ví dụ (xem main()).

|
  • 1

    Cảm ơn thông tin đó. Tôi đã quan tâm hơn đến việc sử dụng một gói hiện có để thực hiện toàn bộ công việc, bởi vì tôi nghĩ nó khá hữu ích. Ví dụ: tôi muốn sử dụng Go với sự kiên trì của dữ liệu mà không cần sử dụng cơ sở dữ liệu ban đầu. Một số ngôn ngữ có điều này tôi tin. ví dụ. Tôi nghĩ rằng Ruby có Readlines đọc một chuỗi các chuỗi (từ bộ nhớ) - không phải tôi đặc biệt là một người hâm mộ Ruby. Tôi đoán nó không phải là vấn đề lớn, tôi chỉ không thích sự trùng lặp, nhưng có lẽ chỉ có tôi mới muốn nó. Dù sao, tôi đã viết một gói để làm điều đó và có lẽ tôi sẽ đưa nó lên github. Những tập tin này thường rất nhỏ.

    – Đỗ Nam Phi 05:53:14 05/05/2011
  • 1

    Nếu bạn chỉ muốn duy trì bất kỳ loại cấu trúc cờ vây nào (ví dụ: một chuỗi các chuỗi, số nguyên, bản đồ hoặc các cấu trúc phức tạp hơn), bạn chỉ cần sử dụng gob.Encode()cho cấu trúc đó. Kết quả là một tệp nhị phân thay vì tệp văn bản phân tách dòng mới. Tệp này có thể chứa tất cả các loại dữ liệu, có thể được phân tích cú pháp hiệu quả, tệp kết quả sẽ nhỏ hơn và bạn không phải đối phó với các dòng mới và phân bổ động. Vì vậy, nó có lẽ phù hợp hơn với bạn nếu bạn chỉ muốn duy trì thứ gì đó để sử dụng sau này với Go.

    – Phan Gia Ngọc 15:35:17 05/05/2011
  • 1

    Những gì tôi muốn là một mảng các dòng văn bản để tôi có thể thay đổi bất kỳ dòng (trường). Những tập tin này rất nhỏ. Khi thay đổi được thực hiện, các chuỗi có độ dài thay đổi cuối cùng sẽ được viết lại. Nó rất linh hoạt và nhanh chóng cho những gì tôi muốn làm. Tôi cần các dòng mới để phân tách các dòng (các trường). Có lẽ có một cách tốt hơn, nhưng điều này có vẻ ổn cho mục đích của tôi hiện tại. Tôi sẽ xem xét những gì bạn đề xuất sau đó và có lẽ thay đổi nó sau đó.

    – Tạ Phúc Tâm 13:50:52 07/05/2011
  • 1

    Lưu ý rằng kể từ r58 (tháng 7 năm 2011), gói mã hóa / dòng đã bị xóa. "Chức năng của nó bây giờ là trong bufio."

    – Hoàng Minh Nhân 06:13:51 08/09/2011
3
func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    reader := bufio.NewReader(f)
    contents, _ := ioutil.ReadAll(reader)
    lines := strings.Split(string(contents), '\n')
}

hoặc là

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

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.