Johdanto
Tämä opas sisältää esimerkkejä yleisten tiedostojen syöttö- ja tulostustoimintojen suorittamisesta Gossa.
Tämä opas on kirjoitettu ei-root-käyttäjälle. Jotkut komennot saattavat kuitenkin vaatia apuasudo
jotta se voidaan suorittaa kunnolla. Jos et ole perehtynytsudo
komento, 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.txt
jossa 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.go
muistuttaa seuraavaa tulostetta:
go run do ItExist.go /bin/What
Polkua ei ole olemassa! stat /bin/What: ei tällaista tiedostoa tai hakemistoa
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.go
muistuttaa seuraavaa tulostetta:
suorita isFile.go /bin/ls
/bin/ls on tavallinen tiedosto!
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.go
tiedosto 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ä avarten
silmukan, joka on kuvattu tämän oppaan muissa esimerkeissä.
SuoritetaanreadFile.go
tuottaa 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
[ ) palata } varten _, tiedosto := alue lippu.Args() { err := lineByLine(tiedosto) jos err != nolla { fmt.Println(err) } }}...]\n"
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ä. Thevarten
silmukka sisäänpää()
funktio on olemassa auttamaan useiden komentoriviargumenttien käsittelyssä.
SuoritetaanlByL.go
tuottaa 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
[ ) palata } varten _, tiedosto := alue lippu.Args() { err := sanasta sanaan(tiedosto) jos err != nolla { fmt.Println(err) } }}...]\n"
Ohjelman ydintoiminnot löytyvätsanasta sanaan()
toiminto. Aluksi tekstitiedosto luetaan rivi riviltä. Sitten säännöllinen lauseke, joka tallennetaanr
muuttuja, käytetään nykyisen rivin sanojen määrittämiseen. Nämä sanat on tallennettusanat
muuttuja. Sen jälkeen avarten
silmukkaa käytetään sisällön iterointiinsanat
ja tulosta ne näytölle ennen kuin jatkat syöttötiedoston seuraavalla rivillä.
SuoritetaanwByW.go
tuottaa 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
[ ) palata } varten _, tiedosto := alue lippu.Args() { err := charByChar(tiedosto) jos err != nolla { fmt.Println(err) } }}...]\n"
ThecharByChar()
toiminto tekee kaiken työn. Jälleen kerran syöttötiedosto on valmis rivi riviltä. Sisällä avarten
silmukka,alue
toistaa jokaisen rivin merkkejä.
SuoritetaancByC.go
tuottaa 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.go
tuottaa 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 palauttaatotta
jos tiedostoa tai hakemistoa ei ole olemassa. Tämä ilmenee julkaisun sisällöstävirhe
muuttuja, joka välitetään argumenttinaEi ole olemassa()
. Thevirhe
muuttuja palautettiin edellisellä kutsulla osoitteeseenos.Stat()
.
SuoritetaancreateFile.go
tuottaa 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.Writer
käyttöliittymä. Muista se vielä kerranos.Create()
katkaisee kohdetiedoston, jos se on jo olemassa.
Onnistunut toteutuswriteFile.go
ei 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_APPEND
lippuos.OpenFile()
toiminto. Tämä lippu kertoo Siirry kirjoittamaan tiedoston loppuun. Lisäksi,os.O_CREATE
lippu 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.go
Ohjelma ei tuota tulosta, kun se suoritetaan onnistuneesti. Tässä esimerkissä se suoritettiin muodossasuorita append.go "123" /tmp/data.txt
. Kuitenkin sisältö/tmp/data.txt
ei 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.go
voit 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.go
tulee 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.go
ilman 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.
Komentoriviargumentit käytettäessäcat.go
ovat vain tiedostopolkuja.cat.go
ei tue argumentteja, joita näet perinteisen kanssakissa
komento, vain ydintoiminnot.
Tuotoscat.go
tulee 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