Programmering

Java 101: Ind og ud af standard input / output

I forudgående Java 101 artikler henviste jeg til begreberne omdirigering, standardinputenhed og standardoutputenhed. Flere eksempler kaldes for at demonstrere indtastning af data System.in.read (). Det viser sig at System.in.read () indlæser data fra standardinputenheden. Eksempler kaldes for at demonstrere outputdata System.out.print () og System.out.println (). I kontrast til System.in.read (), de der metoder - navngivne sekvenser af eksekverbar kode (udforskes i næste måneds artikel) - send deres output til standardoutputenheden. Vil du vide mere om standard I / O-koncepter? Læs videre!

Standard I / O er en standardiseret input / output-mekanisme, der stammer fra Unix-operativsystemet. Selvom denne mekanisme for det meste bruges med ældre ikke-GUI-operativsystemer, spiller standard I / O stadig en rolle i moderne GUI-operativsystemer (grafisk brugergrænseflade), hvor folk bruger den til at debugge fejlfunktionelle programmer og til at undervise input / output i indgangs- programmeringskurser på niveau.

Som du sikkert har gættet, bruger standard I / O enheder til at indtaste og udsende data. Disse enheder inkluderer standardindgang, standardoutput og standardfejl.

Standardindgang

Det standard inputenhed er den del af operativsystemet, der styrer, hvorfra et program modtager input. Standardinputenheden læser som standard den input fra en enhedsdriver, der er knyttet til tastaturet. Det kan du dog omdirigere, eller skift, inputkilden til en enhedsdriver, der er knyttet til en fil, så input synes at "magisk" komme fra en fil - i stedet for tastaturet.

Et program indtaster sine data fra standardinputenheden ved at ringe til Java'er System.in.read () metode. Se i SDK-dokumentationen, så finder du en klasse kaldet System. Denne klasse indeholder en variabel kaldet i - et objekt oprettet fra en underklasse af InputStream. Perioden karakter efter System siger, at i tilhører Systemog periodekarakteren efter i siger, at Læs() tilhører i. Med andre ord, Læs() er en metode, der hører til et objekt, der kaldes i, som igen tilhører en klasse kaldet System. (Jeg vil diskutere mere om klasser, objekter og "tilhører" næste måned.)

System.in.read () tager ingen argumenter og returnerer et heltal, hvilket har fået nogle til at tro det System.in.read () returnerer brugerindtastede heltal. For at afklare, System.in.read () enten returnerer en nøgles 7-bit ASCII-kode (hvis standardinputenheden er indstillet til tastaturet) eller en 8-bit byte fra en fil (hvis standardinputenheden er omdirigeret fra tastaturet til en fil). I begge tilfælde, System.in.read () konverterer koden til et 32-bit heltal og returnerer resultatet.

Antag, at standardinputenheden er indstillet til tastaturet. Følgende er en beskrivelse af, hvad der sker under Windows: Når du skriver en nøgle på et Windows-kontrolleret tastatur, gemmer operativsystemet denne nøgles 7-bit ASCII-kode i en intern nøglebuffer. Denne nøglebuffer rummer op til cirka 16 ASCII-koder og er organiseret som en første ind / først ud cirkulær kødatastruktur. System.in.read () henter ASCII-koden fra hovedet på nøglebufferen og fjerner derefter den kode fra nøglebufferen. Den 7-bit ASCII-kode konverteres derefter til en int -- ved System.in.read () forudgående 25 nul bit til koden - og vender tilbage til metodens opkald. Et sekund System.in.read () metodeopkald henter den næste ASCII-kode, som nu er i spidsen for nøglebufferen og så videre.

Antag, at der ikke er nogen ASCII-koder i nøglebufferen. Hvad der sker? System.in.read () venter på, at brugeren skriver taster og trykker på terminatoren. Under Windows er denne terminator den Gå ind nøgle. Trykker på Gå ind får Windows til at gemme en vognreturkode (ASCII 13) efterfulgt af en ny linjekode (ASCII 10) i nøglebufferen. Derfor kan nøglebufferen muligvis indeholde flere ASCII-koder efterfulgt af en vognretur og et nyt linjetegn. Den første af disse koder vender tilbage fra System.in.read (). Tjek den aktivitet ved at indtaste, kompilere og køre Ekko Ansøgning; dens kildekode vises i liste 1.

Liste 1. Echo.java

// Echo.java klasse Echo {public static void main (String [] args) throw java.io.IOException {int ch; System.out.print ("Indtast tekst:"); mens ((ch = System.in.read ())! = '\ n') System.out.print ((char) ch); }} 

Ekko udfører følgende trin:

  1. Ringer til System.out.print () metode, der tager en Snor argument for at sende en prompt
  2. Opkald System.in.read () at indtaste ASCII-koder fra standardinputenheden som 32-bit heltal
  3. Konverterer disse 32-bit heltal til 16-bit Unicode-tegn ved hjælp af (char) støbt
  4. Ringer til System.out.print () metode, der tager en char argument for at ekko disse Unicode-tegn til standardoutputenheden

De sidste tre trin i de foregående fire trin finder sted i et stykke løb og fortsætter, indtil et nyt linjetegn læses. At løbe Ekko så det indtaster fra tastaturet og output til skærmen, skal du udstede følgende kommandolinje: java Echo.

Selvom System.in.read () kaster aldrig en undtagelse (se ordtællingemnet i denne artikel for en definition af dette udtryk), når standardinputenheden er indstillet til tastaturet, kan det muligvis kaste en undtagelse, når du omdirigerer standardinputenheden fra tastaturet til fil. Antag for eksempel, at du omdirigerer standardinputenheden til en fil, og System.in.read () læser indhold fra filen. Antag nu, at filen er placeret på en diskette, og at brugeren skubber den disk ud under læsningsoperationen. Når udkastningen finder sted, System.in.read () kaster en undtagelse og informerer programmet om, at det ikke kan læse filen. Det giver grunden til at tilføje kaster java.io.IOException klausul til hoved () metodehoved. (Du vil udforske undtagelser, kaste undtagelser og relaterede begreber i en fremtidig artikel.)

Hvordan omdirigerer du standardinputenheden, så input stammer fra en fil? Svaret er at introducere et mindre end tegn, <, på kommandolinjen og følg dette symbol med et filnavn. For at se, hvordan det fungerer, skal du udstede følgende kommandolinje: java Echo <>. Kommandolinjen omdirigerer standardinputenheden til en fil, der kaldes Echo.java. Hvornår Ekko kører, fordi hver linje slutter med et nyt linjetegn, kun den første tekstlinje Echo.java vises på skærmen.

Antag at du har brug for et hjælpeprogram, der læser en hel fil og enten viser filens indhold på skærmen, kopierer indholdet til en anden fil eller kopierer indholdet til en printer. Desværre er Ekko programmet udfører kun denne opgave, indtil det møder den første nye linjekarakter. Hvad laver du? Svaret på problemet ligger i Type Ansøgning. Liste 2 indeholder kildekoden:

Notering 2. Skriv.java

// Type.java-klasse Type {public static void main (String [] args) kaster java.io.IOException {int ch; mens ((ch = System.in.read ())! = -1) System.out.print ((char) ch); }} 

Type ligner Ekkoder er dog ingen hurtig, og mens loop tester mod -1 (som angiver slutningen af ​​filen) i stedet for \ n (som angiver slutningen af ​​linjen). At løbe Type, udsted følgende kommandolinje: java Type <>. Indholdet af Skriv.java - eller hvilken fil der er angivet - vises. Prøv at specificere som et eksperiment java Type. Hvad tror du vil ske? (Tip: dette program ligner Ekko men slutter ikke, før du trykker på Ctrl + C.)

Tidligere nævnte jeg, at nogle programmører fejlagtigt tror det System.in.read () returnerer et brugerindtastet nummer. Som du lige har set, er det ikke tilfældet. Men hvad skal du gøre, hvis du vil bruge System.in.read () at hente et nummer? Se på Konvertere applikation, hvis kildekode er præsenteret i liste 3.

Notering 3. Convert.java

// Klasse Convert.java Konverter {public static void main (String [] args) kaster java.io.IOException {System.out.print ("Indtast et nummer:"); int num = 0; int ch; mens ((ch = System.in.read ())! = '\ n') hvis (ch> = '0' && ch <= '9') {num * = 10; num + = ch - '0'; } andet pause System.out.println ("num =" + num); System.out.println ("num squared =" + num * num); }} 

Liste 3's Konvertere programmet beder brugeren om at indtaste et nummer (via System.out.print ("Indtast et nummer:");). Den læser disse cifre - en ad gangen - og konverterer hvert cifers numeriske kode til et binært tal, der føjes til en variabel kaldet antal. Endelig opfordrer til System.out.println () output værdien indeni antal og kvadratet af denne værdi til standardudgangsenheden.

Konvertere demonstrerer den tidskendte teknik til at bruge en while-løkke til at teste for et ciffer, at multipultere en variabel med 10 (for at give plads til det indgående ciffer), konvertere et ciffer til dets binære ækvivalent og tilføje det binære ækvivalent til variablen. Denne teknik er dog ikke en lydteknik, der skal bruges, hvis du skriver et program til implementering i forskellige lande, da nogle lande bruger andre cifre end 0 til 9 - såsom tamilske cifre. For at få programmet til at fungere med andre cifre, skal du udvide if-sætningen for at teste for disse cifre og ændre ch - '0' udtryk. Heldigvis forenkler Java denne opgave ved at levere en Karakter klasse, som du vil udforske i en fremtidig artikel.

Standard output

Det standard outputenhed er den del af operativsystemet, der styrer, hvor et program sender dets output. Standardoutputenheden sender som standard output til en enhedsdriver, der er knyttet til skærmen. Outputdestinationen kan dog omdirigeres til en enhedsdriver, der er knyttet til en fil eller printer, hvilket resulterer i, at det samme program viser resultaterne på skærmen, gemmer dem i en fil eller giver en hardcopy-oversigt over resultaterne.

Du opnår standardoutput ved at ringe til Java'er System.out.print () og System.out.println () metoder. Bortset fra det faktum at Print() metoder udsender ikke et nyt linjetegn efter dataene, de to metodegrupper er ækvivalente. Der findes metoder til at udlæse boolsk, tegn, tegn array, dobbelt præcision flydende punkt, flydende punkt, heltal, langt heltal, streng og objektværdier. For at demonstrere disse metoder præsenterer Listing 4 kildekode til Print Ansøgning.

Fortegnelse 4. Print.java

// Print.java klasse Print {public static void main (String [] args) {boolean b = true; System.out.println (b); char c = 'A'; System.out.println (c); char [] carray = {'A', 'B', 'C'}; System.out.println (carray); dobbelt d = 3,5; System.out.println (d); flyde f = -9.3f; System.out.println (f); int i = 'X'; System.out.println (i); lang l = 9000000; System.out.println (l); Streng s = "abc"; System.out.println (s); System.out.println (ny udskrivning ()); }} 

Fortegnelse 4 har sandsynligvis udløst nogle spørgsmål til dig. For det første, hvad er alt det der? System.out. forretning gør foran println ()? Igen henvises til System klasse i SDK-dokumentationen. Klassen indeholder en variabel kaldet ud - et objekt oprettet fra en klasse kaldet PrintStream. Perioden karakter efter System angiver det ud tilhører System. Perioden karakter efter ud siger, at println () tilhører ud. Med andre ord, println () er en metode, der hører til et objekt, der kaldes ud, som igen tilhører en klasse kaldet System.

Det andet spørgsmål, du måske stiller dig selv, involverer println () argumentdatatyper: hvordan er det muligt for det samme println () metode, der skal kaldes med forskellige typer argumentdata? Svaret: fordi der er flere println () metoder i PrintStream klasse. Ved kørsel ved JVM hvilken println () metode til opkald ved at undersøge antallet af metodeopkaldsargumenter og deres datatyper. (At erklære flere metoder med samme navn men forskellige antal argumenter og datatyper er kendt som metodeoverbelastning. Jeg vil diskutere dette koncept i næste måned.)

Endelig undrer du dig måske over System.out.println (ny udskrivning ());. Denne metodeopkald illustrerer println () metode, der tager en Objekt argument. Først oprettelsesoperatøren ny skaber et objekt fra Print klasse og returnerer en henvisning til - også kendt som adressen på - objektet. Endelig overføres denne adresse som et argument til println () metode, der tager en Objekt argument. Metoden konverterer objektets indhold til en streng og outputter den streng. Som standard består strengen af ​​navnet på objektets klasse efterfulgt af et @ (at) tegn efterfulgt af et hexadecimal-formateret heltal, der repræsenterer objektets hashcode. (Jeg vil præsentere hashcodes og konvertering af objekter til strenge i en kommende artikel.)

Udarbejde Udskriv.java og kør programmet ved at udstede følgende kommandolinje: java Udskriv. Du skal se ni linjer med output. Omdiriger output til ud.dat fil ved at udstede følgende kommandolinje: java Udskriv> out.dat. Du kan nu se indholdet af filen.

Det større end tegnet, >, angiver standard output omdirigering. Når du vil omdirigere standardoutputenheden fra skærmen til en fil eller printer, skal du angive dette symbol efterfulgt af filen eller printernavnet på kommandolinjen. For eksempel omdirigere Printoutput til en Windows-printer ved at udstede følgende kommandolinje: java Udskriv> prn.