CodeGym /وبلاگ جاوا /Random-FA /خواندن از صفحه کلید: "خوانندگان"
John Squirrels
مرحله
San Francisco

خواندن از صفحه کلید: "خوانندگان"

در گروه منتشر شد
سلام! درس‌ها و وظایف در سطح 3 به شما یاد می‌دهند که چگونه چیزها را روی کنسول نمایش دهید، و با حرکت در جهت دیگر، چگونه داده‌ها را از صفحه کلید بخوانید.
خواندن از صفحه کلید: "خوانندگان" - 1
شما حتی یاد گرفتید که از ساختار پیچیده زیر برای انجام این کار استفاده کنید:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
اما یک سوال وجود دارد که ما هنوز به آن پاسخ نداده ایم.

در دنیا این کار چگونه است؟

در واقعیت، برنامه ها به ندرت کاملاً مستقل هستند. آنها با سایر برنامه ها، سیستم ها، اینترنت و غیره ارتباط برقرار می کنند. منظور ما از "ارتباط" عمدتاً "تبادل داده ها" است. یعنی مقداری داده خارجی دریافت می کنند و همچنین داده های برنامه داخلی را به جایی می فرستند. نمونه هایی از برنامه های مبادله داده در زندگی روزمره فراوان است. به عنوان مثال، بسیاری از وب سایت ها به شما اجازه می دهند به جای ثبت نام، با استفاده از حساب فیس بوک یا توییتر خود وارد شوید. در این شرایط، دو برنامه (مثلاً توییتر و وب‌سایتی که وارد آن می‌شوید) داده‌های لازم را مبادله می‌کنند. نتیجه نهایی این است که شما با موفقیت وارد سیستم شده اید. کلمه "جریان" برای توصیف فرآیند تبادل داده استفاده می شود. این نام از کجا آمده است؟ در تجربه شما، یک "جریان" ممکن است بیشتر با رودخانه ها و برنامه نویسی مرتبط باشد. این تصادفی نیست :) یک جریان، در اصل، یک قطعه متحرک از داده است. به عبارت دیگر، در برنامه نویسی، این آب نیست که جریان دارد - بلکه داده ها به شکل بایت و کاراکتر هستند. می‌توانیم بیت‌هایی از داده‌ها را از یک جریان داده دریافت کنیم و سپس از آنها استفاده کنیم. مجدداً از قیاس آب/جریان استفاده می کنیم: می توانید برای تهیه سوپ، خاموش کردن آتش یا آبیاری گل هایتان از رودخانه آب بگیرید. Streams به شما امکان می‌دهد با هر منبع داده کار کنید: اینترنت، سیستم فایل رایانه‌تان یا چیز دیگری - تفاوتی ندارد. استریم ها ابزاری جهانی هستند. آنها به یک برنامه اجازه می دهند که داده ها را از هر جایی دریافت کند (جریان های ورودی) و آن را به هر کجا ارسال کند (جریان های خروجی). وظیفه آنها یکسان است: گرفتن داده ها از یک مکان و ارسال آن به مکان دیگر. دو نوع جریان وجود دارد:
  1. جریان های ورودی برای دریافت داده ها استفاده می شوند
  2. جریان های خروجی برای ارسال داده ها هستند.
در جاوا این استریم ها توسط کلاس های InputStreamand پیاده سازی می شوند OutputStream. اما جریان ها را می توان به شکل دیگری دسته بندی کرد. ما علاوه بر جریان های ورودی و خروجی، از جریان های بایت و جریان های کاراکتر نیز صحبت می کنیم . معنی در اینجا باید به اندازه کافی واضح باشد: جریان بایت اطلاعات را به صورت مجموعه ای از بایت ها ارسال می کند، در حالی که یک جریان کاراکتر آن را به عنوان مجموعه ای از کاراکترها ارسال می کند. در این درس، به جریان های ورودی می پردازیم. در پایان درس لینکی با اطلاعات مربوط به جریان های خروجی قرار می دهم. شما می توانید آن را به تنهایی بخوانید :) حالا به این کد نگاه کنید:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
وقتی دروس را مرور می‌کردید، فکر نمی‌کردید این خط نسبتاً ترسناک باشد؟ :) وقتی نحوه کارکرد آن را بررسی کردیم، اینطور نخواهد بود. بیایید همه چیز را درست کنیم. از انتها شروع می کنیم System.inیک InputStreamشی است، نمونه ای از کلاسی است که در ابتدا درباره آن صحبت کردیم. این یک جریان ورودی است که به یک دستگاه ورودی سیستم (صفحه کلید) متصل است. ضمناً شما به طور غیر مستقیم با این جریان آشنا هستید. پس از همه، شما اغلب از "همکار" آن استفاده می کنید - System.out! جریان خروجیSystem.out سیستم است . برای خروجی داده‌ها به کنسول از طریق روش دلخواه شما استفاده می‌شود که دائماً از آن استفاده می‌کنید :) یک جریان برای ارسال داده به کنسول است، در حالی که برای دریافت داده از صفحه کلید است. همه چیز ساده است :) علاوه بر این، ما می توانیم داده ها را از صفحه کلید بدون این ساختار عظیم بخوانیم. ما می توانیم به سادگی بنویسیم: ; System.out.println()System.outSystem.inSystem.in.read()
public class Main {

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

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
کلاس InputStream(به یاد داشته باشید، System.inیک InputStreamشی است) read()متدی دارد که به شما امکان می دهد داده ها را بخوانید. یک مشکل وجود دارد: بایت ها را می خواند نه کاراکترها . فقط استفاده از حروف انگلیسی خسته کننده است، بنابراین بیایید سعی کنیم کاراکتر چینی "魚" را از صفحه کلید بخوانیم (فقط این حرف را از اینجا کپی کنید و با استفاده از ctrl + v در رایانه شخصی یا Command + v در Mac آن را در کنسول قرار دهید ) . این شخصیت به هر حال به معنای "ماهی" است. خروجی کنسول: 233 173 154 10 این نماد و بسیاری از چینی های دیگر 3 بایت در حافظه رایانه اشغال می کنند (برخلاف حروف لاتین که فقط 1 بایت را اشغال می کنند). در این مورد، 4 بایت از جریان خوانده می شود: سه بایت اول نشان دهنده کاراکتر "魚"، و بایت دیگر نشان دهنده یک خط جدید (Enter) است. بر این اساس، System.inدر شکل بدون تزئین آن گزینه ای برای ما نیست. انسان ها (به استثنای نادر!) نمی دانند چگونه بایت ها را بخوانند. اما InputStreamReaderکلاس به کمک می آید! بیایید ببینیم این چه نوع حیوانی است.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
ما System.inبه شی InputStreamReader منتقل می کنیم . اسم کلاس میگه! یک شی ایجاد می کنیم InputStreamReaderو یک جریان ورودی به آن ارسال می کنیم که داده ها را از آن بخواند. در این مورد...
new InputStreamReader(System.in)
ما به آن می گوییم، "شما داده ها را از جریان ورودی سیستم (از صفحه کلید) خواهید خواند". اما این تنها عملکرد آن نیست! نه تنها داده InputStreamReaderها را از جریان دریافت می کند. همچنین جریان های بایت را به جریان های کاراکتری تبدیل می کند . به عبارت دیگر، دیگر نیازی به تبدیل داده ها از «یک و صفر» به «زبان قابل خواندن توسط انسان» ندارید. InputStreamreaderهمه چیز را برای شما انجام می دهد البته، InputStreamReaderبه خواندن اطلاعات از کنسول محدود نمی شود. این می تواند داده های مکان های دیگر را نیز بخواند. به عنوان مثال، از یک فایل:
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"));
   }
}
FileInputStreamدر اینجا یک (یک طعم از ) ایجاد می کنیم InputStream، در مسیر فایل پاس می دهیم و خود جریان را به InputStreamReader. اکنون می‌تواند داده‌ها را از فایل بخواند (البته اگر فایلی واقعاً در مسیر وجود داشته باشد). ما همچنین از متد InputStreamReaderکلاس read()برای خواندن داده ها استفاده می کنیم (منبع داده ها مهم نیست: کنسول، یک فایل یا جای دیگر). چه تفاوتی بین System.in.read()و وجود دارد InputStreamReader.read()؟\ بیایید دوباره سعی کنیم شخصیت "魚" را با علامت بخوانیم InputStreamReader. آنچه را که واقعاً توسط System.in.read(): 233 173 154 10 خوانده شد به شما یادآوری می کنم و چگونه InputStreamReaderهمان کار را انجام می دهد؟
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);
       }
   }
}
خروجی کنسول: 39770 10 تفاوت بلافاصله آشکار می شود. آخرین بایت (که نشان دهنده خط جدید است) بدون تغییر باقی می ماند (عدد 10)، اما کاراکتر "魚" به یک کد "39770" تبدیل شد. معنی خواندن شخصیت ها همین است! اگر باور ندارید که 39770 نشان دهنده حرف "魚" است، به راحتی می توانید خود را متقاعد کنید :)
import java.io.IOException;

public class Main {

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

       char x = 39770;
       System.out.println(x);
   }
}
خروجی کنسول: اما اگر بسیار عالیInputStreamReader است، چرا ما نیز به آن نیاز داریم BufferedReader؟ InputStreamReaderمی داند چگونه داده ها را بخواند و بایت ها را به کاراکتر تبدیل کند. چه چیزی بیشتر می توانیم بخواهیم؟ چرا خواننده دیگر؟ :/ پاسخ بسیار ساده است: برای عملکرد و راحتی بیشتر . بیایید با عملکرد شروع کنیم. هنگام BufferedReaderخواندن داده ها، از ناحیه خاصی به نام بافر استفاده می کند، جایی که کاراکترهایی را که می خواند ذخیره می کند. در نهایت، زمانی که این کاراکترها در برنامه مورد نیاز باشند، از بافر گرفته می شوند، نه مستقیماً از منبع داده (صفحه کلید، فایل و غیره). این باعث صرفه جویی در منابع زیادی می شود. برای درک اینکه چگونه این کار می کند، یک پیک را در یک شرکت بزرگ تصور کنید. پیک در دفتری می نشیند و منتظر کسی است که بسته ها را برای تحویل بیاورد. هر بار که او یک بسته جدید دریافت می کند، می تواند بلافاصله به جاده برسد. اما ممکن است بسته های زیادی در طول روز وجود داشته باشد. او مجبور بود بین آدرس دفتر و محل تحویل، سفرهای زیادی انجام دهد. در عوض، پیک جعبه ای را در دفترش می گذارد. همه بسته های خود را داخل جعبه می گذارند. حالا پیک می تواند با آرامش جعبه را بگیرد و از آدرسی به آدرس دیگر حرکت کند. این باعث صرفه جویی در زمان می شود، زیرا او مجبور نیست هر بار به دفتر بازگردد. در این مثال، جعبه فقط یک بافر است و دفتر یک منبع داده است. برای پیک گرفتن بسته ها از یک جعبه در هنگام تحویل بسیار آسان تر از بازگشت به دفتر است. بنزین هم پس انداز خواهد کرد. به طور مشابه، در یک برنامه دریافت داده از یک بافر نسبت به مراجعه به منبع داده در هر بار کمتر به منابع نیاز دارد. در نتیجه، BufferedReader+ InputStreamReaderسریعتر از InputStreamReaderتنهایی است . ما عملکرد را در نظر گرفته ایم. در مورد راحتی چطور؟ مزیت اصلی این است که Bufferedreaderمی تواند داده ها را نه تنها یک کاراکتر در یک زمان بخواند (البته با روش خود می تواند این کار را انجام دهد read())، بلکه کل خطوط را در یک زمان می خواند! این با استفاده از readLine()روش انجام می شود؛
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);
   }
}
خروجی کنسول: CodeGym بهترین وب سایت برای یادگیری جاوا است! این خط را از روی صفحه کلید می خوانیم: CodeGym بهترین وب سایت برای یادگیری جاوا است! این به ویژه در هنگام خواندن مقادیر زیاد داده مفید است. خواندن یک یا دو خط متن به کاراکتر هنوز امکان پذیر است. اما خواندن یک نامه در "جنگ و صلح" تا حدودی مشکل ساز است :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION