5/5 (2)

سلام خدمت شما دوستان و همراهان سایت اسمارت دولوپرز . تو این آموزش میخام شما رو با مفاهیم InputStream و OutputStream آشنا کنم و درک این دو مورد رو براتون راحت ترکنم .

آموزش InputStream و OutputStream و کپی کردن فایل

InputStream چیست ؟

ما در جاوا برای اینکه بتونیم از یک ورودی اطلاعات رو دریافت کنیم باید یک InpustStream از اون ورودی بگیریم . حالا ورودی ما میخاد یک فایل تکست یا عکس باشه یا یک Socket یا یک کانکشن اینترنت . InputStream زیر کلاس های زیادی داره مثل FileInputStream ، ObjectInputStream ، ByteInputStream و …  . که هرکدوم از اینها برای موارد خاصی استفاده میشن .

OutPutStream چیست ؟

برعکس InputStream که برای خوندن اطلاعات نیاز بود ما برای نوشتن اطلاعات به OutPutStream ها نیاز داریم . OutPutStream ها هم متناظر با هر InputStream یک زیر کلاس داره مثل FileOutPutStream  ،  ObjectOutPutStream و … .

چگونه اطلاعات را از InputStream بخوانیم ؟

کلاس های InputStream همشون متد های ()read برای خودند اطلاعات دارند و سه نوع متد read داریم .

اولیش که هیچ پارامتری دریافت نمیکنه به این صورته :

این متد ()read میاد دونه دونه بایت هارو از ورودی میخونه ! توجه کنید دونه دونه ! حالا فرض کنید شما یک فایل 50 مگابایتی دارید اینجا باید چند ساعت طول بکشه تا کل فایل رو بخونه !  اما خوشبختانه متد های بعدی ()read اینطوری نیستن .

نسخه بعدی متد ()read که یک پارامتر از جنس آرایه از byte ها میگیره :

اینجا این متد میاد به اندازه سایز آرایه buffer ینی به اندازه ()buffer.length  بایت از ورودی میخونه و توی آرایه buffer ذخیره میکنه . با این روش دیگه چون ما اومدیم مقدار آرایه رو 4Kb ساختیم به اندازه 4 کیلوبایت از ورودی به یکباره میخونه . این متد یک مقدار بازگشتی هم داره که مقدار بازگشتیش تعداد بایت هایی هست که از ورودی خونده .

فقط اینو در نظر داشته باشید که زیاد کردن سایز buffer ممکنه خوب نباشه . چون این اندازه بستگی به سخت افزار و بلاک های مموری و خیلی عوامل دیگه داره که در حال حاضر مناسب ترین عدد همین 4 کیلوبایته . البته ممکنه 16kb و یا 32kb هم گزینه مناسبی باشند .

خب آخرین نسخه متد ()read که سه تا پارامتر میگیره به این صورته :

اینجا متد read میاد مقدار length عدد بایت رو از ورودی میخونه و از مکان buffer[offset] شروع به نوشتن داخل آرایه buffer میکنه و در مقدار بازگشتی هم تعداد بایت های خونده شده رو برگشت میده . البته اگه به اندازه length بایت توی ورودی نداشته باشیم مسلما به همون اندازه بایتی که وجود داره میخونه که ممکنه کمتر از مقدار length باشه .

نکته : اما مقدار بازگشتی متد های ()read زمانی که به انتهای فایل رسیده باشیم مقدار1- برگشت میده .

چگونه اطلاعات را در OutputStream بنویسیم ؟

کلاس های OutputStream هم متد هایی برای نوشتن اطلاعات دارند که متناظر با متد های ()read کلاس های InputStream هست .

اولیش متد write ی هست که هیچ پارامتری نمیگیره و دونه دونه بایت هارو داخل خروجی رایت میکنه .

متد بعدی هم که یک پارامتر از جنس آرایه ای از byte ها دریافت میکنه .

این متد مقدار بایت های موجود داخل آرایه buffer رو توی خروجی رایت میکنه .

و متد بعدی هم به این صورته :

این متد به اندازه length تعداد بایت رو از مکان offset در آرایه buffer میخونه و توی خروجی رایت میکنه . یعنی چیزی که توی خروجی رایت میشه به این صورته :

این متد رو اگه به این صورت بنویسیم :

برابر این کده :

مثال عملی:

خب الان بیایم با چیزهایی که یاد گرفتیم یک فایل رو به عنوان ورودی بخونیم و توی یه فایل دیگه بنویسیمیش . ( عمل کپی کردن فایل ) .

برای اینکار اول باید یک InputStream از فایل بگیریم و تا زمانی که به انتهای فایل نرسیدیم به خوندن از اون فایل ادامه بدیم و هرچقدر که بایت از ورودی خوندیم رو توی خروجی هم رایت کنیم . برای کارکردن با فایل ها ما از FileInputStream و FileOutputStream استفاده میکنیم .

برای مثال فرض کنید میخایم فایلی با آدرس “/myFolder/file.txt/” رو توی پوشه دیگه ای کپی کنیم مثلا “/folder2/file.txt” .

خب به این صورت باید بنویسیم :

خیلی راحت و بدون هیچ سردرگمی باید متوجه شده باشید که چی شده . 

همونطور که گفتم باید تا زمانی که فایل به انتها نرسیده از فایل مقدار buffer.length بایت رو بخونیم و هرچقدر که خوندیم رو توی خروجی هم رایت کنیم . پس میایم از حلقه while استفاده میکنیم و توی شرطش هم مقدار بازگشتی متد ()read رو بررسی میکنیم که اگه تا زمانی که 1- نشده به خوندن ادامه بده و وقتی که به مقدار 1- رسیدیم ینی به آخر اون فایل رسیدیم و باید از حلقه خارج شیم . و در نهایت هم باید InputStream ها و OutputStream هارو close کنیم تا منابعی که اشغال کردیم رو رها کنیم تا بقیه هم بتونن از این این منابع استفاده کنند .

کپی کردن فایل ها در اندروید :

در اندروید هم روش کپی کردن به همین صورته ولی به دست اوردن InputStream و OutputStream ها فرق میکنه . 

اگه شما Uri مبدا و مقصد رو داشته باشید با استفاده از متد openInputStream و openOutputStream کلاس ContentResolver میتونید به ورودی و خروجی دسترسی داشته باشید و متونید از ورودی بخونید و توی خروجی رایت کنید

و اگه هم آدرس کامل فایل رو دارید که به روش FileInputStream و FileOutputStream میتونید عمل کپی کردن رو انجام بدید . . یا ترکیبی از اینها . مهم داشتن InputStream و OutputStream هست .

نکته : از اونجایی که کار با فایل ها  و InputStream ها و OutputStream ها عمل سنگینی هست و باعث بلاک شدن UI میشه باید این عملیات رو داخل Thread ی غیر از main Thread  انجام بدید .

خب امید وارم این آموزش براتون مفید واقع شده باشه . منتظر نظرات و پیشنهاداتون هستیم .

 

 

به این مطلب چه امتیازی میدهید ؟

اشتراک
باخبر شدن از
guest
2 Comments
Inline Feedbacks
نمایش همه دیدگاه ها
سارا

عالی بازم

نادر

ای ول یعنی Bravo. اشتباهه تو عشقه