سلام! سخنرانی امروز به دو بخش تقسیم می شود. ما برخی از موضوعات قدیمی را که قبلاً در مورد آنها صحبت کرده ایم را تکرار می کنیم و به برخی از ویژگی های جدید نگاه می کنیم :) بیایید با اولی شروع کنیم. تکرار مادر یادگیری است :) شما قبلاً از کلاسی مانند
BufferedReader
. امیدوارم هنوز این دستور را فراموش نکرده باشید:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
قبل از خواندن ادامه مطلب، سعی کنید به خاطر داشته باشید که هر جزء ( System.in, InputStreamReader, BufferedReader
) مسئول چه چیزی است و برای چه چیزی مورد نیاز است. اتفاق افتاد؟ اگر نه، نگران نباشید :) اگر تا این لحظه چیزی را فراموش کرده اید، این سخنرانی را که به خوانندگان اختصاص داده شده است دوباره بخوانید . بیایید به طور خلاصه به یاد بیاوریم که هر کدام از آنها چه کاری می توانند انجام دهند. System.in
یک رشته برای دریافت اطلاعات از صفحه کلید است. اصولاً برای اجرای منطق خواندن متن، یکی برای ما کافی بود. اما، همانطور که به یاد دارید، System.in
فقط می تواند بایت ها را بخواند، نه کاراکترها:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
اگر این کد را اجرا کنیم و حرف Y را در کنسول وارد کنیم، خروجی به این صورت خواهد بود:
Й
208
153
10
کاراکترهای سیریلیک 2 بایت در حافظه اشغال می کنند که بر روی صفحه نمایش داده می شود (و عدد 10 نمایش بایت یک شکست خط است، یعنی فشردن Enter). خواندن بایت ها بسیار لذت بخش است، بنابراین استفاده از آن System.in
به شکل خالص آن ناخوشایند خواهد بود. برای خواندن حروف سیریلیک (و نه تنها) که برای همه قابل درک است، ما 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);
}
}
}
اگر همان حرف Y را در کنسول وارد کنیم، نتیجه این بار متفاوت خواهد بود:
Й
1049
10
InputStreamReader
دو بایت خوانده شده (208، 153) را به یک عدد 1049 تبدیل کرد. این خواندن توسط کاراکتر است. 1049 مربوط به حرف "Y" است که به راحتی قابل تأیید است:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
خروجی کنسول:
Й
خوب، همانطور که برای BufferedReader
'a (و به طور کلی - BufferedAnything)، کلاس های بافر برای بهینه سازی عملکرد استفاده می شود. دسترسی به یک منبع داده (فایل، کنسول، منبع در اینترنت) از نظر عملکرد یک عملیات نسبتاً گران است. بنابراین، برای کاهش تعداد این گونه تماس ها، BufferedReader
داده ها را می خواند و در یک بافر خاص جمع می کند، که بعداً می توانیم از آنجا دریافت کنیم. در نتیجه تعداد تماس ها با منبع داده چندین برابر یا حتی ده ها برابر کاهش می یابد! یکی دیگر از ویژگیهای اضافی BufferedReader
«a و مزیت آن نسبت به معمولی InputStreamReader
» روش بسیار مفیدی است 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("Пользователь ввел следующий текст:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Пользователь ввел следующий текст:
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
البته، BufferedReader
این یک مکانیسم بسیار انعطاف پذیر است و به شما امکان می دهد نه تنها با صفحه کلید کار کنید. برای مثال، میتوانید دادهها را مستقیماً از اینترنت با ارسال URL مورد نیاز به خواننده بخوانید:
public class URLReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("https://www.oracle.com/index.html");
BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
شما می توانید داده ها را از یک فایل با عبور دادن مسیر به آن بخوانید:
public class Main {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("testFile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
String str;
while ((str = reader.readLine()) != null) {
System.out.println (str);
}
reader.close();
}
}
جایگزینی System.out
حال بیایید به یک احتمال جالب توجه کنیم که قبلاً به آن اشاره نکرده بودیم. همانطور که احتمالاً به خاطر دارید،System
دو فیلد ثابت در کلاس وجود دارد - System.in
و System.out
. این برادران دوقلو، اشیاء کلاس نخ هستند. - کلاس System.in
انتزاعی InputStream
یک System.out
کلاس PrintStream
. اکنون به طور خاص در مورد آن صحبت خواهیم کرد System.out
. اگر وارد کد منبع کلاس شویم System
، این را خواهیم دید:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
بنابراین، System.out
فقط یک متغیر کلاس ثابت معمولیSystem
. هیچ جادویی در آن وجود ندارد :) متغیر out
متعلق به کلاس است PrintStream
. در اینجا یک سوال جالب وجود دارد: چرا هنگام اجرای کد، System.out.println()
خروجی در کنسول ظاهر می شود و در جای دیگری نیست؟ و آیا می توان این را به نحوی تغییر داد؟ به عنوان مثال، می خواهیم داده ها را از کنسول بخوانیم و در یک فایل متنی بنویسیم. آیا می توان به نحوی چنین منطقی را بدون استفاده از کلاس های خواننده و نویسنده اضافی و صرفاً با استفاده از ادغام کرد System.out
؟ هنوز تا حد امکان :) و اگرچه متغیر System.out
توسط یک اصلاح کننده تعیین شده است final
، ما هنوز هم می توانیم آن را انجام دهیم! پس برای این به چه چیزی نیاز داریم؟ در ابتداPrintStream
، به جای شیء فعلی، به یک شی کلاس جدید نیاز داریم . شی فعلی نصب شده در کلاس System
به طور پیش فرض برای ما مناسب نیست: به کنسول اشاره می کند. ما باید یک فایل جدید ایجاد کنیم که به یک فایل متنی به عنوان "مقصد" برای داده های ما اشاره کند. ثانیا ، باید بدانید که چگونه یک مقدار جدید را به یک متغیر اختصاص دهید System.out
. شما نمی توانید آن را به همین شکل انجام دهید، زیرا علامت گذاری شده است final
. بیایید از آخر شروع کنیم. کلاس System
دقیقاً حاوی متدی است که ما نیاز داریم - setOut()
. یک شی را به عنوان ورودی می گیرد PrintStream
و آن را به عنوان نقطه خروجی تنظیم می کند. فقط چیزی که ما نیاز داریم! تنها چیزی که باقی می ماند ایجاد شی است PrintStream
. انجام این کار نیز آسان است:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
کل کد به شکل زیر خواهد بود:
public class SystemRedirectService {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
/*Сохраним текущее meaning System.out в отдельную переменную, чтобы потом
можно было переключиться обратно на вывод в консоль*/
PrintStream console = System.out;
// Присваиваем System.out новое meaning
System.setOut(filePrintStream);
System.out.println("Эта строка будет записана в текстовый файл");
// Возвращаем System.out старое meaning
System.setOut(console);
System.out.println("А эта строка - в консоль!");
}
}
در نتیجه خط اول در یک فایل متنی نوشته می شود و خط دوم به کنسول خروجی می شود :) می توانید این کد را در IDE خود کپی کرده و اجرا کنید. با باز کردن فایل متنی، خواهید دید که خط مورد نیاز با موفقیت در آنجا نوشته شده است :) با این کار سخنرانی به پایان می رسد. امروز نحوه کار با استریم ها و خوانندگان را به یاد آوردیم، تفاوت آنها با یکدیگر را به یاد آوردیم و در مورد ویژگی های جدیدی System.out
که تقریباً در هر درس استفاده می کردیم یاد گرفتیم :) شما را در سخنرانی های بعدی می بینیم!
GO TO FULL VERSION