Tiedostojen luominen, lukeminen ja kirjoittaminen Gossa – opetusohjelma (2023)

Johdanto

Tämä opas sisältää esimerkkejä yleisten tiedostojen syöttö- ja tulostustoimintojen suorittamisesta Gossa.

Huomautus

Tämä opas on kirjoitettu ei-root-käyttäjälle. Jotkut komennot saattavat kuitenkin vaatia apuasudojotta se voidaan suorittaa kunnolla. Jos et ole perehtynytsudokomento, katsoKäyttäjät ja ryhmätopas.

Tässä oppaassa

Tässä oppaassa opit, miten:

  • Lue tiedostoja Gossa
  • Tarkista, onko tiedosto tai hakemisto olemassa
  • Luo uusia tiedostoja
  • Kirjoita tiedot tiedostoihin
  • Toteuta yksinkertainen versio cat(1)-komentorivityökalusta Gossa

Ennen kuin aloitat

  • Tämän oppaan noudattamiseksi sinulla on oltavaAsenna tietokoneellesija pääsy haluamaasi tekstieditoriin.

  • Tämän oppaan tarkoituksia varten tekstitiedosto nimeltädata.txtjossa käytetään seuraavaa sisältöä:

    cat /tmp/data.txt
    1 2Yksi KaksiKolme

Polun olemassaolon tarkistaminen

Jotta voit lukea tiedoston, sinun on avattava se ensin. Jotta tiedosto voidaan avata, sen on oltava annetussa polussa ja oltava todellinen tiedosto, ei hakemisto. Tämän osion koodi tarkistaa, josannettua polkuaolemassa.

Tiedosto: ./doesItExist.go
1234567891011121314151617181920
paketti päätuonti ( "fmt" "os")func pää() { argumentteja := os.Args jos len(argumentteja) == 1 { fmt.Println("Anna yksi argumentti.") palata } polku := argumentteja[1] _, err := os.Tilasto(polku) jos err != nolla { fmt.Println("Polkua ei ole olemassa!", err) }}

Kaikki työ täällä tehdään voimakkaiden toimestaos.Stat()toiminto. Jos puheluos.Stat()onnistuu, virhearvo onnolla, joka vahvistaa, että annettu polku on olemassa. Huomaa, että jos annettu polku on olemassa, ohjelma ei tuota UNIX-filosofian mukaista tulosta.

SuoritetaaneiItExist.gomuistuttaa seuraavaa tulostetta:

go run do ItExist.go /bin/What
Polkua ei ole olemassa! stat /bin/What: ei tällaista tiedostoa tai hakemistoa
Huomautus

Se, että polku on olemassa, ei välttämättä tarkoita, että se on tavallinen tiedosto tai hakemisto. On olemassa lisätestejä ja toimintoja, jotka auttavat sinua määrittämään, minkä tyyppistä tiedostoa käsittelet.

Tarkistaa, onko polku tavallinen tiedosto

Go-standardikirjastossa on erityinen toiminto,on säännöllinen(), joka tarkistaa, kuuluuko polku tiedostoon vai ei. Tämä toiminto on kuvattu alla olevassa esimerkissä.

Tiedosto: ./isFile.go
12345678910111213141516171819202122232425
paketti päätuonti ( "fmt" "os")func pää() { argumentteja := os.Args jos len(argumentteja) == 1 { fmt.Println("Anna yksi argumentti.") palata } polku := argumentteja[1] fileInfo, err := os.Tilasto(polku) jos err != nolla { fmt.Println("Polkua ei ole olemassa!", err) } tila := fileInfo.tila() jos tila.On Säännöllinen() { fmt.Println(polku, "on tavallinen tiedosto!") }}

Saatuaan tietoja tiedoston tilasta käyttämälläMode(), sinun täytyy soittaaon säännöllinen()toiminto määrittää, kuuluuko annettu polku tavalliseen tiedostoon vai ei. Jos polku on tavallinen tiedosto, tulostetaanon säännöllinen()antaa sinulle tämän tiedon.

SuoritetaanisFile.gomuistuttaa seuraavaa tulostetta:

suorita isFile.go /bin/ls
/bin/ls on tavallinen tiedosto!
Huomautus

Suurin osa tämän oppaan esimerkeistä ei testaa, onko luettava tiedosto olemassa koodin määrän minimoimiseksi. Theos.Open()toiminto tekee osan tästä toiminnasta, mutta vähemmän tyylikkäällä tavalla. Tuotantokoodille tulee kuitenkin tehdä kaikki tarvittavat testit, jotta vältytään ohjelmiston kaatumisilta ja virheiltä.

Tiedostojen lukeminen Gossa

Tiedostojen lukeminen Gossa on yksinkertainen tehtävä. Go käsittelee sekä teksti- että binaaritiedostoja samalla tavalla, ja sinun on itse tulkittava tiedoston sisältö. Yksi monista tavoista lukea tiedostoa,ReadFull(), on esitetty kohdassareadFile.gotiedosto alla.

Tiedosto: ./readFile.go
12345678910111213141516171819202122232425262728293031
paketti päätuonti ( "fmt" "io" "os")func pää() { jos len(os.Args) != 2 { fmt.Println("Anna tiedostonimi") palata } Tiedoston nimi := os.Args[1] f, err := os.Avata(Tiedoston nimi) jos err != nolla { fmt.Printf("virhe avattaessa %s: %s", Tiedoston nimi, err) palata } lykätä f.kiinni() buf := tehdä([]tavu, 8) jos _, err := io.ReadFull(f, buf); err != nolla { jos err == io.EOF { err = io.ErrUnexpectedEOF } } io.WriteString(os.Stdout, merkkijono(buf)) fmt.Println()}

Theio.ReadFull()toiminto lukee lukijalta avoimen tiedoston ja sijoittaa tiedot atavun siivu8 paikalla. Theio.WriteString()toimintoa käytetään tietojen lähettämiseen vakiolähtöön (os.Stdout), joka on myös tiedosto UNIXin osalta. Lukutoiminto suoritetaan vain kerran. Jos haluat lukea koko tiedoston, sinun on käytettävä avartensilmukan, joka on kuvattu tämän oppaan muissa esimerkeissä.

SuoritetaanreadFile.gotuottaa seuraavan tulosteen:

suorita readFile.go /tmp/data.txt
12 Yksi

Tiedoston lukeminen rivi riviltä

Seuraava koodi näyttää, kuinka voit lukea tekstitiedoston Go rivi riviltä.

Tiedosto: ./lByL.go
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
paketti päätuonti ( "bufio" "lippu" "fmt" "io" "os")func lineByLine(tiedosto merkkijono) virhe { oli err virhe fd, err := os.Avata(tiedosto) jos err != nolla { palata err } lykätä fd.kiinni() lukija := bufio.UusiReader(fd) varten { linja, err := lukija.ReadString('\n') jos err == io.EOF { tauko } muu jos err != nolla { fmt.Printf("virhe luettaessa tiedostoa %s", err) tauko } fmt.Tulosta(linja) } palata nolla}func pää() { lippu.Jäsentää() jos len(lippu.Args()) == 0 { fmt.Printf("käyttö: lByL  [ ...]\n") palata } varten _, tiedosto := alue lippu.Args() { err := lineByLine(tiedosto) jos err != nolla { fmt.Println(err) } }}

Ohjelman ydintoiminnot löytyvätlineByLine()toiminto. Kun olet varmistanut, että tiedostonimi voidaan avata, toiminto luo uuden lukijan käyttämälläbufio.NewReader(). Sitten toiminto käyttää kyseistä lukijaabufio.ReadString()lukeaksesi syöttötiedoston rivi riviltä. Tämä saavutetaan ohittamallarivin uusi merkkiparametrillebufio.ReadString().bufio.ReadString()jatkaa tiedoston lukemista, kunnes kyseinen merkki löytyy. Soittelee jatkuvastibufio.ReadString()Kun tämä parametri on rivinvaihtomerkki, syöttötiedosto luetaan rivi riviltä. Thevartensilmukka sisäänpää()funktio on olemassa auttamaan useiden komentoriviargumenttien käsittelyssä.

SuoritetaanlByL.gotuottaa seuraavanlaisen tulosteen:

suorita lByL.go /tmp/data.txt
1 2Yksi KaksiKolme

Tekstitiedoston lukeminen sana kerrallaan

Seuraava koodi näyttää, kuinka voit lukea tekstitiedoston sana sanalta.

Tiedosto: ./wByW.go
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
paketti päätuonti ( "bufio" "lippu" "fmt" "io" "os" "säännöllinen lauseke")func sanasta sanaan(tiedosto merkkijono) virhe { oli err virhe fd, err := os.Avata(tiedosto) jos err != nolla { palata err } lykätä fd.kiinni() lukija := bufio.UusiReader(fd) varten { linja, err := lukija.ReadString('\n') jos err == io.EOF { tauko } muu jos err != nolla { fmt.Printf("virhe luettaessa tiedostoa %s", err) palata err } r := regexp.MustCompile("[^\\s]+") sanat := r.FindAllString(linja, -1) varten i := 0; i < len(sanat); i++ { fmt.Println(sanat[i]) } } palata nolla}func pää() { lippu.Jäsentää() jos len(lippu.Args()) == 0 { fmt.Printf("käyttö: wByW  [ ...]\n") palata } varten _, tiedosto := alue lippu.Args() { err := sanasta sanaan(tiedosto) jos err != nolla { fmt.Println(err) } }}

Ohjelman ydintoiminnot löytyvätsanasta sanaan()toiminto. Aluksi tekstitiedosto luetaan rivi riviltä. Sitten säännöllinen lauseke, joka tallennetaanrmuuttuja, käytetään nykyisen rivin sanojen määrittämiseen. Nämä sanat on tallennettusanatmuuttuja. Sen jälkeen avartensilmukkaa käytetään sisällön iterointiinsanatja tulosta ne näytölle ennen kuin jatkat syöttötiedoston seuraavalla rivillä.

SuoritetaanwByW.gotuottaa seuraavanlaisen tulosteen:

suorita wByW.go /tmp/data.txt
12YksiKaksiKolme

Tiedoston lukeminen merkki merkiltä

Seuraava koodi näyttää, kuinka voit lukea tekstitiedoston merkki kerrallaan.

Tiedosto: ./cByC.go
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
paketti päätuonti ( "bufio" "lippu" "fmt" "io" "os")func charByChar(tiedosto merkkijono) virhe { oli err virhe fd, err := os.Avata(tiedosto) jos err != nolla { palata err } lykätä fd.kiinni() lukija := bufio.UusiReader(fd) varten { linja, err := lukija.ReadString('\n') jos err == io.EOF { tauko } muu jos err != nolla { fmt.Printf("virhe luettaessa tiedostoa %s", err) palata err } varten _, x := alue linja { fmt.Println(merkkijono(x)) } } palata nolla}func pää() { lippu.Jäsentää() jos len(lippu.Args()) == 0 { fmt.Printf("käyttö: cByC  [ ...]\n") palata } varten _, tiedosto := alue lippu.Args() { err := charByChar(tiedosto) jos err != nolla { fmt.Println(err) } }}

ThecharByChar()toiminto tekee kaiken työn. Jälleen kerran syöttötiedosto on valmis rivi riviltä. Sisällä avartensilmukka,aluetoistaa jokaisen rivin merkkejä.

SuoritetaancByC.gotuottaa seuraavanlaisen tulosteen:

suorita cByC.go /tmp/data.txt
12YksiKaksiKolme

Muita esimerkkejä

Tarkistaa, onko polku hakemisto

Tässä osiossa opit erottamaan hakemistot muista UNIX-tiedostotyypeistä.

Tiedosto: ./isDirectory.go
12345678910111213141516171819202122232425
paketti päätuonti ( "fmt" "os")func pää() { argumentteja := os.Args jos len(argumentteja) == 1 { fmt.Println("Anna yksi argumentti.") palata } polku := argumentteja[1] fileInfo, err := os.Tilasto(polku) jos err != nolla { fmt.Println("Polkua ei ole olemassa!", err) } tila := fileInfo.tila() jos tila.SubDir() { fmt.Println(polku, "on hakemisto!") }}

Kaikki työt tehdäänSubDir()toiminto. Jos se on hakemisto, se palaatotta.

SuoritetaanisDirectory.gotuottaa seuraavanlaisen tulosteen:

mene suorittamaan isDirectory.go /tmp
/tmp on hakemisto!

Uuden tiedoston luominen

Tässä osiossa opit luomaan uuden tiedoston Goissa.

Tiedosto: ./createFile.go
1234567891011121314151617181920212223242526272829
paketti päätuonti ( "fmt" "os")func pää() { jos len(os.Args) != 2 { fmt.Println("Anna tiedostonimi") palata } Tiedoston nimi := os.Args[1] oli _, err = os.Tilasto(Tiedoston nimi) jos os.Ei ole olemassa(err) { tiedosto, err := os.Luoda(Tiedoston nimi) jos err != nolla { fmt.Println(err) palata } lykätä tiedosto.kiinni() } muu { fmt.Println("Tiedosto on jo olemassa!", Tiedoston nimi) palata } fmt.Println("Tiedosto luotiin onnistuneesti", Tiedoston nimi)}

On todella tärkeää varmistaa, että luotavaa tiedostoa ei ole jo olemassa, muuten saatat korvata olemassa olevan tiedoston ja menettää sen tiedot.os.Create()katkaisee kohdetiedoston, jos se on jo olemassa. TheEi ole olemassa()funktio palauttaatottajos tiedostoa tai hakemistoa ei ole olemassa. Tämä ilmenee julkaisun sisällöstävirhemuuttuja, joka välitetään argumenttinaEi ole olemassa(). Thevirhemuuttuja palautettiin edellisellä kutsulla osoitteeseenos.Stat().

SuoritetaancreateFile.gotuottaa seuraavan tulosteen:

suorita createFile.go /tmp/newFile.txt
Tiedosto luotiin onnistuneesti /tmp/newFile.txt

Tietojen kirjoittaminen tiedostoon

Tässä osiossa opit kirjoittamaan tietoja uuteen tiedostoon käyttämälläfmt.Fprintf().

Tiedosto: ./writeFile.go
123456789101112131415161718192021222324
paketti päätuonti ( "fmt" "os")func pää() { jos len(os.Args) != 2 { fmt.Println("Anna tiedostonimi") palata } Tiedoston nimi := os.Args[1] määränpäähän, err := os.Luoda(Tiedoston nimi) jos err != nolla { fmt.Println("os.Create:", err) palata } lykätä määränpäähän.kiinni() fmt.Fprintf(määränpäähän, "[%s]:", Tiedoston nimi) fmt.Fprintf(määränpäähän, "Fmt.Fprintf:n käyttö %s:ssa\n", Tiedoston nimi)}

Käyttöfmt.Fprintf()kirjoitustoiminnon avulla voimme kirjoittaa muotoiltua tekstiä tiedostoihin tavalla, joka on samanlainen kuinfmt.Printf()toiminto toimii. Huomaa, ettäfmt.Fprintf()voi kirjoittaa kenelle tahansaio.Writerkäyttöliittymä. Muista se vielä kerranos.Create()katkaisee kohdetiedoston, jos se on jo olemassa.

Onnistunut toteutuswriteFile.goei tuota tulosta - tässä tapauksessa suoritettu komento onsuorita writeFile.go /tmp/aNewFile. Olisi kuitenkin mielenkiintoista nähdä sen sisältö/tmp/aNewFile.

cat /tmp/aNewFile
[/tmp/aNewFile]: fmt.Fprintf:n käyttö tiedostossa /tmp/aNewFile

Tietojen liittäminen tiedostoon

Nyt opit lisäämään tietoja tiedostoon, mikä tarkoittaa tietojen lisäämistä tiedoston loppuun poistamatta olemassa olevia tietoja.

Tiedosto: ./append.go
12345678910111213141516171819202122232425
paketti päätuonti ( "fmt" "os" "polku/tiedostopolku")func pää() { argumentteja := os.Args jos len(argumentteja) != 3 { fmt.Printf("käyttö: %s viestin tiedostonimi\n", tiedostopolku.Pohja(argumentteja[0])) palata } viesti := argumentteja[1] Tiedoston nimi := argumentteja[2] tiedosto, err := os.Avaa tiedosto(Tiedoston nimi, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660) jos err != nolla { fmt.Println(err) palata } lykätä tiedosto.kiinni() fmt.Fprintf(tiedosto, "%s\n", viesti)}

Varsinaisesta liittämisestä huolehtiios.O_APPENDlippuos.OpenFile()toiminto. Tämä lippu kertoo Siirry kirjoittamaan tiedoston loppuun. Lisäksi,os.O_CREATElippu tekeeos.OpenFile()Luo tiedosto, jos sitä ei ole olemassa, mikä on melko kätevää. Tämän lisäksi tiedot kirjoitetaan tiedostoon käyttämälläfmt.Fprintf().

Theappend.goOhjelma ei tuota tulosta, kun se suoritetaan onnistuneesti. Tässä esimerkissä se suoritettiin muodossasuorita append.go "123" /tmp/data.txt. Kuitenkin sisältö/tmp/data.txtei ole sama:

cat /tmp/data.txt
1 2Yksi KaksiKolme123

Tiedostojen kopioiminen

Tässä osiossa opit yhden tavan luoda kopio olemassa olevasta tiedostosta.

Tiedosto: ./fileCopy.go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
paketti päätuonti ( "fmt" "io" "os" "polku/tiedostopolku" "strconv")oli PUSKURIN KOKO int64func Kopio(src, dst merkkijono, PUSKURIN KOKO int64) virhe { sourceFileStat, err := os.Tilasto(src) jos err != nolla { palata err } jos !sourceFileStat.tila().On Säännöllinen() { palata fmt.Errorf("%s ei ole tavallinen tiedosto.", src) } lähde, err := os.Avata(src) jos err != nolla { palata err } lykätä lähde.kiinni() _, err = os.Tilasto(dst) jos err == nolla { palata fmt.Errorf("Tiedosto %s on jo olemassa.", dst) } määränpäähän, err := os.Luoda(dst) jos err != nolla { palata err } lykätä määränpäähän.kiinni() buf := tehdä([]tavu, PUSKURIN KOKO) varten { n, err := lähde.Lukea(buf) jos err != nolla && err != io.EOF { palata err } jos n == 0 { tauko } jos _, err := määränpäähän.Kirjoittaa(buf[:n]); err != nolla { palata err } } palata err}func pää() { jos len(os.Args) != 4 { fmt.Printf("käyttö: %s lähdekohde BUFFERSIZE\n", tiedostopolku.Pohja(os.Args[0])) palata } lähde := os.Args[1] määränpäähän := os.Args[2] PUSKURIN KOKO, _ = strconv.ParseInt(os.Args[3], 10, 64) fmt.Printf("Kopioidaan %s kohteeseen %s\n", lähde, määränpäähän) err := Kopio(lähde, määränpäähän, PUSKURIN KOKO) jos err != nolla { fmt.Printf("Tiedoston kopiointi epäonnistui: %q\n", err) }}

fileCopy.govoit määrittää kopioinnin aikana käytettävän puskurin koon. Tässä Go-ohjelmassa puskuri toteutetaan käyttämällä atavun siivunimettybuf. Kopioiminen tapahtuuKopio()toiminto, joka jatkaa syöttötiedoston lukemista käyttämällä tarvittavaa määrääLukea()soittaa ja kirjoittaa sen tarvittavalla määrälläKirjoittaa()puhelut. TheKopio()Funktio suorittaa monia testejä varmistaakseen, että lähdetiedosto on olemassa ja että se on tavallinen tiedosto ja että kohdetiedostoa ei ole olemassa.

TuotosfileCopy.gotulee muistuttamaan seuraavia:

suorita fileCopy.go /tmp/data.txt /tmp/newText 16
Kopioidaan /tmp/data.txt tiedostoon /tmp/newText

Toteutetaan kissa Gossa

Tässä osiossa toteutamme sen ydintoiminnotkissa (1)komentoriviohjelma Gossa. Thekissa (1)apuohjelmaa käytetään tulostamaan tiedoston sisältö pääteikkunaan.

Tiedosto: ./cat.go
123456789101112131415161718192021222324252627282930313233343536373839
paketti päätuonti ( "bufio" "fmt" "io" "os")func printFile(Tiedoston nimi merkkijono) virhe { f, err := os.Avata(Tiedoston nimi) jos err != nolla { palata err } lykätä f.kiinni() skanneri := bufio.NewScanner(f) varten skanneri.Skannata() { io.WriteString(os.Stdout, skanneri.Teksti()) io.WriteString(os.Stdout, "\n") } palata nolla}func pää() { Tiedoston nimi := "" argumentteja := os.Args jos len(argumentteja) == 1 { io.Kopio(os.Stdout, os.Stdin) palata } varten i := 1; i < len(argumentteja); i++ { Tiedoston nimi = argumentteja[i] err := printFile(Tiedoston nimi) jos err != nolla { fmt.Println(err) } }}

Jos suoritatcat.goilman komentoriviargumentteja, apuohjelma vain kopioi vakiosyötteestä vakiotulostukseen käyttämälläio.Copy(os.Stdout, os.Stdin)lausunto. Jos kuitenkin on komentoriviargumentteja, ohjelma käsittelee ne kaikki samassa järjestyksessä kuin ne annettiinprintFile()toiminto.

Huomautus

Komentoriviargumentit käytettäessäcat.goovat vain tiedostopolkuja.cat.goei tue argumentteja, joita näet perinteisen kanssakissakomento, vain ydintoiminnot.

Tuotoscat.gotulee muistuttamaan seuraavia:

suorita cat.go /tmp/data.txt
1 2Yksi KaksiKolme

Yhteenveto

Tiedoston I/O on valtava aihe, jota ei voida käsitellä yhdessä oppaassa. Nyt kun kuitenkin tunnet tiedostojen syöttämisen ja tulostuksen perusteet Gossa, voit aloittaa kokeilemisen ja omien järjestelmäapuohjelmien kirjoittamisen.

Lisää tietoa

Saatat haluta tutustua seuraaviin resursseihin saadaksesi lisätietoja tästä aiheesta. Vaikka nämä toimitetaan siinä toivossa, että niistä on hyötyä, huomaa, että emme voi taata ulkoisesti isännöityjen materiaalien tarkkuutta tai ajantasaisuutta.

Tämä sivu on alun perin julkaistu

Top Articles
Latest Posts
Article information

Author: Golda Nolan II

Last Updated: 16/12/2023

Views: 5381

Rating: 4.8 / 5 (78 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Golda Nolan II

Birthday: 1998-05-14

Address: Suite 369 9754 Roberts Pines, West Benitaburgh, NM 69180-7958

Phone: +522993866487

Job: Sales Executive

Hobby: Worldbuilding, Shopping, Quilting, Cooking, Homebrewing, Leather crafting, Pet

Introduction: My name is Golda Nolan II, I am a thoughtful, clever, cute, jolly, brave, powerful, splendid person who loves writing and wants to share my knowledge and understanding with you.