ByteArrayOutputStream வகுப்பு ஒரு பைட் வரிசையில் தரவை எழுதும் வெளியீட்டு ஸ்ட்ரீமை செயல்படுத்துகிறது . தரவு எழுதப்பட்டவுடன் தாங்கல் தானாகவே வளரும்.

ByteArrayOutputStream வகுப்பு நினைவகத்தில் ஒரு இடையகத்தை உருவாக்குகிறது, மேலும் ஸ்ட்ரீமுக்கு அனுப்பப்பட்ட எல்லா தரவும் பஃப்பரில் சேமிக்கப்படும் .

ByteArrayOutputStream கன்ஸ்ட்ரக்டர்கள்

ByteArrayOutputStream வகுப்பு பின்வரும் கட்டமைப்பாளர்களைக் கொண்டுள்ளது :

கன்ஸ்ட்ரக்டர்
ByteArrayOutputStream() இந்த கன்ஸ்ட்ரக்டர் 32 பைட்டுகள் நீளமுள்ள நினைவக இடையகத்தை உருவாக்குகிறது.
ByteArrayOutputStream(int a) இந்த கன்ஸ்ட்ரக்டர் ஒரு குறிப்பிட்ட அளவுடன் நினைவகத்தில் உள்ள இடையகத்தை உருவாக்குகிறது.

வகுப்பு உள்ளே இருப்பது இதுதான்:


// The buffer itself, where the data is stored.
protected byte buf[];

// Current number of bytes written to the buffer.
protected int count;

public ByteArrayOutputStream() {
    this(32);
}

public ByteArrayOutputStream(int size) {
    if (size < 0) {
        throw new IllegalArgumentException("Negative initial size: "
                                           + size);
    }
    buf = new byte[size];
}
    

ByteArrayOutputStream வகுப்பின் முறைகள்

எங்கள் வகுப்பில் நாம் பயன்படுத்தக்கூடிய முறைகளைப் பற்றி பேசலாம்.

நம் ஸ்ட்ரீமில் ஏதாவது ஒன்றை வைக்க முயற்சிப்போம். இதைச் செய்ய, நாம் எழுதும் () முறையைப் பயன்படுத்துவோம் - இது எழுதுவதற்கு ஒரு பைட் அல்லது பைட்டுகளின் தொகுப்பை ஏற்கலாம்.

முறை
வெற்றிடமான எழுத்து (int b) ஒரு பைட் எழுதுகிறார்.
வெற்றிட எழுத்து (பைட் பி[], இன்ட் ஆஃப், இன்ட் லென்) ஒரு குறிப்பிட்ட அளவிலான பைட்டுகளின் வரிசையை எழுதுகிறது.
வெற்றிடமான எழுத்து பைட்டுகள்(பைட் b[]) பைட்டுகளின் வரிசையை எழுதுகிறது.
வெற்றிடத்தை எழுதுவதற்கு (அவுட்புட் ஸ்ட்ரீம் அவுட்) தற்போதைய வெளியீட்டு ஸ்ட்ரீமிலிருந்து அனுப்பப்பட்ட வெளியீட்டு ஸ்ட்ரீம் வரை அனைத்து தரவையும் எழுதுகிறது.

செயல்படுத்தும் முறை:


public static void main(String[] args) throws IOException {
   ByteArrayOutputStream outputByte = new ByteArrayOutputStream();
   // Write one byte
   while(outputByte.size()!= 7) {
      outputByte.write("codegym".getBytes());
   }

   // Write array of bytes
   String value = "\nWelcome to Java\n";
   byte[] arrBytes = value.getBytes();
   outputByte.write(arrBytes);

   // Write part of an array
   String codeGym = "CodeGym";
   byte[] b = codeGym.getBytes();
   outputByte.write(b, 4, 3);

   // Write to a file
   FileOutputStream fileOutputStream = new FileOutputStream("output.txt");
   outputByte.write(80);
   outputByte.writeTo(fileOutputStream);
}
    

இதன் விளைவாக ஒரு புதிய output.txt கோப்பு இது போல் தெரிகிறது:

toByteArray () முறையானது இந்த வெளியீட்டு ஸ்ட்ரீமின் தற்போதைய உள்ளடக்கங்களை பைட்டுகளின் வரிசையாக வழங்குகிறது. பஃப் பைட் வரிசையை உரையாகப் பெற, toString() முறையைப் பயன்படுத்தலாம் :


public static void main(String[] args) throws IOException {
    ByteArrayOutputStream outputByte = new ByteArrayOutputStream();

    String value = "CodeGym";
    outputByte.write(value.getBytes());

    byte[] result = outputByte.toByteArray();
    System.out.println("Result: ");

    for(int i = 0 ; i < result.length; i++) {
        // Display the characters
        System.out.print((char)result[i]);
    }
}
    

எங்கள் இடையகத்திற்கு நாம் அனுப்பிய பைட் வரிசை உள்ளது.

ரீசெட் () முறையானது பைட் வரிசை வெளியீட்டு ஸ்ட்ரீமில் உள்ள செல்லுபடியாகும் பைட்டுகளின் எண்ணிக்கையை பூஜ்ஜியத்திற்கு மீட்டமைக்கிறது (எனவே வெளியீட்டில் திரட்டப்பட்ட அனைத்தும் மீட்டமைக்கப்படும்).


public static void main(String[] args) throws IOException {
   ByteArrayOutputStream outputByte = new ByteArrayOutputStream(120);

   String value = "CodeGym";
   outputByte.write(value.getBytes());
   byte[] result = outputByte.toByteArray();
   System.out.println("Output before reset: ");

   for (byte b : result) {
      // Display the characters
      System.out.print((char) b);
   }

   outputByte.reset();

   byte[] resultAfterReset = outputByte.toByteArray();
   System.out.println("\nOutput after reset: ");

   for (byte b : resultAfterReset) {
      // Display the characters
      System.out.print((char) b);
   }
}
    

ரீசெட்() முறையை அழைத்த பிறகு நமது இடையகத்தைக் காண்பிக்கும் போது , ​​நமக்கு எதுவும் கிடைக்காது.

நெருக்கமான() முறையின் குறிப்பிட்ட அம்சங்கள்

இந்த முறை சிறப்பு கவனம் தேவை. அது என்ன செய்கிறது என்பதைப் புரிந்து கொள்ள, உள்ளே ஒரு கண்ணோட்டத்தை எடுத்துக் கொள்வோம்:


/**
 * Closing a {@code ByteArrayOutputStream} has no effect. The methods in
 * this class can be called after the stream has been closed without
 * generating an {@code IOException}.
 */
public void close() throws IOException {
}
    

ByteArrayOutputStream வகுப்பின் நெருக்கமான() முறை உண்மையில் எதையும் செய்யாது என்பதை நினைவில் கொள்ளவும் .

அது ஏன்? ஒரு ByteArrayOutputStream என்பது நினைவக அடிப்படையிலான ஸ்ட்ரீம் ஆகும் (அதாவது, இது பயனரால் நிர்வகிக்கப்பட்டு, குறியீட்டில் நிரப்பப்படுகிறது), எனவே Close() என அழைப்பது எந்த விளைவையும் ஏற்படுத்தாது.

பயிற்சி

இப்போது நமது ByteArrayOutputStream மற்றும் ByteArrayInputStream ஐப் பயன்படுத்தி ஒரு கோப்பு முறைமையை செயல்படுத்த முயற்சிப்போம் .

சிங்கிள்டன் வடிவமைப்பு வடிவத்தைப் பயன்படுத்தி ஒரு FileSystem வகுப்பை எழுதுவோம் மற்றும் நிலையான HashMap<String, byte[]> ஐப் பயன்படுத்துவோம் , எங்கே:

  • சரம் என்பது ஒரு கோப்பிற்கான பாதை
  • பைட்[] என்பது சேமித்த கோப்பில் உள்ள தரவு

import java.io.*;
import java.util.HashMap;
import java.util.Map;

class FileSystem {
   private static final FileSystem fileSystem = new FileSystem();
   private static final Map<String, byte[]> files = new HashMap<>();

   private FileSystem() {
   }

   public static FileSystem getFileSystem() {
       return fileSystem;
   }

   public void create(String path) {
       validateNotExists(path);
       files.put(path, new byte[0]);
   }

   public void delete(String path) {
       validateExists(path);
       files.remove(path);
   }

   public boolean isExists(String path) {
       return files.containsKey(path);
   }

   public InputStream newInputStream(String path) {
       validateExists(path);
       return new ByteArrayInputStream(files.get(path));
   }

   public OutputStream newOutputStream(String path) {
       validateExists(path);
       return new ByteArrayOutputStream() {
           @Override
           public void flush() throws IOException {
               final byte[] bytes = toByteArray();
               files.put(path, bytes);
               super.flush();
           }

           @Override
           public void close() throws IOException {
               final byte[] bytes = toByteArray();
               files.put(path, bytes);
               super.close();
           }
       };
   }

   private void validateExists(String path) {
       if (!files.containsKey(path)) {
           throw new RuntimeException("File not found");
       }
   }

   private void validateNotExists(String path) {
       if (files.containsKey(path)) {
           throw new RuntimeException("File exists");
       }
   }
}
    

இந்த வகுப்பில், பின்வரும் பொது முறைகளை உருவாக்கினோம்:

  • நிலையான CRUD முறைகள் (உருவாக்கு, படிக்க, புதுப்பிக்க, நீக்கு),
  • ஒரு கோப்பு இருக்கிறதா என்று சரிபார்க்க ஒரு முறை,
  • கோப்பு முறைமையின் உதாரணத்தைப் பெறுவதற்கான ஒரு முறை.

ஒரு கோப்பிலிருந்து படிக்க, ஒரு InputStream ஐ வழங்குகிறோம் . ஹூட்டின் கீழ் ByteArrayInputStream செயல்படுத்தல் உள்ளது. இடையகமானது கோப்புகள் வரைபடத்தில் சேமிக்கப்பட்ட பைட் வரிசையாகும் .

மற்றொரு சுவாரஸ்யமான முறை newOutputStream ஆகும் . இந்த முறை அழைக்கப்படும்போது, ​​இரண்டு முறைகளை மீறும் புதிய ByteArrayOutputStream ஆப்ஜெக்ட்டை நாங்கள் திருப்பித் தருகிறோம்: ஃப்ளஷ் மற்றும் மூடு . இந்த முறைகளில் ஏதேனும் ஒன்றை அழைப்பதன் மூலம் எழுதுதல் நடைபெற வேண்டும்.

அதைத்தான் நாங்கள் செய்கிறோம்: பயனர் எழுதிய பைட் வரிசையைப் பெறுகிறோம், மேலும் ஒரு நகலை சேமிக்கிறோம்மதிப்புபொருத்தமான விசையுடன் கோப்பு வரைபடத்தில் .

எங்கள் கோப்பு முறைமையை (FS) சோதிக்க பின்வரும் குறியீட்டைப் பயன்படுத்துகிறோம்:


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static java.nio.charset.StandardCharsets.UTF_8;

public class MyFileSystemTest {
   public static void main(String[] args) throws IOException {
       FileSystem fileSystem = FileSystem.getFileSystem();
       final String path = "/user/bin/data.txt";

       // Create a file
       fileSystem.create(path);
       System.out.println("File created successfully");

       // Make sure it's empty
       try (InputStream inputStream = fileSystem.newInputStream(path)) {
           System.out.print("File contents:\t");
           System.out.println(read(inputStream));
       }

       // Write data to it
       try (final OutputStream outputStream = fileSystem.newOutputStream(path)) {
           outputStream.write("CodeGym".getBytes(UTF_8));
           System.out.println("Data written to file");
       }

       // Read data
       try (InputStream inputStream = fileSystem.newInputStream(path)) {
           System.out.print("File contents:\t");
           System.out.println(read(inputStream));
       }

       // Delete the file
       fileSystem.delete(path);

       // Verify that the file does not exist in the FS
       System.out.print("File exists:\t");
       System.out.println(fileSystem.isExists(path));

   }

   private static String read(InputStream inputStream) throws IOException {
       return new String(inputStream.readAllBytes(), UTF_8);
   }
}
    

சோதனையின் போது, ​​பின்வரும் செயல்களை நாங்கள் சரிபார்க்கிறோம்:

  1. நாங்கள் ஒரு புதிய கோப்பை உருவாக்குகிறோம்.
  2. உருவாக்கப்பட்ட கோப்பு காலியாக உள்ளதா என்பதை நாங்கள் சரிபார்க்கிறோம்.
  3. கோப்பில் சில தரவை எழுதுகிறோம்.
  4. தரவை மீண்டும் படித்து, நாங்கள் எழுதியவற்றுடன் அது பொருந்துகிறதா என்று சரிபார்க்கிறோம்.
  5. நாங்கள் கோப்பை நீக்குகிறோம்.
  6. கோப்பு நீக்கப்பட்டதை நாங்கள் சரிபார்க்கிறோம்.

இந்தக் குறியீட்டை இயக்குவது நமக்கு இந்த வெளியீட்டை அளிக்கிறது:

கோப்பு வெற்றிகரமாக உருவாக்கப்பட்டது
கோப்பு உள்ளடக்கங்கள்:
கோப்பில் எழுதப்பட்ட தரவு
கோப்பு உள்ளடக்கங்கள்: CodeGym
கோப்பு உள்ளது: தவறு

இந்த உதாரணம் ஏன் தேவைப்பட்டது?

எளிமையாகச் சொன்னால், தரவு எப்போதும் பைட்டுகளின் தொகுப்பாகும். வட்டில் இருந்து/வட்டிற்கு நிறைய தரவுகளைப் படிக்க/எழுத வேண்டியிருந்தால், I/O பிரச்சனைகளால் உங்கள் குறியீடு மெதுவாக இயங்கும். இந்த வழக்கில், RAM இல் ஒரு மெய்நிகர் கோப்பு முறைமையை பராமரிப்பது அர்த்தமுள்ளதாக இருக்கிறது, நீங்கள் ஒரு பாரம்பரிய வட்டுடன் அதே வழியில் வேலை செய்கிறீர்கள். இன்புட்ஸ்ட்ரீம் மற்றும் அவுட்புட்ஸ்ட்ரீமை விட எளிமையானது எது ?

நிச்சயமாக, இது அறிவுறுத்தலுக்கு ஒரு எடுத்துக்காட்டு, உற்பத்திக்கு தயாராக உள்ள குறியீடு அல்ல. இது கணக்கில் இல்லை (பின்வரும் பட்டியல் விரிவானது அல்ல):

  • மல்டித்ரெடிங்
  • கோப்பு அளவு வரம்புகள் (இயங்கும் JVM க்கு கிடைக்கும் RAM அளவு)
  • பாதை கட்டமைப்பின் சரிபார்ப்பு
  • முறை வாதங்களின் சரிபார்ப்பு

சுவாரஸ்யமான உள் தகவல்:
CodeGym பணி சரிபார்ப்பு சேவையகம் ஓரளவு ஒத்த அணுகுமுறையைப் பயன்படுத்துகிறது. நாங்கள் ஒரு மெய்நிகர் எஃப்எஸ்ஸைச் சுழற்றுவோம், பணிச் சரிபார்ப்பிற்காக எந்தச் சோதனைகளை நடத்த வேண்டும் என்பதைத் தீர்மானித்து, சோதனைகளை இயக்கி, முடிவுகளைப் படிக்கிறோம்.

முடிவு மற்றும் பெரிய கேள்வி

இந்தப் பாடத்தைப் படித்த பிறகு பெரிய கேள்வி என்னவென்றால், "ஏன் பைட்டைப் பயன்படுத்த முடியாது [] , ஏனெனில் இது மிகவும் வசதியானது மற்றும் கட்டுப்பாடுகளை விதிக்காது?"

ByteArrayInputStream இன் நன்மை என்னவென்றால், நீங்கள் படிக்க-மட்டும் பைட்டுகளைப் பயன்படுத்தப் போகிறீர்கள் என்பதை இது வலுவாகக் குறிக்கிறது (ஏனெனில் ஸ்ட்ரீம் அதன் உள்ளடக்கத்தை மாற்றுவதற்கான இடைமுகத்தை வழங்காது). ஒரு புரோகிராமர் இன்னும் நேரடியாக பைட்டுகளை அணுக முடியும் என்பது குறிப்பிடத்தக்கது .

ஆனால் சில சமயங்களில் உங்களிடம் பைட்[] இருந்தால், சில சமயங்களில் உங்களிடம் கோப்பு இருந்தால், சில சமயங்களில் உங்களிடம் பிணைய இணைப்பு இருந்தால், "பைட்டுகளின் ஸ்ட்ரீம்" என்பதற்கு சில வகையான சுருக்கம் உங்களுக்குத் தேவைப்படும், மேலும் அவை எங்கே என்று எனக்கு கவலையில்லை. இருந்து வரும்". அதுதான் InputStream . மூலமானது ஒரு பைட் வரிசையாக இருக்கும் போது, ​​ByteArrayInputStream என்பது பயன்படுத்த ஒரு நல்ல InputStream ஆகும்.

இது பல சூழ்நிலைகளில் பயனுள்ளதாக இருக்கும், ஆனால் இங்கே இரண்டு குறிப்பிட்ட எடுத்துக்காட்டுகள் உள்ளன:

  1. நீங்கள் பைட்டுகளைப் பெற்று அவற்றை எப்படியாவது செயலாக்கும் நூலகத்தை எழுதுகிறீர்கள் (உதாரணமாக, இது பட செயலாக்கப் பயன்பாடுகளின் நூலகம் என்று வைத்துக்கொள்வோம்). உங்கள் நூலகத்தின் பயனர்கள் ஒரு கோப்பிலிருந்து, நினைவகத்தில் உள்ள பைட்டிலிருந்து [] , அல்லது வேறு ஏதேனும் மூலத்திலிருந்து பைட்டுகளை வழங்க முடியும். எனவே நீங்கள் InputStream ஐ ஏற்கும் ஒரு இடைமுகத்தை வழங்குகிறீர்கள் , அதாவது அவர்களிடம் பைட்[] இருந்தால், அவர்கள் அதை ByteArrayInputStream இல் மடிக்க வேண்டும் .

  2. நெட்வொர்க் இணைப்பைப் படிக்கும் குறியீட்டை எழுதுகிறீர்கள். ஆனால் இந்த குறியீட்டில் யூனிட் சோதனைகளைச் செய்ய, நீங்கள் இணைப்பைத் திறக்க விரும்பவில்லை - குறியீட்டிற்கு சில பைட்டுகளை வழங்க வேண்டும். எனவே குறியீடு ஒரு InputStream ஐ எடுக்கும் மற்றும் உங்கள் சோதனை ஒரு ByteArrayInputStream இல் கடந்து செல்கிறது .