CodeGym /Java blogg /Slumpmässig /Läser från tangentbordet: "läsare"
John Squirrels
Nivå
San Francisco

Läser från tangentbordet: "läsare"

Publicerad i gruppen
Hej! Lektionerna och uppgifterna på nivå 3 lärde dig hur du visar saker på konsolen och, när du rörde dig åt andra hållet, hur du läser data från tangentbordet.
Läsa från tangentbordet: "läsare" - 1
Du lärde dig till och med att använda följande komplexa konstruktion för att åstadkomma detta:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Men det finns en fråga som vi inte har besvarat ännu.

Hur i hela friden fungerar det här?

I verkligheten är programmen sällan helt oberoende. De kommunicerar med andra program, system, Internet etc. Med "kommunicera" menar vi främst "utbyte av data". Det vill säga att de tar emot en del extern data och även skickar interna programdata någonstans. Exempel på program som utbyter data finns i överflöd i vardagen. Till exempel låter många webbplatser dig logga in med ditt Facebook- eller Twitter-konto istället för att registrera dig. I den här situationen utbyter två program (t.ex. Twitter och webbplatsen du loggar in på) nödvändiga data. Slutresultatet är att du har loggat in. Ordet " ström"används för att beskriva processen för datautbyte. Var kom detta namn ifrån? Enligt din erfarenhet kan en "bäck" vara mer förknippad med floder och än med programmering. Det är ingen tillfällighet :) En ström är i grunden en rörlig bit data. Med andra ord, i programmering är det inte vatten som rinner — utan snarare data i form av byte och tecken. Vi kan ta emot bitar av data från en dataström och sedan använda dem. Återigen kommer vi att använda vatten/flöde-analogin: du kan ösa vatten från en flod för att göra soppa, släcka eld eller vattna dina blommor. Strömmar låter dig arbeta med vilken datakälla som helst: oavsett om det är Internet, din dators filsystem eller något annat — det spelar ingen roll. Strömmar är ett universellt verktyg. De tillåter ett program att ta emot data var som helst (indataströmmar) och skicka dem var som helst (outputströmmar). Deras uppgift är densamma: att ta data från en plats och skicka den till en annan. Det finns två typer av strömmar:
  1. Indataströmmar används för att ta emot data
  2. Utdataströmmar är till för att skicka data.
I Java implementeras dessa strömmar av klasserna InputStreamoch . OutputStreamMen strömmarna kan kategoriseras på ett annat sätt. Förutom in- och utströmmar talar vi även om byteströmmar och teckenströmmar . Innebörden här borde vara tydlig nog: byteström skickar information som en uppsättning byte, medan en teckenström skickar den som en uppsättning tecken. I den här lektionen kommer vi att uppehålla oss vid ingångsströmmar. Jag lägger en länk med information om utdataströmmar i slutet av lektionen. Du kan läsa den på egen hand :) Ta nu en titt på den här koden:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
När du gick igenom lektionerna, tyckte du inte att den här raden var ganska skrämmande? :) Så kommer inte att vara fallet när vi har utforskat hur det fungerar. Låt oss rätta till saker och ting. Vi börjar i slutet. System.inär ett InputStreamobjekt, en instans av klassen vi pratade om tidigt. Det är en ingångsström kopplad till en systemingångsenhet (tangentbordet). Förresten, du är indirekt bekant med denna ström. När allt kommer omkring använder du ofta dess "kollega" — System.out! System.outär systemets utström . Den används för att mata ut data till konsolen via din favoritmetod , System.out.println()som du använder konstant :) System.outär en ström för att skicka data till konsolen, medanSystem.inär för att hämta data från tangentbordet. Allt är enkelt :) Dessutom kan vi läsa data från tangentbordet utan denna enorma konstruktion. Vi kan helt enkelt skriva: System.in.read();

public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
Klassen InputStream(kom ihåg, System.inär ett InputStreamobjekt) har en read()metod som låter dig läsa data. Det finns ett problem: den läser bytes , inte tecken . Det är tråkigt att bara använda engelska bokstäver så låt oss försöka läsa det kinesiska tecknet "魚" från tangentbordet (kopiera bara den här bokstaven härifrån och klistra in den på konsolen med ctrl + v på PC eller Command + v Mac ) . Denna karaktär betyder förresten "en fisk". Konsolutgång: 233 173 154 10 Denna symbol och många andra kineser upptar 3 byte i datorns minne (till skillnad från latinska bokstäver, som bara upptar 1 byte). I det här fallet läses 4 byte från strömmen: de första tre representerar tecknet "魚", och andra byte representerar en ny rad (Enter). Följaktligen, System.ini sin outsmyckade form är inte ett alternativ för oss. Människor (med sällsynta undantag!) vet inte hur man läser bytes. Men InputStreamReaderklassen kommer till undsättning! Låt oss se vad det är för djur.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Vi skickar System.intill InputStreamReader -objektet. Klassnamnet säger det! Vi skapar ett InputStreamReaderobjekt och skickar det en indataström som det kommer att läsa data från. I detta fall...

new InputStreamReader(System.in)
...vi säger till det, "du kommer att läsa data från systemets indataström (från tangentbordet)". Men detta är inte dess enda funktion! Den InputStreamReadertar inte bara emot data från strömmen. Den konverterar också byteströmmar till teckenströmmar . Du behöver med andra ord inte längre konvertera datan från "ettor och nollor" till ett "läsbart språk". InputStreamreadergör allt för dig. Naturligtvis InputStreamReaderär det inte begränsat till att läsa data från konsolen. Den kan läsa data från andra platser också. Till exempel, från en fil:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
Här skapar vi en FileInputStream(en smak av InputStream), skickar in filsökvägen och skickar själva strömmen till InputStreamReader. Nu kommer den att kunna läsa data från filen (om en fil faktiskt finns på sökvägen, förstås). Vi använder också InputStreamReaderklassens read()metod för att läsa data (källan till data spelar ingen roll: konsolen, en fil eller någon annanstans). Vad är skillnaden mellan System.in.read()och InputStreamReader.read()?\ Låt oss igen försöka läsa tecknet "魚" med en InputStreamReader. Jag påminner dig om vad som faktiskt lästes av System.in.read(): 233 173 154 10 Och hur fungerar InputStreamReadersamma arbete?

public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
Konsolutgång: 39770 10 Skillnaden är direkt uppenbar. Den sista byten (som representerar den nya raden) förblir oförändrad (siffran 10), men tecknet "魚" konverterades till en enda kod "39770". Det här är vad det innebär att läsa karaktärer! Om du inte tror att 39770 representerar bokstaven "魚", är det lätt att övertyga dig själv :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 39770;
       System.out.println(x);
   }
}
Konsolutgång: Men om InputStreamReaderdet är så bra, varför behöver vi också BufferedReader? InputStreamReadervet hur man läser data och konverterar bytes till tecken. Vad mer kan vi begära? Varför en annan läsare? :/ Svaret är mycket enkelt: för större prestanda och bekvämlighet . Låt oss börja med prestanda. När BufferedReaderden läser data använder den ett speciellt område som kallas en buffert, där den "lagrar" tecknen den läser. I slutändan, när dessa tecken behövs i programmet, kommer de att tas från bufferten, inte direkt från datakällan (tangentbord, fil, etc.). Detta sparar mycket resurser. För att förstå hur detta fungerar, föreställ dig en kurir i ett stort företag. Kuriren sitter på ett kontor och väntar på att någon ska ta med paket för leverans. Varje gång han får ett nytt paket kan han genast ge sig ut på vägen. Men det kan bli många paket under dagen. Han skulle behöva göra massor av resor mellan kontoret och leveransadresserna. Istället sätter kuriren en låda på sitt kontor. Alla lägger sina paket i lådan. Nu kan kuriren lugnt ta lådan och flytta från adress till adress. Detta sparar mycket tid, eftersom han inte behöver återvända till kontoret varje gång. I det här exemplet är boxen bara en buffert och kontoret är en datakälla. Det är mycket lättare för kuriren att ta paket från en enda låda när de gör leveranser än att gå tillbaka till kontoret varje gång. Han kommer att spara bensin också. På samma sätt är det i ett program mycket mindre resurskrävande att ta data från en buffert än att referera till datakällan varje gång. Som ett resultat,BufferedReader+ InputStreamReaderär snabbare än InputStreamReaderensam . Vi har funderat på prestanda. Vad sägs om bekvämlighet? Den största fördelen är att den Bufferedreaderkan läsa data inte bara ett tecken åt gången (även om det kan göra detta med sin read()metod), utan också hela rader åt gången! Detta görs med readLine()metoden;

public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
Konsolutgång: CodeGym är den bästa webbplatsen för att lära sig Java! Vi läser denna rad från tangentbordet: CodeGym är den bästa webbplatsen för att lära sig Java! Detta är särskilt användbart när du läser stora mängder data. Att läsa en eller två rader text tecken för tecken är fortfarande möjligt. Men att läsa i "Krig och fred" en bokstav i taget skulle vara lite problematiskt :)

Mer läsning:

Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION