</motto<This example file is dedicated to Io, 
        the Greek goddess of input and output.

        -- -- Donald E. Knuth: The Metafont Book.
>>
 
/chapter</ii<Fortranin I//O>>
 
Crayn </sc fortran>in I//O on suunnilleen standardin
mukaista.  Tyypillisi{ laitteistosta ja k{ytt|j{rjestelm{st{
riippuvia asioita ovat tiedostojen nime{minen ja
rakenteeseen liittyv{t m{{rittelyt. 
 
</sc Fortran>in sy|tt|- ja tulostustiedostoja voidaan
k{sitell{ periaatteessa ainakin seuraavilla eri tavoilla:
 
/beginitems
 
/entry nime{m{ll{ tiedosto uudestaan tiedostoksi 
</tt fort.></sl<n>>,
 
/entry avaamalla se ohjelmassa eksplisiittisell{ nimell{.
 
/entry k{ytt{m{ll{ linkkej{, /iii<linkki>
 
/entry antamalla tiedoston nimi </tt/ii<assign>>-komennolla, tai
 
/entry k{ytt{m{ll{ /ii<uudelleenohjaus>ta (/ii<redirection>
       ja /ii<here document>
       eli </sc unix>in operaattorit </tt /lt>, </tt /gt>, </tt /gt/gt>
       ja </tt /lt/lt>). T{m{ toimii kuitenkin vain
       laitenumeroille 5, 6 ja 0 sek{ 100 ja 101,
       jotka on valmiiksi liitetty standarditiedostoihin </tt/ii<stdin>>,
       </tt/ii<stdout>> ja </tt/ii<stderr>>).
 
/enditems
 
 
/section<Loogiset laitenumerot>
 
</sc fortran>in tiedoston /ii<looginen laitenumero>
voi olla v{lill{ 0--99. Itse asiassa
my|s numerot 100 ja 101 ovat </sc unicos>in k{yt|ss{, 
mutta ne ovat erikoisasemassa.
 
Seuraavat numerot on valmiiksi liitetty 
standarditiedostoihin </tt stdin>,
</tt stdout> ja </tt stderr>:
 
</copymode
      </sc fortran>      laitenumerot     tiedosto

      unit=0             0          stderr
      unit=5             5          stdin 
      unit=6             6          stdout
 
      read(*,...)      100          stdin 
      write(*,...)     101          stdout
      print            101          stdout
>
 
 
 
/section<Tiedostojen nime{minen Fortranissa>
 
</bf Muista, ett{ </sc unix>issa komennoissa ja tiedostojen 
nimiss{ isot ja pienet kirjaimet tarkoittavat eri asiaa!>
 
Mik{li /ii<open-lause>essa ei ole annettu tiedostolle nime{,
k{ytet{{n nimelle oletusta
 
</copymode
      fort.></sl<n>
>
 
miss{ </sl n> on tiedoston (kanavan) laitenumero.
Tiedostoa etsit{{n nykyhakemistosta.
 
Mik{li </tt open>-lauseessa on annettu tiedoston nimi
ilman hakemistopolkua, esimerkiksi 
 
</copymode
      open(4, file='K2CO4', status='old')
 
>
 
etsit{{n tiedostoa </tt K2CO4> nykyhakemistosta.
 
Jos tiedosto on jossain muualla kuin nykyhakemistossa, on
</tt open>-lauseessa m{{ritelt{v{ sen t{ydellinen nimi
polkuineen. 
 
Kun ohjelmassa avataan /ii<tulostustiedosto> ja sille m{{ritell{{n
</tt status='new'>, esimerkiksi 
 
</copymode
      open(15, file='more.K2CO4', status='new')
>
 
kirjoitetaan tiedosto nykyhakemistoon.  Mik{li hakemistossa
on saman niminen tiedosto olemassa, ohjelman suoritus
keskeytyy virheeseen.  Jos siis todella haluat tehd{ uuden
tiedoston, muista tuhota mahdollinen vanha versio ennen
ohjelman suoritusta. 
 
Jos tiedostoa avattaessa m{{ritell{{n </tt
status='scratch'>, syntyy ohjelman suorituksen ajaksi
nykyhakemistoon tiedosto, jonka nimi on tyyppi{ </tt
tmp.Fa></sl<nnnn>>.  Tiedosto poistuu automaattisesti ty|n
loputtua. 
 
 
Todellinen tiedosto </tt file.dat> voidaan liitt{{
laitenumeroon </sl n> eli sit{ vastaavaan tiedostoon </tt
fort.></sl<n>> my|s tekem{ll{ /ii<linkki> t{h{n tiedostoon </sc unix>in
komennolla </tt ln>:
 
</copymode
      ln file.dat fort.9
>
 
Linkkej{ ei voi kuitenkaan tehd{ tiedostoj{rjestelm{st{
toiseen.
 
 
Kolmas tapa asettaa looginen laitenumero viittaamaan
johonkin todelliseen tiedostoon on </sc unicos>in </tt/ii<assign>>-lause.
 
Komennon k{ytt| edellytt{{, ett{ ymp{rist|muuttuja 
</tt/ii<FILENV>> on m{{ritelty.  Muuttujalla </tt FILENV>
m{{ritell{{n tiedoston nimi, johon talletetaan </tt
assign>-komennolla annetut tiedostom{{rittelyt. 
 
Esimerkiksi
suoritetaan ohjelma </tt a.out> siten, ett{ tiedostom{{rittelyt
ovat tiedostossa </tt myfyles>:
 
</copymode
      FILENV=myfyles
      export FILENV
>
 
tai C-shelliss{
 
</copymode
      setenv FILENV myfyles
>
 
 
Tiedostom{{rittelyt talletetaan t{m{n j{lkeen tiedostoon
</tt myfyles> k{ytt{en </tt assign>-komentoa 
(</tt FILENV>-tiedostoa </tt myfyles> voi periaatteessa my|s
editoida, mutta </tt assign>-komento on helpompi tapa
muuttaa sit{).  Komennon </tt assign> ainoa tarkoitus on
luoda t{m{ </tt FILENV>-tiedosto. 
 
Komennon </tt/ii<assign>> muoto on seuraava:
 
</copymode
      assign -a </sl aliasfile> fort.</sl<n>>
>
 
T{m{ siis asettaa </sc fortran>in tiedoston </tt fort.></sl<n>>
viittaamaan tiedostoon </sl aliasfile>.
Tiedoston nime{ ei pid{ antaa eksplisiittisesti 
</tt open>-lauseessa.
 
 
Jos esimerkiksi haluamme tiedoston </tt fort.10>
viittaavan tilap{istiedostoon, voimme sanoa
 
</copymode
      assign -a //tmp//f/$/$//fort.10 fort.10
>
 
</tt FILENV>in asettamisen ja </tt assign>-komentojen
j{lkeen voidaan suorittaa ohjelma:
 
</copymode
      .//a.out
>
 
Voidaan k{ytt{{ hy|dyksi my|s </tt env>-komentoa:
 
</copymode
      env FILENV=myfyles .//a.out
>
 
T{m{n tavan etuna on, ett{ komennolla </tt env> asetetaan
muuttuja </tt FILENV> voimaan vain ohjelman suorituksen ajaksi.
 
 
 
/section<Tiedostojen tyypit>
 
/iii<formatoitu tiedosto>
/iii<formatoimaton tiedosto>
Tavallinen per{kk{istiedosto voi olla formatoitu tai
formatoimaton. Formatoimaton I//O on jopa yli 100 kertaa
nopeampaa kuin formatoitu, joten sit{ kannattaa k{ytt{{
kaikille tiedostoille, jotka on tarkoitettu vain 
tietokoneen luettavaksi. Formatoimaton tiedosto voidaan
avata esimerkiksi sanomalla
 
</copymode
      open(1,'fyle',form='unformatted',status='new')
>
 
K{sitelt{ess{ t{llaista tiedostoa j{tet{{n I//O-lauseesta
yksinkertaisesti formaatti pois:
 
</copymode
      real a(10)
      ..
      write (1) a
>
 
Formatoiduille tekstitiedostoille tietueen maksimipituus
on 152 merkki{. Pitemm{t tietueet ovat mahdollisia, jos
tiedostoa k{sitell{{n suorasaantitiedostona.
 
/ii<Suorasaantitiedosto>lle on m{{ritelt{v{ tietueen pituus;
tiedoston avaus k{y esimerkiksi n{in:
 
</copymode
      open(1,'fyle',status='new',access='direct',recl=800)
>
 
jolloin tietueen pituudeksi tulee 800 tavua (eli 100 sanaa).
Suorasaantitiedostoa luettaessa ja kirjoitettaessa on
mainittava tietueen numero:
 
</copymode
      read(1,rec=n) ...
>
 
Tietueiden numerointi alkaa ykk|sest{.



/section</ii<Puskurointi>>

K{ytt|j{rjestelm{ puskuroi muistiin kaiken standardin
mukaisen I//O:n.  Kirjoitettaessa puskuri tyhjennet{{n
(flush) levylle vasta kun se on t{ynn{.  Vastaavasti
luettaessa puskuri t{ytet{{n levylt{, kun se on tyhj{. 

J{rjestelm{ss{ on kahdenlaisia puskureita;
k{ytt|j{rjestelm{n ytimess{ (kerneliss{) sijaitsevat
/ii<systeemipuskuri>t (/ii<system buffers>) ja k{ytt{j{n ohjelmaan
linkitysvaiheessa tulleet /ii<kirjastorutiinien puskurit>
(/ii<library buffers>). 
 
Tavallinen, per{kk{inen, formatoimaton I//O puskuroidaan
kirjastopuskurien kautta, mutta systeemipuskurit ohitetaan. 
Formatoitu I//O kulkee molempien puskureiden kautta. 

</sc Unicos>issa yhden puskurilohkon koko on aina 512 sanaa eli
4096 tavua.  Oletuksen mukaan kirjastopuskurilohkoja on 42
eli koko kirjastopuskurin koko on 172032 tavua.  Kokoa voi
muuttaa </tt assign>-komennolla esimerkiksi seuraavasti:

</copymode
    assign -b84 fort.1
>

Optiolla </tt -b> m{{ritell{{n kirjastopuskurin kooksi 84 lohkoa eli
344064 tavua. M{{rittely koskee tiedostokanavaa 1.

Systeemipuskureiden kokoon ei k{ytt{j{ voi vaikuttaa.


/section<Tiedostojen tietuemuoto>

</sc Unix>eissa ja </sc unicos>issakin tavallinen
tekstitieto (ASCII) on tiedostoissa merkkijonona. 
Merkkijono katkotaan riveiksi (tietueiksi) </tt
newline>-merkill{ (ASCII 012 tai '</tt/char92 n>'). 

</sc Unicos>in erikoisuus on formatoimattoman tiedoston
tietuemuoto, joka on nimelt{{n /ii<cos-blocked> format.  Nimens{
mukaisesti se on periytynyt </sc cos>-k{ytt|j{rjestelm{st{.  Tieto
talletetaan 512 sanan lohkoissa, siten ett{ jokaisen lohkon
ensimm{inen sana on /ii<BCW> eli /ii<block control word> ja jokainen
tietue p{{ttyy /ii<RCW>:iin eli /ii<Record control word>iin. 
Kontrollisanat BCW ja RCW sis{lt{v{t tiedon siit{, mist{
l|ytyy seuraava BCW tai RCW (forward link).  T{m{
mahdollistaa eteen- ja taaksep{in hyppelehtimisen
tiedostossa. 

Joskus voi olla perusteltua k{ytt{{ tiedostomuotoa, jossa ei
ole mit{{n rakennetta eli se ei sis{ll{ kontrollisanoja. 
T{llaisia ovat </sc unicos>issa /ii<undefined structure -tiedostot>.
T{llaisessa tiedostossa jokainen tietue on
omassa lohkossa eli jokainen tietue vie 512 sanaa tilaa. 
Jokainen lohko siirret{{n suoraan levylle yhdell{
systeemikutsulla ilman mit{{n puskurointia.  On selv{{, ett{
lyhyiden tietueiden tallettaminen n{in on hidasta ja tuhlaa
levytilaa.  Suurilla tietueenpituuksilla p{{st{{n
tehokkaampaan I//O:hon verrattuna cos-blocked I//O:hon. 
Undefined-tiedosto m{{ritell{{n esimerkiksi seuraavasti:

</copymode
    assign -su fort.98
>

/iii<binary structure -tiedosto>
Nelj{s tiedostotyyppi on binary structure.  Siin{k{{n ei ole
kontrollisanoja tietueiden v{liss{, vain tiedoston lopussa
on kontrollisanat /ii<EOR> (/ii<end of record>), /ii<EOF>
(/ii<end of file>) ja
/ii<EOD> (/ii<end of data>).  Tietueita ei t{ss{ muodossa erotella
mitenk{{n toisistaan, joten k{ytt{j{n on tiedett{v{
tarkalleen miten tiedosto on kirjoitettu pysty{kseen
lukemaan sit{.  Esimerkki t{llaisen tiedoston k{ytt{misest{
on luvussa 12.4, jossa kerrotaan bin{{ritiedostojen
siirt{misest{ eri koneiden v{lill{.  Binary structure
-tyyppej{ on kahta: standard binary structure (/ii<sbin>) ja
binary structure (/ii<bin>).  Sbin-tyyppisen tiedoston I//O
puskuroidaan sek{ systeemi- ett{ kirjastotasolla,
bin-tyyppisen vai kirjastotasolla. 


/section</ii<Asynkroninen I//O>>
 
I//O:ta voidaan tehd{ my|s samanaikaisesti ohjelman muun
suorituksen kanssa.  T{llaista asynkronista I//O:ta varten
on Crayn </sc fortran>issa k{skyt </tt/ii<buffer in>> ja </tt
/ii<buffer out>>.  Oletuksen mukaan asynkroninen I//O on
formatoimatonta ja tietuetyyppi on cos-blocked.  My|s
undefine-tyyppist{ tiedostoa voi k{sitell{ asynkronisesti. 

Lauseiden muoto on
 
</copymode
      buffer in  (u,m) (alku,loppu)
      buffer out (u,m) (alku,loppu)
>
 
T{ss{ </tt u> on </sc fortran>in looginen laitenumero, </tt
m> m{{rittelee, miten levyjaksoja k{sitell{{n ...  </tt
alku> ja </tt loppu> viittaavat ensimm{iseen ja viimeiseen
siirrett{v{{n sanaan muistissa.  N{m{ lauseet k{ynnist{v{t
I//O:n, mutta sen j{lkeen ohjelman suoritus jatkuu
normaalisti.  Ohjelmoijan on huolehdittava itse
synkronoinnista, mik{ tapahtuu kutsumalla funktiota </tt
unit> tai </tt length>.  N{m{ j{{v{t odottamaan
I//O-operaation p{{ttymist{ ja palauttavat tiedon sen
onnistumisesta. 
 
 
Funktiokutsun </tt/ii<unit>(u)> arvo on -1, jos lukeminen
laitteelta </tt u> onnistui ja 0, jos tiedosto on lopussa. 
Jos tiedostossa on j{ljell{ v{hemm{n luettavaa kuin </tt
buffer in> -kutsussa pyydettiin, luetaan sen verran kuin
pystyt{{n ja </tt unit> palauttaa -1:n.  Vasta kun
tiedostossa ei ole j{ljell{ yht{{n mit{{n, saa </tt unit>
arvon 0.  Positiiviset arvot tarkoittavat, ett{ lukeminen
ep{onnistui jostain muusta syyst{, l{hinn{ laitevian takia. 
 
Funktiokutsun </tt/ii<length>(u)> arvo on luettujen
sanojen m{{r{. Tiedosto on loppunut, kun </tt length>
palauttaa nollan.
 
Ohjelma ei tietenk{{n saa muuttaa kirjoitettavia
muuttujia ennen kuin I//O on p{{ttynyt. Luettavien
muuttujien arvoja ei my|sk{{n saa k{ytt{{ ennen I//O:n
p{{ttymist{. K{{nt{j{ ei tutki asynkronisen I//O:n
mahdollisesti aiheuttamia riippuvuuksia, joten
sen k{ytt| vaatii huolellisuutta.
 
Seuraavassa esimerkiss{ k{ynnistet{{n taulukon
</tt a> alkioiden </tt 1..1000> lukeminen. 
Samanaikaisesti voidaan k{sitell{ muita taulukoita.
Vasta tarvittaessa </tt a>:ta j{{d{{n odottamaan 
I//O:n valmistumista.
 
</copymode
      real a(1000),b(1000)
      ...
      buffer in (1,0)(a(1),a(1000))
      do 1 i=1,1000
         b(i)=...
  1   continue
      n=length(1)
      if (n .eq. 0) goto 999  ! olipa tyhj{ tiedosto
      do 2 i=1,n
         b(i)=b(i)*a(i)
  2   continue
      ...
>
 
Asynkroninen I//O aiheuttaa ylim{{r{ist{ j{rjestelm{n kuormaa, joten
pienten tietom{{rien siirt{misess{ siit{ on vain haittaa. Sit{
kannattaa harkita vain, jos siirrett{v{{ tietoa paljon.
Odottaessaan siirron loppumista ohjelma voi tehd{ jotakin j{rkev{{
laskentaa.
 
 
/section<Esimerkki>

Seuraava er{ty| suorittaa ohjelman </tt deconv>,
joka k{ytt{{ lukuisia laitenumeroita.
 
</copymode
/# user=lounamaa
/# QSUB -lt 90
/# QSUB
mkdir /$TMPDIR//f/$/$
cd /$TMPDIR//f/$/$
ls -l
FILENV=ex
export FILENV
assign -a /$HOME//deconv//variances.dat fort.2
assign -a /$HOME//deconv//data.dat fort.3
assign -a /$HOME//deconv//kernel.dat fort.4
assign -a kerout.out fort.7
assign -a datout.out fort.8
assign -a varout.out fort.9
assign -a decout.out fort.10
assign -a resout.out fort.11
/$HOME//deconv//deconv /lt /$HOME//deconv//control.dat /gt deconv.out
ls -l
>
 
Ohjelma </tt deconv> lukee kanavilta 2, 3 ja 4 tiedostot
</tt variances.dat>, </tt data.dat> ja </tt kernel.dat>.
N{m{ tiedostot ovat kotihakemiston alihakemistossa </tt deconv>.
Samassa hakemistossa on itse ohjelma </tt deconv> sek{ sen
sy|tt|tiedosto </tt control.dat>.
Ohjelma lukee  tiedoston </tt control.dat> laitteelta 5
ja kirjoittaa </tt deconv.out>-tiedoston laitteelle 6.
 
Kaikki tulostustiedostot tulevat nykyhakemistoon. Ohjelma kirjoittaa
kaikkiaan viisi tiedostoa:

/vskip/baselineskip
 
</parskip0mm
 
</tt kerout.out> </tt unit>-numerolle 7,
 
</tt datout.out> </tt unit>-numerolle 8,
 
</tt varout.out> </tt unit>-numerolle 9,
 
</tt decout.out> </tt unit>-numerolle 10 ja
 
</tt resout.out> </tt unit>-numerolle 11.
 
>
 
Seuraavassa ty|st{ syntyneess{ lokissa on listattu
nykyhakemiston tiedostot.  Kaikki muut tiedostot ovat
ohjelman tulostustiedostoja paitsi tiedosto </tt ex>, joka
sis{lt{{ </tt assign>-m{{/-ri/-tyk/-set. 
 
</leftskip0cm
/catcode`/[=12
/catcode`/]=12
/font/tt = cmtt8 /baselineskip=10pt
/beginverbatim

+ trap 1 2 3 
+ [ BATCH != BATCH ] 
+ mkdir /tmp/f72147 
+ cd /tmp/f72147 
+ ls -l 
total 0
+ assign -a /csc/lounamaa/deconv/variances.dat fort.2 
+ assign -a /csc/lounamaa/deconv/data.dat fort.3 
+ assign -a /csc/lounamaa/deconv/kernel.dat fort.4 
+ assign -a kerout.out fort.7
+ assign -a datout.out fort.8
+ assign -a varout.out fort.9
+ assign -a decout.out fort.10
+ assign -a resout.out fort.11
+ /csc/lounamaa/deconv/deconv 
   STOP              in DECONV  
+ ls -l 
total 66
-rw-------   1 lounamaa csc         9472 Feb 19 21:59 datout.out
-rw-------   1 lounamaa csc       218695 Feb 19 21:59 deconv.out
-rw-------   1 lounamaa csc         9450 Feb 19 21:59 decout.out
-rw-------   1 lounamaa csc          154 Feb 19 21:59 ex
-rw-------   1 lounamaa csc         1214 Feb 19 21:59 kerout.out
-rw-------   1 lounamaa csc         1743 Feb 19 21:59 resout.out
-rw-------   1 lounamaa csc        10850 Feb 19 21:59 varout.out
/endverbatim>


/endinput
