خوندن فایل با Scanner در جاوا و کاتلین

خوندن فایل با Scanner در جاوا و کاتلین

دسترسی سریع

بررسی کلاس Scanner

کلاس Scanner علاوه بر خوندن داده ها از کنسول برای خوندن متن فایل هم مورد استفاده قرار میگیره.

در مطلب قبل گفتیم با استفاده از PrintWriter میتونیم داده های متنی رو در فایل بنویسیم. در این مطلب به خوندن متن از فایل با استفاده از Scanner در جاوا و کاتلین میپردازیم.

احتمالا با کلاس Scanner آشنایی داشته باشید تا اینجا از Scanner برای خوندن ورودی از کنسول استفاده میکردیم؛ برای این کار نیاز داشتیم فیلد استاتیک in در کلاس System رو به عنوان پارامتر به کانستراکتور Scanner پاس بدیم. مقدار فیلد in از نوع InputStream است.

کلاس Scanner در جاوا و کاتلین علاوه بر خوندن داده ها از کنسول برای خوندن متن و داده های Primitive از فایل نیز مورد استفاده قرار میگیره.

این کلاس همانند سایر کلاس های خوندن و نوشتن از AutoClosable ارث بری میکنه بنابراین میتونیم داخل try-with-resources تعریفش کنیم.

کلاس Scanner برخلاف سایر کلاس های خوندن و نوشتن در فایل، که در پکیج io یا nio تعریف شدن، در پکیج util تعریف شده است.

کانستراکتور و متد (توابع) کلاس Scanner در زیر بیان شده است.

java.util.Scanner
+Scanner(File)
یک آبجکت از Scanner ایجاد میکنه و مسیر فایل رو با File تعریف میکنیم.
+Scanner(String)
یک آبجکت از Scanner ایجاد میکنه و مسیر فایل رو با String تعریف میکنیم.
+Scanner(Path)
یک آبجکت از Scanner ایجاد میکنه و مسیر فایل رو با Path تعریف میکنیم.
+Scanner(InputStream)
یک آبجکت از Scanner ایجاد میکنه و مسیر فایل رو با کلاس های InputStream تعریف میکنیم.
+nextLine()
خط فعلی متن فایل رو میخونه و میره خط بعدی.
+next()
کلمه ی فعلی متن رو تا جایی که اسپیس نباشه میخونه و میره سراغ بعدی.
+nextInt()
اگه کلمه ی فعلی عدد باشه مانند next میخونه و به عنوان متغیر int در برنامه برمیگردونه.
+nextLong()
اگه کلمه ی فعلی عدد باشه مانند next میخونه و به عنوان long در برنامه برمیگردونه.
+nextFloat()
اگه کلمه ی بعدی عدد باشه مانند next میخونه و به عنوان float در برنامه برمیگردونه.
+nextDouble()
اگه کلمه ی فعلی عدد باشه مانند next میخونه و به عنوان double در برنامه برمیگردونه.
+hasNext()
بررسی میکنه آیا کلمه ی بعدی در متن وجود داره یا خیر.
+hasNextLine()
بررسی میکنه آیا خط بعدی در متن وجود داره یا خیر
+close()
فایل رو میبنده؛ استفاده نکردن از این متد بعد از پایان خوندن فایل یا try-with-resources ممکنه باعث رسیدن آسیب به فایل بشه.

اگه جایی از متن عدد باشه علاوه بر next میتونیم با nextInt، nextDouble، nextLong و nextFloat بخونیم تفاوتشون تو نوعیه که بر میگردونن مثلا اگه عددی رو در متن با nextInt بخونیم نوع int برمیگردونه و...

توجه

اگه بجای خوندن عدد با nextInt، nextLong، nextFloat و nextDouble کلمه ای رو بخونیم که عدد نیست دچار InputMismatchException میشیم.

توجه

اگه متن خالی باشه و یا با Scanner اخر متن باشیم و بخوایم کلمه فعلی رو بخونیم؛ چون کلمه ای برای خوندن وجود نداره دچار NoSuchElementException میشیم.

مثال

ابتدا با PrintWriter اطلاعات یک فرد رو در فایل ذخیره میکنیم و سپس با Scanner اطلاعات ذخیره شده در فایل رو میخونیم

public static void main(String[] args){ File file = new File("user-info.txt"); if(!file.exists()){ try(PrintWriter output = new PrintWriter(file)){ output.print("John "); output.print("Smith "); output.println(24); }catch(IOException e){ System.out.println(e.getMessage()); } } try(Scanner input = new Scanner(file)){ String firstname = input.next(); String lastname = input.next(); int age = input.nextInt(); System.out.println(firstname); System.out.println(lastname); System.out.println(age); }catch(IOException e){ System.out.println(e.getMessage()); } }
fun main(){ val file = File("user-info.txt") if(!file.exists()){ val output = PrintWriter(file); output.use{ it -> it.print("John "); it.print("Smith "); it.println(24); } } val input = new Scanner(File("user-info.txt"); input.use{ it -> val firstname = it.next() val lastname = it.next() val age = it.nextInt() println(firstname) println(lastname) println(age) } }

در بالا با next به ترتیب نام و نام خانوادگی رو خونده و سپس با nextInt سن فرد رو میخونیم و در نهایت با println داده ها رو در کنسول نمایش میدیم.

مثال

در مثال زیر میخوایم یک متن رو از فایل با Scanner بخونیم و کلمات sun رو با rain و sunny رو با rainy عوض کنیم و در آخر ذخیره کنیم.

متن زیر رو در یک فایل ذخیره کرده و در برنامه مسیر متن ذخیره شده رو به‌جای PATH_TO_SOURCE_FILE بدید.

The weather is sunny it's a good idea to walk through a sunny day The perfume of sweet plants is pleasurable in this sunny day. Let's walk through this sunny day.

public static void main(String[] args) { File f = new File("PATH_TO_SOURCE_FILE"); try { //باز کردن فایل با Scanner Scanner input = new Scanner(f); StringBuilder edited = new StringBuilder(); while (input.hasNext()) { String line = input.nextLine(); line = line.replaceAll("sunny", "rainy") + "\n"; edited.append(line); } //بستن فایل بعد از عملیات خوندن input.close(); //باز کردن فایل با PrintWriter PrintWriter output = new PrintWriter(f); output.println(edited); //بستن فایل بعد از عملیات نوشتن output.close(); }catch (IOException e){ System.out.println(e.getMessage()); } }
fun main(){ val f = File("PATH_TO_SOURCE_FILE") val edited = StringBuilder() val input = Scanner(f) input.use { it -> while (it.hasNext()) { var line: String = it.nextLine() line = line.replace(Regex("sunny")) { "rainy" } edited.append(line).append("\n") } } val output = PrintWriter(f) output.use { it -> it.println(edited) } }

هنگام خوندن فایل با Scanner در هربار تکرار حلقه ی while یک خط از متن خونده شده و در متغیر line ذخیره میشه در همونجا کلمه ی sunny با rainy عوض کرده و در آخر کار با PrintWriter کل متن رو ذخیره میکنیم.

کلاس StringBuilder با جاوا کمی تفاوت داره، در مثال بالا همینطور که دیدید متد replaceAll در StringBuilder کاتلین وجود نداره و بجاش تابع replace در StringBuilder کاتلین به کار برده شده اما وجه مشترک هردو استفاده از Regular Expression برای جاگزینی کلمه ی rainy با sunny است.

خلاصه

- برای خوندن متن از فایل یا کسنول از کلاس Scanner استفاده میکنیم.

- کلاس اسکنر مناسب خوندن داده های متنی و Primitive از فایل یا کنسول است.

- از next برای خوندن کلمه ی فعلی متن تا جایی که اسپیس نباشه استفاده میکنیم و از nextLine برای خوندن خط فعلی متن.

- اگه جایی از متن عدد باشه علاوه بر next میتونیم از nextInt، nextDouble، nextLong و nextFloat برای خوندنش استفاده کنیم تفاوتشون تو نوعیه که بر میگردونن.

arrow_drop_up
کپی شد!