CodeGym /مدونة جافا /Random-AR /الإدخال / الإخراج في جافا. فئات FileInputStream وFileOutp...
John Squirrels
مستوى
San Francisco

الإدخال / الإخراج في جافا. فئات FileInputStream وFileOutputStream وBufferedInputStream

نشرت في المجموعة
"مرحبًا! في درس اليوم، سنواصل حديثنا حول تدفقات الإدخال والإخراج في Java ( Java I/O ). هذا ليس الدرس الأول حول هذا الموضوع، وبالتأكيد لن يكون الأخير :) الإدخال / الإخراج في جافا.  فئات FileInputStream وFileOutputStream وBufferedInputStream - 1لأنه في بعض الأحيان، توفر لغة Java العديد من الطرق للعمل مع الإدخال/الإخراج. هناك عدد لا بأس به من الفئات التي تنفذ هذه الوظيفة، لذلك قمنا بتقسيمها إلى عدة دروس - لذلك لن تشعر بالارتباك من البداية :) في الماضي الدروس التي تطرقنا إليها BufferedReaderبالإضافة إلى InputStreamالفئات OutputStreamالمجردة والعديد من الفروع اليوم سننظر في 3 فئات جديدة: FileInputStreamو  FileOutputStreamو و  BufferedInputStream.

فئة FileOutputStream

الغرض الرئيسي من FileOutputStreamالفصل هو كتابة البايتات إلى ملف. لا شيء معقد :) FileOutputStreamهو أحد تطبيقات الفئة OutputStreamالمجردة. في المنشئ، تأخذ كائنات هذه الفئة إما المسار إلى الملف الهدف (حيث يجب كتابة البايتات) أو كائنًا File. وسنقوم بدراسة أمثلة لكل منها:
public class Main {

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

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt");
       FileOutputStream fileOutputStream = new FileOutputStream(file);

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
عند إنشاء Fileالكائن، قمنا بتمرير المسار المطلوب إلى المنشئ. لا نحتاج إلى إنشائه مسبقًا: إذا لم يكن موجودًا، فسيقوم البرنامج بإنشائه. يمكنك أيضًا المضي قدمًا دون إنشاء كائن إضافي، فقط قم بتمرير سلسلة مع المسار:
public class Main {

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

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt");
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
والنتيجة في كلتا الحالتين ستكون هي نفسها. يمكننا فتح ملفنا ورؤية ما يلي هناك:

Hi! Welcome to CodeGym — The best site for would-be programmers!
ولكن هناك فارق بسيط هنا. حاول تشغيل الكود من المثال أعلاه عدة مرات متتالية. ثم ابحث في الملف وأجب عن هذا السؤال: كم عدد الأسطر فيه؟ واحد فقط. لكنك قمت بتشغيل الكود عدة مرات. اتضح أنه تتم الكتابة فوق البيانات في كل مرة، حيث يتم استبدال البيانات القديمة بالجديدة. ماذا نفعل إذا كان ذلك لا يناسبنا ونحتاج إلى الكتابة بالتسلسل إلى الملف؟ ماذا لو أردنا أن نكتب تحيتنا إلى ملف ثلاث مرات متتالية؟ كل شيء بسيط جدا. نظرًا لأن اللغة لا يمكنها معرفة السلوك الذي نحتاجه في كل حالة، FileOutputStreamفيمكن للمنشئ أن يأخذ معلمة إضافية - boolean append. إذا كانت قيمته صحيحة، سيتم كتابة البيانات في نهاية الملف. إذا كانت خاطئة (وهي خاطئة افتراضيًا)، فسيتم مسح أي بيانات قديمة واستبدالها ببيانات جديدة. دعونا نتحقق من ذلك عن طريق تشغيل الكود المعدل ثلاث مرات:
public class Main {

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

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true);
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n";

       fileOutputStream.write(greetings.getBytes());
       fileOutputStream.close();
   }
}
محتويات الملف:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
الآن هذا مختلف! لا تنس هذه الميزة عند استخدام فئات الإدخال/الإخراج. كان هناك وقت قضيت فيه ساعات في أداء المهام، وأجهد عقلي لساعات، محاولًا فهم كيفية اختفاء بياناتي من الملفات :) وبالطبع، تمامًا كما هو الحال مع فئات الإدخال/الإخراج الأخرى، لا تنس استخدام هذه close()الطريقة لتحرير الموارد.

فئة FileInputStream

الغرض المعاكس هو FileInputStreamقراءة البايتات من الملف. تمامًا كما FileOutputStreamيرث OutputStream، فإن هذه الفئة مشتقة من InputStreamالفئة المجردة. سنكتب بضعة أسطر من النص في ملف " test.txt ":

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
الإدخال / الإخراج في جافا.  فئات FileInputStream وFileOutputStream وBufferedInputStream - 2هنا كيف تبدو قراءة البيانات من ملف باستخدام FileInputStream:
public class Main {

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

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       int i;

       while((i=fileInputStream.read())!= -1){

           System.out.print((char)i);

       }
   }
}
نقرأ بايتًا واحدًا من الملف، ونحول بايتات القراءة إلى أحرف ونعرضها على وحدة التحكم. وهنا إخراج وحدة التحكم:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

فئة BufferedInputStream

أعتقد، نظرًا للمعرفة المستفادة من الدروس السابقة، يمكنك بسهولة تحديد سبب حاجتنا إلى الفصل BufferedInputStreamوما هي المزايا التي يتمتع بها مقارنةً به FileInputStream:) لقد واجهنا بالفعل تدفقات مخزنة، لذا حاول التخمين (أو التذكر) قبل مواصلة القراءة :) هناك حاجة إلى التدفقات المخزنة بشكل أساسي لتحسين الإدخال/الإخراج. يعد الوصول إلى مصدر بيانات، مثل القراءة من ملف، عملية مكلفة من حيث الأداء، كما أن الوصول إلى ملف لقراءة كل بايت يعد إهدارًا. ولهذا السبب BufferedInputStreamلا يقرأ البيانات بايتًا واحدًا في المرة الواحدة، بل يقرأها على شكل كتل، ويخزنها مؤقتًا في مخزن مؤقت خاص. يتيح لنا ذلك تحسين البرنامج عن طريق تقليل عدد مرات الوصول إلى الملف. دعونا نرى كيف يبدو هذا:
public class Main {

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

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200);

       int i;

       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }
   }
}
هنا قمنا بإنشاء BufferedInputStreamكائن. يأخذ منشئه مثيلًا للفئة InputStreamأو أي من أحفادها، FileInputStreamوسيفعل ذلك أيضًا. كوسيطة إضافية، فإنه يأخذ حجم المخزن المؤقت بالبايت. بفضل هذه الوسيطة، سيتم الآن قراءة البيانات من الملف ليس بايت واحد في كل مرة، ولكن 200 بايت في المرة الواحدة! تخيل كم قمنا بتقليل عدد مرات الوصول إلى الملفات. لمقارنة الأداء، يمكنك أخذ ملف نصي كبير (عدة ميغابايت من النص) ومقارنة المدة التي تستغرقها القراءة والإخراج إلى وحدة التحكم بالمللي ثانية باستخدام FileInputStreamو BufferedInputStream. إليك الكود الذي يوضح كلا الخيارين:
public class Main {

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

       Date date = new Date();

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf");
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

       int i;
       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }

       Date date1 = new Date();
       System.out.println((date1.getTime() - date.getTime()));
   }
}


public class Main {

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

       Date date = new Date();
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf");

       int i;
       while((i = fileInputStream.read())!= -1){

           System.out.print((char)i);
       }


       Date date1 = new Date();
       System.out.println((date1.getTime() - date.getTime()));
   }
}
عند قراءة ملف بحجم 1.5 ميغابايت على جهاز الكمبيوتر الخاص بي، FileInputStreamأكملت العمل في حوالي 3500 مللي ثانية، ولكن BufferedInputStreamتمكنت من إدارته في حوالي 1700 مللي ثانية. كما ترون، قام الدفق المخزن بتحسين العمل، حيث قام بتقسيمه إلى نصفين! :) سنواصل دراسة فصول I/O - نراكم قريبًا!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION