Как читать / записывать из / в файл с помощью Go?
Я пытался научиться идти самостоятельно, но я был в тупике, пытаясь читать и писать в обычные файлы.
Я могу добраться до inFile, _ := os.Open(INFILE, 0, 0), но на самом деле получить содержание файла не имеет смысла, потому что функция read принимает []byte в качестве параметра.
func (file *File) Read(b []byte) (n int, err Error)
8 ответов:
давайте сделаем Go 1-совместимый список всех способов чтения и записи файлов в Go.
потому что API файлов недавно изменился, и большинство других ответов не работают с Go 1. Они тоже скучают
bufioчто важно ИМХО.в следующих примерах я копирую файл, читать из него и писать в файл назначения.
начните с основ
package main import ( "io" "os" ) func main() { // open input file fi, err := os.Open("input.txt") if err != nil { panic(err) } // close fi on exit and check for its returned error defer func() { if err := fi.Close(); err != nil { panic(err) } }() // open output file fo, err := os.Create("output.txt") if err != nil { panic(err) } // close fo on exit and check for its returned error defer func() { if err := fo.Close(); err != nil { panic(err) } }() // make a buffer to keep chunks that are read buf := make([]byte, 1024) for { // read a chunk n, err := fi.Read(buf) if err != nil && err != io.EOF { panic(err) } if n == 0 { break } // write a chunk if _, err := fo.Write(buf[:n]); err != nil { panic(err) } } }здесь я использовал
os.Openиos.Create, которые удобные обертки вокругos.OpenFile. Обычно нам не нужно звонитьOpenFileнапрямую.обратите внимание на лечение EOF.
Readпытается заполнитьbufпри каждом вызове, и возвращаетio.EOFкак ошибка, если она достигает конца файла при этом. В данном случаеbufсохраняет данные. Последовательные звонки вReadвозвращает ноль как количество прочитанных байтов и то же самоеio.EOFошибка. Любая другая ошибка приведет к панике.используя
bufiopackage main import ( "bufio" "io" "os" ) func main() { // open input file fi, err := os.Open("input.txt") if err != nil { panic(err) } // close fi on exit and check for its returned error defer func() { if err := fi.Close(); err != nil { panic(err) } }() // make a read buffer r := bufio.NewReader(fi) // open output file fo, err := os.Create("output.txt") if err != nil { panic(err) } // close fo on exit and check for its returned error defer func() { if err := fo.Close(); err != nil { panic(err) } }() // make a write buffer w := bufio.NewWriter(fo) // make a buffer to keep chunks that are read buf := make([]byte, 1024) for { // read a chunk n, err := r.Read(buf) if err != nil && err != io.EOF { panic(err) } if n == 0 { break } // write a chunk if _, err := w.Write(buf[:n]); err != nil { panic(err) } } if err = w.Flush(); err != nil { panic(err) } }
bufioздесь просто действует как буфер, потому что мы не имеем большого отношения к данным. В большинстве других ситуаций (особенно с текстовыми файлами)bufio- Это очень полезно, давая нам хороший API для чтения и записи легко и гибко, в то время как он обрабатывает буферизации за кулисами.используя
ioutilpackage main import ( "io/ioutil" ) func main() { // read the whole file at once b, err := ioutil.ReadFile("input.txt") if err != nil { panic(err) } // write the whole body at once err = ioutil.WriteFile("output.txt", b, 0644) if err != nil { panic(err) } }легко, как пирог! Но используйте его только если вы уверены, что не имеете дело с большими файлы.
Это хороший вариант:
package main import ( "io/ioutil"; ) func main() { contents,_ := ioutil.ReadFile("plikTekstowy.txt") println(string(contents)) ioutil.WriteFile("filename", contents, 0644) }
используя
io.Copypackage main import ( "io" "log" "os" ) func main () { // open files r and w r, err := os.Open("input.txt") if err != nil { panic(err) } defer r.Close() w, err := os.Create("output.txt") if err != nil { panic(err) } defer w.Close() // do the actual work n, err := io.Copy(w, r) if err != nil { panic(err) } log.Printf("Copied %v bytes\n", n) }если вы не хотите изобретать велосипед, то
io.Copyиio.CopyNможет служить вам хорошо. Если вы проверьте источник из io.Функция копирования, это не что иное, как одно из решений Mostafa (на самом деле "основное"), упакованное в библиотеку Go. Однако они используют значительно больший буфер, чем он.
[]byte- Это фрагмент (похожий на подстроку) всего или части массива байтов. Подумайте о срезе как о структуре значений со скрытым полем указателя для системы, чтобы найти и получить доступ ко всему или части массива (срез), а также поля для длины и емкости среза, к которым вы можете получить доступ с помощьюlen()иcap()функции.вот рабочий стартовый комплект для вас, который читает и печатает двоичный файл; вам нужно будет изменить
inNameбуквальное значение, указывающее к небольшому файлу в вашей системе.package main import ( "fmt"; "os"; ) func main() { inName := "file-rw.bin"; inPerm := 0666; inFile, inErr := os.Open(inName, os.O_RDONLY, inPerm); if inErr == nil { inBufLen := 16; inBuf := make([]byte, inBufLen); n, inErr := inFile.Read(inBuf); for inErr == nil { fmt.Println(n, inBuf[0:n]); n, inErr = inFile.Read(inBuf); } } inErr = inFile.Close(); }
попробуйте это:
package main import ( "io"; ) func main() { contents,_ := io.ReadFile("filename"); println(string(contents)); io.WriteFile("filename", contents, 0644); }
какие новые версии Go, чтение / запись в / из файла легко. Читать из файла:
package main import ( "fmt" "io/ioutil" ) func main() { data, err := ioutil.ReadFile("text.txt") if err != nil { return } fmt.Println(string(data)) }для записи в файл:
package main import "os" func main() { file, err := os.Create("text.txt") if err != nil { return } defer file.Close() file.WriteString("test\nhello") }это перезапишет содержимое файла (создайте новый файл, если его там не было).
просто глядя на документацию, кажется, что вы должны просто объявить буфер типа []байт и передать его для чтения, который затем прочитает до этого количества символов и вернет количество фактически прочитанных символов (и ошибку).
документы сказать
Read считывает до LEN (b) байт из файла. Он возвращает количество прочитанных байтов и ошибку, если таковые имеются. EOF сигнализируется нулевым количеством с err, установленным в EOF.
тут что не работает?
EDIT: кроме того, я думаю, что вы, возможно, должны использовать интерфейсы чтения/записи, объявленные в bufio пакет вместо использования os пакета.
метод Read принимает параметр byte, потому что это буфер, в который он будет считываться. Это распространенная идиома в некоторых кругах и имеет некоторый смысл, когда вы думаете об этом.
таким образом, вы можете определить, сколько байтов будет прочитано читателем и проверить возврат, чтобы увидеть, сколько байтов на самом деле были прочитаны и обрабатывать любые ошибки соответствующим образом.
как другие указали в своих ответах bufio, вероятно, то, что вы хотите для чтения из большинства файлов.
Я добавлю еще один намек, так как это действительно полезно. Чтение строки из файла лучше всего выполнять не методом ReadLine,а методом ReadBytes или ReadString.
Comments