عبارت I/O در «Java I/O» مخفف Input/Output یا ورودی/خروجی است. رابط برنامهنویسی Java I/O تمام ابزارهایی را که برنامهی شما برای دسترسی به اطلاعات خارجی نیاز دارد، فراهم میکند. در اینجا «خارج» به دو بخش اشاره دارد: دیسکها — یا بهطور کلیتر، سیستمفایلها (سیستمفایلها همیشه دیسک را مدل نمیکنند؛ مثلاً ممکن است در حافظه قرار داشته باشند) — و شبکه. نکتهی جالب این است که با Java I/O و افزونههای آن میتوانید به بخش سومی هم دسترسی پیدا کنید: حافظهی خارج از پشته (off-heap).
با استفاده از رابط Java I/O میتوانید فایلها را بخوانید و بنویسید و همچنین از طریق پروتکلهای مختلف داده را در شبکه ارسال و دریافت کنید. رابطهایی که دسترسی به پایگاهداده را فراهم میکنند (مانند Java Database Connectivity یا JDBC) نیز از Java I/O برای اتصال از طریق TCP/IP استفاده میکنند. بسیاری از رابطهای شناختهشده بر پایهی Java I/O ساخته شدهاند.
رابط برنامهنویسی Java I/O در اواسط دههی ۱۹۹۰ همراه با نخستین نسخههای JDK معرفی شد.
در سال ۲۰۰۲ و با انتشار Java SE 1.4، Java NIO با کلاسها، مفاهیم و امکانات جدیدی ارائه شد. در ابتدا NIO مخفف New Input/Output یا ورودی/خروجی جدید بود. اما چیزی که در زمانی «جدید» است، با گذشت زمان دیگر جدید به نظر نمیرسد. به همین دلیل امروزه NIO را بهعنوان Non-blocking Input/Output یا ورودی/خروجی غیرbloککننده میشناسند؛ اصطلاحی که ویژگی اصلی این افزونه را بهخوبی خلاصه میکند. انتشار Java NIO تغییر اساسی در نحوهی استفادهی برنامهها از Java I/O ایجاد نکرد. ممکن است بخواهید بخشی از کدهای I/O خود را با استفاده از بهبودهای Java NIO بازنویسی کنید، اما الگوهای Java I/O همچنان یکسان باقی میمانند.
در سال ۲۰۱۱ و با انتشار Java SE 7، Java NIO2 با کلاسها و مفاهیم بیشتری منتشر شد. Java NIO2 الگوهای جدیدی برای Java I/O به ارمغان آورد. برخی از کلاسهای Java NIO2 در Java SE 8 بهروزرسانی شدند و الگوهای بیشتری به Java I/O اضافه کردند.
این آموزش Java I/O سه بخش API را پوشش میدهد: Java I/O، Java NIO و Java NIO2.
دو مفهوم اصلی در Java I/O وجود دارد: مکانیابی منبعی که میخواهید به آن دسترسی داشته باشید (چه یک فایل باشد و چه یک منبع شبکهای)، و باز کردن یک Stream برای آن منبع. در بخشهای بعدی خواهید دید که چگونه از طریق سیستمفایل به فایلها دسترسی پیدا کنید و ساختار رابط Java I/O در ارتباط با Streamها چگونه است.
دو روش برای دسترسی به فایلها در Java I/O وجود دارد: روش اول از کلاس File و روش دوم از رابط Path استفاده میکند.
کلاس File در Java SE 1.0 معرفی شد و روش قدیمی دسترسی به فایلها را نمایش میدهد. این کلاس را میتوان یک بستهبندی روی یک رشتهی کاراکتری دانست که مسیری در سیستمفایل پیشفرض را نشان میدهد. مسیر میتواند مطلق یا نسبی باشد و میتواند یک فایل عادی یا یک دایرکتوری را نمایش دهد. میتوانید بررسی کنید که آیا فایل وجود دارد، آیا قابل خواندن یا تغییر است. همچنین میتوانید روی فایل عملیات انجام دهید: ایجاد، کپی یا بررسی محتوا.
از Java SE 7 به بعد، رابط Path بهعنوان بخشی از API مربوط به Java NIO2 معرفی شد. هدف این رابط رفع نقایص متعدد کلاس File است:
File هنگام خطا Exception تولید نمیکنند و دریافت پیام خطای مفید را غیرممکن میسازند. بهعنوان مثال، اگر file.delete() را فراخوانی کنید و حذف انجام نشود، برنامه فقط مقدار false برمیگرداند. اما نمیتوانید بدانید آیا فایل وجود ندارد، کاربر دسترسی ندارد، یا مشکل دیگری پیش آمده است.File مقیاسپذیر نیستند. درخواست فهرست بزرگی از یک دایرکتوری از طریق سرور میتواند باعث هنگ شود. دایرکتوریهای بزرگ همچنین میتوانند مشکلات منابع حافظه ایجاد کنند و بهطور بالقوه باعث Denial of Service شوند.تمام این مشکلات توسط رابط Path حل شدهاند. به همین دلیل استفاده از کلاس File دیگر توصیه نمیشود.
این آموزش بخشی دربارهی نحوهی Refactor کردن کدهای قدیمی File به استفاده از رابط Path دارد.
یک I/O Stream یک منبع ورودی یا مقصد خروجی را نمایش میدهد. Stream میتواند انواع مختلفی از منابع و مقاصد را نمایش دهد، از جمله فایلهای دیسک، دستگاهها، برنامههای دیگر و آرایههای حافظه.
Streamها از انواع مختلفی از داده پشتیبانی میکنند، از جمله بایتهای ساده، انواع دادهی اولیه (Primitive)، کاراکترهای بومیسازیشده و اشیاء. برخی Streamها صرفاً داده را منتقل میکنند؛ برخی دیگر داده را به شکلهای مفید پردازش و تبدیل میکنند.
صرفنظر از نحوهی عملکرد داخلی، تمام Streamها مدل سادهی واحدی را به برنامهها ارائه میدهند: یک Stream یک توالی از داده است. برنامه از یک InputStream برای خواندن داده از یک منبع (یک آیتم در هر لحظه) و از یک OutputStream برای نوشتن داده در یک مقصد (یک آیتم در هر لحظه) استفاده میکند.
منبع و مقصد داده میتواند هر چیزی باشد که داده را ذخیره، تولید یا مصرف کند. واضح است که این شامل فایلهای دیسک میشود، اما منبع یا مقصد میتواند یک برنامهی دیگر، یک دستگاه جانبی، یک سوکت شبکه یا یک آرایه باشد.
نکته: Streamهای I/O مفهومی متفاوت از Streamهای مربوط به Stream API هستند که در Java SE 8 معرفی شد. حتی اگر نام یکسانی دارند — که ممکن است باعث ابهام شود — مفاهیم متفاوتی دارند.
رابط Java I/O دو نوع محتوا را برای یک منبع تعریف میکند:
همچنین دو عملیات روی این محتوا تعریف میکند: خواندن و نوشتن.
بر اساس این تقسیمبندی، رابط Java I/O چهار کلاس پایهی انتزاعی تعریف میکند که هر کدام نوع خاصی از Stream و عملیات مرتبط را مدلسازی میکنند.
| Reading (خواندن) | Writing (نوشتن) | |
|---|---|---|
| Streams of Character (جریان کاراکتری) | Reader | Writer |
| Streams of Byte (جریان باینری) | InputStream | OutputStream |
تمام Streamهای باینری از InputStream و OutputStream مشتق شدهاند و تعداد زیادی از آنها وجود دارد. برخی از آنها در این آموزش پوشش داده شدهاند.
تمام کلاسهای Stream کاراکتری از Reader و Writer مشتق شدهاند.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/