Làm cách nào tôi có thể đọc toàn bộ tệp thành một biến chuỗi


161

Tôi có rất nhiều tệp nhỏ, tôi không muốn đọc từng dòng một.

Có một hàm trong Go sẽ đọc toàn bộ tệp thành một biến chuỗi không?

Câu trả lời:


253

Sử dụng ioutil.ReadFile:

func ReadFile(filename string) ([]byte, error)

ReadFile đọc tệp có tên theo tên tệp và trả về nội dung. Cuộc gọi thành công trả về err == nil, không phải err == EOF. Vì ReadFile đọc toàn bộ tệp, nó không coi EOF từ Read là lỗi được báo cáo.

Bạn sẽ nhận được một []bytethay vì một string. Nó có thể được chuyển đổi nếu thực sự cần thiết:

s := string(buf)

5
Sau đó, để xây dựng kết quả chuỗi cuối cùng, bạn có thể sử dụng append () để tích lũy dữ liệu trong một lát byte đơn khi bạn đọc từng tệp, sau đó chuyển đổi lát byte tích lũy thành kết quả chuỗi cuối cùng. Ngoài ra, bạn có thể thích byte.Join.
Sonia

1
Chỉ cho chúng tôi cách chuyển đổi nó sau đó ... Câu hỏi không yêu cầu một mảng byte.
Kyle Bridenstine

Sử dụng điều này để mở một tệp html và tôi thấy một dòng mới được nối thêm sau mỗi dòng đang làm rối chúng tôi một số định dạng của tôi. Có cách nào để tránh điều đó?
Jonathan

55

Nếu bạn chỉ muốn nội dung như string, thì giải pháp đơn giản là sử dụng ReadFilehàm từ io/ioutilgói. Hàm này trả về một lát bytesmà bạn có thể dễ dàng chuyển đổi thành a string.

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    b, err := ioutil.ReadFile("file.txt") // just pass the file name
    if err != nil {
        fmt.Print(err)
    }

    fmt.Println(b) // print the content as 'bytes'

    str := string(b) // convert content to a 'string'

    fmt.Println(str) // print the content as a 'string'
}

22

Tôi nghĩ rằng điều tốt nhất để làm, nếu bạn thực sự lo lắng về hiệu quả của việc ghép tất cả các tệp này, là sao chép tất cả chúng vào cùng một bộ đệm byte.

buf := bytes.NewBuffer(nil)
for _, filename := range filenames {
  f, _ := os.Open(filename) // Error handling elided for brevity.
  io.Copy(buf, f)           // Error handling elided for brevity.
  f.Close()
}
s := string(buf.Bytes())

Thao tác này sẽ mở từng tệp, sao chép nội dung của nó vào buf, sau đó đóng tệp. Tùy thuộc vào tình huống của bạn mà bạn có thể không thực sự cần phải chuyển đổi nó, dòng cuối cùng chỉ để hiển thị rằng buf.Bytes () có dữ liệu bạn đang tìm kiếm.


Xin chào, io.Copy có ghi đè lên nội dung của buf không? Và năng lực của buf là gì? Cảm ơn.
WoooHaaaa

Sao chép sẽ không ghi đè, nó sẽ tiếp tục thêm vào buf và buf sẽ phát triển nhiều như nó cần để chứa dữ liệu mới.
Chạy hoang dã

1
Các buf có một khả năng "vô hạn". Nó sẽ tiếp tục mở rộng khi nhiều dữ liệu được thêm vào. ioutil.Readfile sẽ phân bổ bộ đệm đủ lớn để phù hợp với tệp hoàn chỉnh và không cần phân bổ lại.
Stephen Weinberg

1
Việc sử dụng một bytebuffer có thực sự cải thiện hiệu suất so với việc chỉ thêm nó vào lát (/ mảng) không? Còn trí nhớ thì sao? Làm thế nào lớn là sự khác biệt?
Kissaki

8

Đây là cách tôi đã làm nó:

package main

import (
  "fmt"
  "os"
  "bytes"
  "log"
)

func main() {
   filerc, err := os.Open("filename")
   if err != nil{
     log.Fatal(err)
   }
   defer filerc.Close()

   buf := new(bytes.Buffer)
   buf.ReadFrom(filerc)
   contents := buf.String()

   fmt.Print(contents) 

}    

-2

Tôi không có máy tính, vì vậy tôi viết một bản nháp. Bạn có thể rõ ràng về những gì tôi nói.

func main(){
    const dir = "/etc/"
    filesInfo, e := ioutil.ReadDir(dir)
    var fileNames = make([]string, 0, 10)
    for i,v:=range filesInfo{
        if !v.IsDir() {
            fileNames = append(fileNames, v.Name())
        }
    }

    var fileNumber = len(fileNames)
    var contents = make([]string, fileNumber, 10)
    wg := sync.WaitGroup{}
    wg.Add(fileNumber)

    for i,_:=range content {
        go func(i int){
            defer wg.Done()
            buf,e := ioutil.Readfile(fmt.Printf("%s/%s", dir, fileName[i]))
            defer file.Close()  
            content[i] = string(buf)
        }(i)   
    }
    wg.Wait()
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.