Як я можу прочитати цілий файл у змінну рядка


161

У мене багато невеликих файлів, я не хочу їх читати по черзі.

Чи є в Go функція, яка буде читати весь файл у змінну рядка?

Відповіді:


253

Використання ioutil.ReadFile:

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

ReadFile читає файл, названий ім'ям файлу, і повертає вміст. Успішний виклик повертає err == nil, не err == EOF. Оскільки ReadFile читає весь файл, він не трактує EOF з Read як помилку, про яку потрібно повідомити.

Ви отримаєте []byteзамість string. Його можна перетворити, якщо це дійсно необхідно:

s := string(buf)

5
Потім для побудови кінцевого результату рядка ви можете використовувати append () для накопичення даних в одному байтовому фрагменті під час читання кожного файлу, а потім перетворити накопичений байтовий фрагмент у кінцевий результат рядка. Крім того, вам можуть сподобатися байти.
Соня

1
Покажіть нам, як потім його перетворити ... Питання не запитує байтовий масив.
Кайл Бріденстін

Використовуючи це, щоб відкрити файл html, і я знаходжу, що новий рядок додається після кожного рядка, який псує нам частину мого форматування. Чи є спосіб уникнути цього?
Джонатан

55

Якщо ви просто хочете, щоб вміст був таким string, то простим рішенням є використання ReadFileфункції з io/ioutilпакету. Ця функція повертає фрагмент, bytesякий ви можете легко перетворити на 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

Я думаю, що найкраще, якщо ви дійсно стурбовані ефективністю об'єднання всіх цих файлів, - це скопіювати їх у один і той же байт-буфер.

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

Це відкриває кожен файл, копіює його вміст у buf, а потім закриває файл. Залежно від вашої ситуації вам, можливо, не потрібно її конвертувати, останній рядок полягає лише в тому, щоб показати, що buf.Bytes () має дані, які ви шукаєте.


Привіт, чи буде io.Copy замінити вміст buf? А яка ємність буфа? Дякую.
WoooHaaaa

Копія не буде перезаписана, вона просто продовжуватиме додавати в buf, і buf зросте стільки, скільки потрібно для розміщення нових даних.
Запуск Wild

1
Буф має "нескінченну" ємність. Він буде продовжувати розширюватися, оскільки додаватимуть більше даних. ioutil.Readfile виділить буфер, який є достатньо великим, щоб вмістити весь файл і не потрібно перерозподіляти.
Стівен Вайнберг

1
Чи справді використання байт-буфера покращує продуктивність порівняно з простою додаванням його до фрагменту (/ масиву)? А що з пам’яттю? Наскільки велика різниця?
Кіссакі

8

Ось як я це зробив:

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

Я не з комп’ютером, тому пишу чернетку. Вам може бути зрозуміло, що я говорю.

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()
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.