os.File în Go

Tipul care reprezintă un fișier deschis; îl obții cu os.Open, os.Create sau os.OpenFile.

Sintaxă
type File struct { /* câmpuri ascunse */ }

func Open(name string) (*File, error)
func Create(name string) (*File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)

Ce face os.File

Un *os.File este un fișier deschis: poți citi din el, scrie în el, muta poziția curentă și afla informații despre el. Implementează io.Reader, io.Writer și io.Closer, deci merge cu toate funcțiile din io și bufio. os.Stdin, os.Stdout și os.Stderr sunt tot valori *os.File.

Îl obții în trei feluri: os.Open(nume) deschide doar pentru citire; os.Create(nume) creează sau golește fișierul și îl deschide pentru citire și scriere; os.OpenFile(nume, flag, perm) îți dă control complet prin opțiuni combinate cu |: os.O_RDONLY, os.O_WRONLY, os.O_RDWR, os.O_CREATE, os.O_APPEND, os.O_TRUNC, os.O_EXCL.

Orice fișier deschis trebuie închis cu Close, de obicei cu defer f.Close() imediat după verificarea erorii. Pentru citirea sau scrierea unui fișier întreg dintr-un singur apel, os.ReadFile și os.WriteFile sunt mai simple.

Parametri

Parametru Descriere
name Calea fișierului.
flag La OpenFile: modul de deschidere, de exemplu os.O_APPEND|os.O_CREATE|os.O_WRONLY.
perm La OpenFile: drepturile, dacă fișierul este creat (de obicei 0o644).

Ce returnează

Un *os.File și nil, sau nil și o eroare *fs.PathError.

Exemple

Exemplul 1: Create, scriere, Open, citire

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    f, err := os.Create("salut.txt")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    fmt.Fprintln(f, "Salut din Iași!")
    fmt.Fprintf(f, "Temperatura: %d°C\n", 21)
    f.Close()

    f, err = os.Open("salut.txt")
    if err != nil {
        fmt.Println("eroare:", err)
        return
    }
    defer f.Close()
    continut, _ := io.ReadAll(f)
    fmt.Print(string(continut))
}

Rezultat

Salut din Iași!
Temperatura: 21°C

Exemplul 2: Adăugare într-un jurnal cu OpenFile

O_CREATE creează fișierul dacă lipsește, O_APPEND scrie mereu la final.

package main

import (
    "fmt"
    "os"
)

func adauga(mesaj string) error {
    f, err := os.OpenFile("jurnal.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
    if err != nil {
        return err
    }
    defer f.Close()
    _, err = fmt.Fprintln(f, mesaj)
    return err
}

func main() {
    adauga("09:00 magazin deschis")
    adauga("09:14 comanda 1042 (Ana)")
    adauga("09:20 comanda 1043 (Mihai)")

    date, _ := os.ReadFile("jurnal.log")
    fmt.Print(string(date))
}

Rezultat

09:00 magazin deschis
09:14 comanda 1042 (Ana)
09:20 comanda 1043 (Mihai)

Exemplul 3: Scriere într-un fișier deschis doar pentru citire

os.Open deschide numai pentru citire; scrierea dă eroarea „bad file descriptor”.

package main

import (
    "fmt"
    "os"
)

func main() {
    os.WriteFile("date.txt", []byte("abc"), 0o644)
    f, _ := os.Open("date.txt")
    defer f.Close()

    _, err := f.WriteString("xyz")
    fmt.Println(err)
}

Rezultat

write date.txt: bad file descriptor

Greșeli frecvente

  • Pui defer f.Close() înainte să verifici eroarea. Dacă deschiderea a eșuat, f este nil; verifică err întâi.
  • Deschizi fișiere într-o buclă cu defer f.Close() în main. Defer-urile rulează abia la final, iar fișierele rămân deschise; mută corpul buclei într-o funcție separată.
  • Folosești os.Create pe un fișier pe care voiai doar să-l completezi. Create îl golește; folosește OpenFile cu O_APPEND.

Comenzi înrudite

  • os.File.Close: Închide fișierul și eliberează resursele sistemului; după Close fișierul nu mai poate fi folosit.
  • os.File.Read: Citește din fișier cel mult len(b) octeți în slice-ul b și returnează câți a citit.
  • os.File.Write: Scrie octeți (Write) sau text (WriteString) în fișier, la poziția curentă.
  • os.ReadFile: Citește tot conținutul unui fișier într-un slice de octeți, dintr-un singur apel.
  • os.WriteFile: Scrie octeții dați într-un fișier: îl creează dacă lipsește și îi înlocuiește conținutul dacă există.
  • bufio.NewScanner: Creează un bufio.Scanner, cel mai simplu mod de a citi un text rând cu rând (sau cuvânt cu cuvânt).
  • os.Open: Deschide un fișier existent doar pentru citire și returnează un *os.File.
  • os.Create: Creează un fișier nou (sau golește unul existent) și îl deschide pentru scriere și citire.
  • os.OpenFile: Deschide un fișier cu opțiuni alese de tine: citire, scriere, adăugare la final, creare, golire, creare exclusivă.