La capacité de lire (et d'écrire) un fichier texte dans et hors d'un tableau de chaînes est, à mon avis, une exigence assez courante. C'est également très utile lorsque vous démarrez avec une langue, supprimant le besoin initial d'accéder à une base de données. Existe-t-il un à Golang?
par exemple.
func ReadLines(sFileName string, iMinLines int) ([]string, bool) {
et
func WriteLines(saBuff[]string, sFilename string) (bool) {
Je préférerais utiliser un existant plutôt que de le dupliquer.
Depuis la version Go1.1, il existe une API bufio.Scanner qui peut facilement lire les lignes d'un fichier. Prenons l'exemple ci-dessus, réécrit avec 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)
}
}
Si le fichier n'est pas trop volumineux, vous pouvez le faire avec le ioutil.ReadFile
et strings.Split
fonctionne comme ceci:
content, err := ioutil.ReadFile(filename)
if err != nil {
//Do something
}
lines := strings.Split(string(content), "\n")
Vous pouvez lire la documentation sur les paquets ioutil et chaînes .
Impossible de mettre à jour la première réponse.
Quoi qu’il en soit, après la sortie de Go1, il y a eu quelques changements radicaux. J'ai donc mis à jour les modifications suivantes:
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)
}
Vous pouvez utiliser os.File (qui implémente l'interface io.Reader ) avec le package bufio pour cela. Cependant, ces packages sont conçus pour une utilisation de mémoire fixe (quelle que soit la taille du fichier) et sont assez rapides.
Malheureusement, la lecture de tout le fichier dans la mémoire est un peu plus compliquée. Vous pouvez utiliser un bytes.Buffer pour joindre les parties de la ligne si elles dépassent la limite de ligne. Quoi qu'il en soit, je vous recommande d'essayer d'utiliser le lecteur de ligne directement dans votre projet (surtout si vous ne connaissez pas la taille du fichier texte!). Mais si le fichier est petit, l'exemple suivant peut vous suffire:
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)
}
}
Une autre alternative pourrait être d'utiliser io.ioutil.ReadAll pour lire le fichier complet en une fois et faire le découpage par ligne ensuite. Je ne vous donne pas un exemple explicite sur la façon d'écrire les lignes dans le fichier, mais c'est en gros un os.Create()
suivi d'une boucle similaire à celle de l'exemple (voir main()
) .
func readToDisplayUsingFile1(f *os.File){
defer f.Close()
reader := bufio.NewReader(f)
contents, _ := ioutil.ReadAll(reader)
lines := strings.Split(string(contents), '\n')
}
ou
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)
}