জাভাতে ইনপুটস্ট্রিমটি বাইট অ্যারেতে রূপান্তর করুন


উত্তর:


1134

আপনি এটি এবং অনুরূপ কাজগুলি পরিচালনা করতে অ্যাপাচি কমন্স আইও ব্যবহার করতে পারেন ।

IOUtilsটাইপ একটি পড়তে একটি স্ট্যাটিক পন্থা নেই InputStreamএবং একটি ফিরতি byte[]

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

অভ্যন্তরীণভাবে এটি একটি তৈরি করে ByteArrayOutputStreamএবং আউটপুটে বাইটগুলি অনুলিপি করে, তারপরে কল করে toByteArray()। এটি 4KiB- এর ব্লকগুলিতে বাইটগুলি অনুলিপি করে বড় ফাইলগুলি পরিচালনা করে।


188
4 টি লাইনের কোড লেখার ইচ্ছেটির জন্য, আপনি কি মনে করেন যে কোনও তৃতীয় পক্ষের নির্ভরতা আমদানি করা সার্থক?
অক্সবো_লাক্স

217
যদি এমন কোনও লাইব্রেরি থাকে যা প্রয়োজনীয়তা পরিচালনা করে এবং বড় ফাইলগুলির প্রসেসিংয়ের বিষয়ে ডিল করে, এবং ভালভাবে পরীক্ষা করে দেখা হয় তবে অবশ্যই প্রশ্নটি হয় কেন আমি এটি নিজে লিখব? জারটি কেবল 107 কেবি এবং আপনার যদি এটি থেকে কোনও পদ্ধতির প্রয়োজন হয় তবে আপনি অন্যদেরও সম্ভবত ব্যবহার করতে পারেন
রিচ সেলার

242
@ অক্সবো_লাক্স: আমি আমার বিকাশকারী জীবনে এই বৈশিষ্ট্যটির ভুল বাস্তবায়নের বিস্ময়কর পরিমাণ বিবেচনা করে আমার মনে হয়েছে যে হ্যাঁ এটি সঠিকভাবে অর্জন করা বাহ্যিক নির্ভরতার পক্ষে খুব মূল্যবান।
জোছিম সউর

17
কেন যাবেন না এবং অ্যাপাচি কমন্স স্টাফের মতো FastArrayListবা তাদের নরম ও দুর্বল রেফারেন্স মানচিত্রগুলি দেখুন এবং এই লাইব্রেরিটি কতটা "ভাল-পরীক্ষিত" তা আমাকে ফিরে আসতে বলুন। এটা তোলে আবর্জনা একটি গাদা এর
oxbow_lakes

87
অ্যাপাচি কমন্স-আইও ছাড়াও গুগল পেয়ারা থেকে বাইটস্ট্রিম ক্লাস পরীক্ষা করে দেখুন । InputStream is; byte[] filedata=ByteStreams.toByteArray(is);
মাইকেলেলোক

446

আপনার নিজের থেকে প্রতিটি বাইট পড়তে হবে InputStreamএবং এটিতে এটি লিখতে হবে ByteArrayOutputStream

তারপরে আপনি কল করে অন্তর্নিহিত বাইট অ্যারে পুনরুদ্ধার করতে পারেন toByteArray():

InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] data = new byte[16384];

while ((nRead = is.read(data, 0, data.length)) != -1) {
  buffer.write(data, 0, nRead);
}

return buffer.toByteArray();

16
সদ্য নির্মিত বাইটের আকার সম্পর্কে কী []। কেন এটি 16384? আমি সঠিক সঠিক আকারটি কীভাবে নির্ধারণ করতে পারি? আপনাকে অনেক ধন্যবাদ.
ওন্দ্রেজ বোজেক

6
16384 হ'ল মোটামুটি স্বেচ্ছাচারী পছন্দ যদিও আমি শব্দের সীমানার সাথে অ্যারে প্রান্তিকরণের সম্ভাবনা বাড়ানোর জন্য 2 এর শক্তির পক্ষে থাকি। পাইহেন্টগির উত্তরটি দেখায় যে আপনি কীভাবে একটি মধ্যবর্তী বাফার ব্যবহার এড়াতে পারবেন, বরং সঠিক আকারের একটি অ্যারে বরাদ্দ করুন। আপনি যদি বড় ফাইলগুলির সাথে ডিল না করেন তবে আমি ব্যক্তিগতভাবে উপরের কোডটি পছন্দ করি, যা আরও মার্জিত এবং ইনপুট স্ট্রিমের জন্য ব্যবহার করা যেতে পারে যেখানে পড়ার জন্য বাইটের সংখ্যা আগে থেকে জানা যায় না।
অ্যাডামস্কি

@ অ্যাডামস্কি বাইটের অ্যারে তৈরি করছেন না যা আপনি আশা করছেন যে ডেটা প্রবাহে থাকবে, স্মৃতিটি নষ্ট করবে?
পল ব্রিউকজিনস্কি

@ ব্লুজেম: হ্যাঁ এটি সঠিক। যাইহোক, আমার উদাহরণে বাইট অ্যারেটি কেবলমাত্র 16 কেবি এবং আজকের মান অনুসারে এত ক্ষুদ্র। এছাড়াও, অবশ্যই এই স্মৃতিটি পরে আবার মুক্ত হবে।
অ্যাডামস্কি

5
@ অ্যাডামস্কি প্রচুর অবকাঠামো হার্ডওয়্যার, ওয়েব-সার্ভার এবং ওএস-লেয়ার উপাদানগুলি ডেটা স্থানান্তর করতে 4K বাফার ব্যবহার করছে, সুতরাং এটি সঠিক সংখ্যার কারণ, তবে মূল বিষয়টি হল 4K এর উপরে গিয়ে আপনি এত কম পারফরম্যান্স বৃদ্ধি পাচ্ছেন এটি সাধারণত স্মৃতির অপব্যয় হিসাবে বিবেচিত হয়। আমি ধরে নিচ্ছি এটি এখনও সত্য, কারণ এটি আমার দশক পুরানো জ্ঞান ছিল!

312

অবশেষে, বিশ বছর পরে, তৃতীয় পক্ষের লাইব্রেরির প্রয়োজন ছাড়াই একটি সহজ সমাধান রয়েছে, জাভা 9 এর জন্য ধন্যবাদ :

InputStream is;

byte[] array = is.readAllBytes();

সুবিধাগুলি readNBytes(byte[] b, int off, int len)এবং transferTo(OutputStream)পুনরাবৃত্তির প্রয়োজনগুলির সমাধানের জন্যও নোট করুন ।


132

ভ্যানিলা জাভা DataInputStreamএবং এর readFullyপদ্ধতিটি ব্যবহার করুন (কমপক্ষে জাভা 1.4 সাল থেকে বিদ্যমান):

...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...

এই পদ্ধতির আরও কিছু স্বাদ রয়েছে তবে আমি এই ব্যবহারের ক্ষেত্রে এটি সর্বদা ব্যবহার করি।


45
তৃতীয় পক্ষের নির্ভরতার পরিবর্তে স্ট্যান্ডার্ড লাইব্রেরি ব্যবহারের জন্য +1। দুর্ভাগ্যক্রমে এটি আমার পক্ষে কার্যকর হয় না কারণ আমি প্রবাহের সম্মুখ দৈর্ঘ্য জানি না।
অ্যান্ড্রু স্পেন্সার

2
imgFile কি? এটি কোনও ইনপুটস্ট্রিম হতে পারে না, যা এই পদ্ধতির ইনপুট হওয়ার কথা ছিল
জানুস ট্রয়লসেন

4
@ জানুস এটি একটি "ফাইল"। আপনি যদি ফাইলটির দৈর্ঘ্য বা পড়ার জন্য বাইটের গণনা জানেন তবেই এইভাবে কাজ করে।
dermoritz

5
আকর্ষণীয় বিষয়, তবে আপনাকে অবশ্যই পড়ার (প্রবাহের অংশ) প্রবাহের সঠিক দৈর্ঘ্য জানতে হবে। অধিকন্তু, ক্লাসটি DataInputStreamপ্রাথমিক স্ট্রিম থেকে প্রাথমিক ধরণের (লংস, শর্টস, চরস ...) পড়তে প্রাথমিকভাবে ব্যবহৃত হয়, তাই আমরা এই ব্যবহারটিকে শ্রেণীর অপব্যবহার হিসাবে দেখতে পারি।
অলিভিয়ার ফাউচাক্স

17
আপনি যদি স্ট্রিম থেকে পড়ার জন্য ডেটার দৈর্ঘ্যটি ইতিমধ্যে জানেন তবে এটি এর চেয়ে ভাল আর নয় InputStream.read
লোগান পিকআপ


46

সর্বদা হিসাবে, এছাড়াও স্প্রিং ফ্রেমওয়ার্ক (3.2.2 থেকে বসন্ত-কোর) আপনার জন্য কিছু রয়েছে:StreamUtils.copyToByteArray()


অন্য অনেকের মতো, আমি খুব সহজ কোনও কিছুর জন্য তৃতীয় পক্ষের গ্রন্থাগারটি এড়াতে চেয়েছিলাম, তবে জাভা 9 এই মুহুর্তে কোনও বিকল্প নয় ... ভাগ্যক্রমে, আমি ইতিমধ্যে স্প্রিং ব্যবহার করছিলাম।
স্কটিসিস 21

42
public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[0xFFFF];
    for (int len = is.read(buffer); len != -1; len = is.read(buffer)) { 
        os.write(buffer, 0, len);
    }
    return os.toByteArray();
}

2
এটি একটি উদাহরণ এবং যেমন, ব্রিভিটি হ'ল দিনের ক্রম। এছাড়াও এখানে নাল ফিরিয়ে দেওয়া কিছু ক্ষেত্রে উপযুক্ত পছন্দ হবে (যদিও উত্পাদন পরিবেশে আপনার যথাযথ ব্যতিক্রম পরিচালনা ও ডকুমেন্টেশনও থাকতে পারে)।

11
আমি একটি উদাহরণে ব্রেভিটি বুঝতে পারি, তবে কেন কেবল উদাহরণ পদ্ধতিটি গিলে ফেলা এবং অর্থহীন মান ফেরানোর চেয়ে আইওএক্সেপশন নিক্ষেপ করবেন না?
দুল

4
আমি 'রিটার্ন নাল' থেকে 'থ্রো আইওএক্সেপশন'-তে পরিবর্তন করার স্বাধীনতা নিয়েছি
ক্রিটজিক্রতজি

3
রিসোর্স-এর সাথে এখানে চেষ্টা করার দরকার নেই, কারণ বাইটআর্যআউটপুট স্ট্রিম # ক্লোজ () কিছুই করে না। (বাইটআরআউটআউটপুট স্ট্রিম # ফ্লাশ () প্রয়োজন হয় না এবং খুব বেশি কিছু করে না))
লুক হাচিসন

25

নিরাপদ সমাধান (closeপ্রবাহেরদক্ষতার সাথেসঠিকভাবে):

  • জাভা 9+ সংস্করণ:

    final byte[] bytes;
    try (inputStream) {
        bytes = inputStream.readAllBytes();
    }
  • জাভা 8 সংস্করণ:

    public static byte[] readAllBytes(InputStream inputStream) throws IOException {
        final int bufLen = 4 * 0x400; // 4KB
        byte[] buf = new byte[bufLen];
        int readLen;
        IOException exception = null;
    
        try {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
                    outputStream.write(buf, 0, readLen);
    
                return outputStream.toByteArray();
            }
        } catch (IOException e) {
            exception = e;
            throw e;
        } finally {
            if (exception == null) inputStream.close();
            else try {
                inputStream.close();
            } catch (IOException e) {
                exception.addSuppressed(e);
            }
        }
    }
  • কোটলিন সংস্করণ (যখন জাভা 9+ অ্যাক্সেসযোগ্য নয়):

    @Throws(IOException::class)
    fun InputStream.readAllBytes(): ByteArray {
        val bufLen = 4 * 0x400 // 4KB
        val buf = ByteArray(bufLen)
        var readLen: Int = 0
    
        ByteArrayOutputStream().use { o ->
            this.use { i ->
                while (i.read(buf, 0, bufLen).also { readLen = it } != -1)
                    o.write(buf, 0, readLen)
            }
    
            return o.toByteArray()
        }
    }

    নেস্টেড এড়ানোর useজন্য এখানে দেখুন


আপনি বাফার এবং বাইট অ্যারে উভয়ই ব্যবহার করেছেন বলে এর অর্থ কি না? আউটপুট বাইট অ্যারেতে বাইটগুলি প্রেরণের কোনও উপায় নেই?
অ্যান্ড্রয়েড বিকাশকারী

@androiddeveloper; আমি দুঃখিত. আমি উত্তর জানি না! তবে আমি তা মনে করি না। আমি মনে করি এইভাবে (বাফার ব্যবহার করে) একটি অনুকূলিত উপায়।
মীর-ইসমাইলি

আমি যাচাই করেছি এবং এটি করে ফেলেছি, তবে মনে হয় যে আকারটি জানেন না তখনই আপনি এটি চয়ন করতে পারেন কেবলমাত্র সমাধান। আপনি যদি ইতিমধ্যে আকারটি জানেন তবে আপনি প্রদত্ত আকারের সাথে সরাসরি বাইট-অ্যারে তৈরি করতে এবং পূরণ করতে পারেন। সুতরাং, আপনি এমন একটি ফাংশন ব্যবহার করেন যা বাইট আকারের একটি প্যারামিটার পাবে এবং যদি এটি বৈধ হয় তবে এটি অন্য কোনও বড় অবজেক্ট তৈরি না করে সরাসরি বাইট অ্যারে তৈরি এবং পূরণ করতে ব্যবহার করুন।
অ্যান্ড্রয়েড বিকাশকারী

@androiddeveloper; আপনার তথ্যের জন্য ধন্যবাদ. আমি তাদের চিনতাম না।
মীর-ইসমাইলি

19

আপনার কি সত্যই চিত্রটির প্রয়োজন byte[]? আপনি ঠিক কীটি আশা করতে পারেন byte[]- কোনও চিত্র ফাইলের সম্পূর্ণ সামগ্রী, ইমেজ ফাইলটি যে কোনও ফর্ম্যাটে এনকোডযুক্ত রয়েছে, বা আরজিবি পিক্সেল মান?

এখানে অন্যান্য উত্তরগুলি আপনাকে কীভাবে একটিতে ফাইল পড়তে হবে তা দেখায় byte[]। আপনার byte[]ফাইলটির সঠিক বিষয়বস্তু থাকবে এবং আপনাকে চিত্রের ডেটা দিয়ে কিছু করতে ডিকোড করতে হবে।

চিত্রগুলি পড়ার (এবং লেখার) জন্য জাভার স্ট্যান্ডার্ড এপিআই হ'ল ইমেজআইও এপিআই, যা আপনি প্যাকেজে খুঁজে পেতে পারেন javax.imageio। আপনি কেবলমাত্র একটি একক লাইন কোডের একটি ফাইল থেকে একটি ছবিতে পড়তে পারেন:

BufferedImage image = ImageIO.read(new File("image.jpg"));

এটি আপনাকে একটি দেবে BufferedImage, একটি নয় byte[]। ইমেজ তথ্য এ পেতে, আপনি কল করতে পারেন getRaster()উপর BufferedImage। এটি আপনাকে একটি Rasterঅবজেক্ট দেবে, যার পিক্সেল ডেটা অ্যাক্সেস করার পদ্ধতি রয়েছে (এতে বেশ কয়েকটি getPixel()/getPixels() পদ্ধতি রয়েছে)।

এপিআই ডকুমেন্টেশন লুকআপ জন্য javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Rasterইত্যাদি

ইমেজআইও ডিফল্টরূপে বেশ কয়েকটি চিত্রের ফর্ম্যাটকে সমর্থন করে: জেপিইজি, পিএনজি, বিএমপি, ডাব্লুবিএমপি এবং জিআইএফ। আরও ফর্ম্যাটগুলির জন্য সমর্থন যুক্ত করা সম্ভব (আপনার একটি প্লাগ-ইন দরকার যা চিত্রের পরিষেবা পরিষেবা সরবরাহকারী ইন্টারফেসটি প্রয়োগ করে)।

নিম্নলিখিত টিউটোরিয়ালটি দেখুন: চিত্রগুলির সাথে কাজ করা


16

সেক্ষেত্রে কেউ এখনও নির্ভরতা ছাড়াই সমাধান খুঁজছেন এবং যদি আপনার কাছে ফাইল থাকে

1) ডেটা ইনপুট স্ট্রিম

 byte[] data = new byte[(int) file.length()];
 DataInputStream dis = new DataInputStream(new FileInputStream(file));
 dis.readFully(data);
 dis.close();

2) বাইটআর্যআউটপুট স্ট্রিম

 InputStream is = new FileInputStream(file);
 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 int nRead;
 byte[] data = new byte[(int) file.length()];
 while ((nRead = is.read(data, 0, data.length)) != -1) {
     buffer.write(data, 0, nRead);
 }

3) র্যান্ডমএকসেসফাইল

 RandomAccessFile raf = new RandomAccessFile(file, "r");
 byte[] data = new byte[(int) raf.length()];
 raf.readFully(data);

বলুন, বাইট অ্যারেটি যদি খুব বড় হয় যা গাদা জন্য OOM এর কারণ হতে পারে? এমন কোনও সমাধান আছে যা জেএনআই ব্যবহার করে বাইটগুলি সঞ্চয় করতে পারে এবং পরে আমরা সেখানে সঞ্চিত ডেটা (সাময়িক ক্যাশে বাছাই করা) থেকে ইনপুটস্ট্রিম ব্যবহার করতে সক্ষম হব?
অ্যান্ড্রয়েড বিকাশকারী

14

আপনি যদি অ্যাপাচি কমন্স-আইও লাইব্রেরিটি ব্যবহার করতে না চান তবে এই স্নিপেটটি sun.misc.IOUtils ক্লাস থেকে নেওয়া হয়েছে। এটি বাইটবফার্স ব্যবহার করে সাধারণ প্রয়োগের চেয়ে প্রায় দ্বিগুণ দ্রুত:

public static byte[] readFully(InputStream is, int length, boolean readAll)
        throws IOException {
    byte[] output = {};
    if (length == -1) length = Integer.MAX_VALUE;
    int pos = 0;
    while (pos < length) {
        int bytesToRead;
        if (pos >= output.length) { // Only expand when there's no room
            bytesToRead = Math.min(length - pos, output.length + 1024);
            if (output.length < pos + bytesToRead) {
                output = Arrays.copyOf(output, pos + bytesToRead);
            }
        } else {
            bytesToRead = output.length - pos;
        }
        int cc = is.read(output, pos, bytesToRead);
        if (cc < 0) {
            if (readAll && length != Integer.MAX_VALUE) {
                throw new EOFException("Detect premature EOF");
            } else {
                if (output.length != pos) {
                    output = Arrays.copyOf(output, pos);
                }
                break;
            }
        }
        pos += cc;
    }
    return output;
}

এটি কিছুটা অদ্ভুত সমাধান, দৈর্ঘ্য অ্যারের দৈর্ঘ্যের উপরের একটি আবদ্ধ। আপনি যদি দৈর্ঘ্য জানেন তবে আপনার যা প্রয়োজন তা হ'ল: বাইট [] আউটপুট = নতুন বাইট [দৈর্ঘ্য]; is.read (আউটপুট); (তবে আমার উত্তর দেখুন)
লুক হাচিসন

@ লুক-হাচিসন যেমনটি আমি বলেছিলাম, এটি সান.মিসিক.আইউইটিসগুলির সমাধান। সর্বাধিক সাধারণ ক্ষেত্রে আপনি কোনও ইনপুটস্ট্রিমের সম্মুখভাগের আকার জানেন না, সুতরাং যদি (দৈর্ঘ্য == -1) দৈর্ঘ্য = পূর্ণসংখ্যার MA MAX_VALUE; প্রযোজ্য। প্রদত্ত দৈর্ঘ্য ইনপুট স্ট্রিমের দৈর্ঘ্যের চেয়েও বড় হলেও এই সমাধানটি কার্যকর করে।
ক্রিশ্চিয়ান ক্রালজিক

@ লুকাহাচিসন যদি আপনি দৈর্ঘ্য জানেন তবে কয়েকটি লাইন দিয়ে এটি পরিচালনা করতে পারেন। প্রতিটি উত্তরের দিকে নজর দিলে প্রত্যেকে অভিযোগ করছে যে দৈর্ঘ্য জানা নেই। পরিশেষে একটি উত্তর যা মানসম্মত, জাভা 7 অ্যান্ড্রয়েডের সাথে ব্যবহার করা যেতে পারে এবং কোনও বাহ্যিক গ্রন্থাগারের প্রয়োজন হয় না।
সিএসবা তোথ

11
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (true) {
    int r = in.read(buffer);
    if (r == -1) break;
    out.write(buffer, 0, r);
}

byte[] ret = out.toByteArray();

8

@ অ্যাডামস্কি: আপনি পুরোপুরি বাফার এড়াতে পারবেন।

Http://www.exampledepot.com/egs/java.io/File2ByteArray.html থেকে কোড অনুলিপি করা হয়েছে (হ্যাঁ, এটি খুব ভার্জোজ, তবে অন্যান্য সমাধানের মতো মেমরির অর্ধেক আকার প্রয়োজন))

// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
    InputStream is = new FileInputStream(file);

    // Get the size of the file
    long length = file.length();

    // You cannot create an array using a long type.
    // It needs to be an int type.
    // Before converting to an int type, check
    // to ensure that file is not larger than Integer.MAX_VALUE.
    if (length > Integer.MAX_VALUE) {
        // File is too large
    }

    // Create the byte array to hold the data
    byte[] bytes = new byte[(int)length];

    // Read in the bytes
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length
           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
        offset += numRead;
    }

    // Ensure all the bytes have been read in
    if (offset < bytes.length) {
        throw new IOException("Could not completely read file "+file.getName());
    }

    // Close the input stream and return bytes
    is.close();
    return bytes;
}

5
সামনের আকার জানার উপর নির্ভর করে।
স্টলসভিক

2
অবশ্যই, তবে তাদের আকারটি জানা উচিত: "আমি একটি চিত্র পড়তে চাই"
পাইহেন্টগি

1
আপনি যদি আকারটি জানেন তবে জাভা আপনার জন্য কোড সরবরাহ করে। "ডেটা ইনপুটস্ট্রিম" এর জন্য আমার উত্তর বা গুগল দেখুন এবং এটি সম্পূর্ণরূপে পঠিত পদ্ধতি।
dermoritz

আপনি যোগ করা উচিত is.close()যদি offset < bytes.lengthবা InputStreamযদি সেই ব্যতিক্রম নিক্ষিপ্ত তা বন্ধ করা হবে না।
জারেড রুম্মার

3
তারপরে আরও ভাল, আপনার চেষ্টা করা উচিত রিসোর্স-উইথ রিসোর্সগুলি
pihentagy

8
Input Stream is ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int next = in.read();
while (next > -1) {
    bos.write(next);
    next = in.read();
}
bos.flush();
byte[] result = bos.toByteArray();
bos.close();

তবে সাধারণত ওএস ইতিমধ্যে যথেষ্ট পরিমাণে বাফার করে এটি ছোট ফাইলগুলির জন্য খুব বড় উদ্বেগের কারণ হবে না। এটির মতো নয় যে হার্ড ডিস্কের মাথাটি প্রতিটি বাইট আলাদা আলাদাভাবে পড়বে (একটি হার্ড ডিস্কটি একটি চৌম্বকীয় কাচের প্লেট যার উপর চৌম্বকীয় কোডেড তথ্য রয়েছে, কিছুটা সেই অদ্ভুত আইকনের মতো যা আমরা ডেটা সংরক্ষণে ব্যবহার করি: পি)।
মার্টেন বোদেউয়েস

6
@ মার্টেন বোদেউইস: বেশিরভাগ ডিভাইসে এক ধরণের ব্লক ট্রান্সফার থাকে, সুতরাং প্রতিটি পাঠ () সত্যই কোনও ডিভাইস অ্যাক্সেসের কারণ হতে পারে না, তবে বাইট প্রতি ওএস-কল থাকা ইতিমধ্যে কর্মক্ষমতা হ্রাস করার পক্ষে যথেষ্ট। যদিও মোড়কে InputStreamএকটি BufferedInputStreamযে কোড সামনে ওএস-কল কমানো ও উল্লেখযোগ্যভাবে কর্মক্ষমতা অপূর্ণতা প্রশমিত হবে, যে কোড এখনও অন্য এক বাফার থেকে অপ্রয়োজনীয় ম্যানুয়াল অনুলিপি কাজ করতে হবে।
হলগার

4

জাভা 9 আপনাকে শেষ পর্যন্ত একটি দুর্দান্ত পদ্ধতি দেবে:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();

4
এটি ও InputStram.readAllBytes()ওয়ান লাইনার মধ্যে পার্থক্য কী ?
স্লাভা সেমুশিন

2

আমি জানি এটি অনেক দেরি হয়ে গেছে তবে এখানে আমি মনে করি এটি পরিষ্কার সমাধান যা আরও পঠনযোগ্য ...

/**
 * method converts {@link InputStream} Object into byte[] array.
 * 
 * @param stream the {@link InputStream} Object.
 * @return the byte[] array representation of received {@link InputStream} Object.
 * @throws IOException if an error occurs.
 */
public static byte[] streamToByteArray(InputStream stream) throws IOException {

    byte[] buffer = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();

    int line = 0;
    // read bytes from stream, and store them in buffer
    while ((line = stream.read(buffer)) != -1) {
        // Writes bytes from byte array (buffer) into output stream.
        os.write(buffer, 0, line);
    }
    stream.close();
    os.flush();
    os.close();
    return os.toByteArray();
}

4
আপনার চেষ্টা করা উচিত-সহ-সংস্থানগুলি।
ভিক্টর স্টাফুসা

আপনার শেষ দিকে সাজাতে ত্রুটির ক্ষেত্রে অবশেষে ব্লক করা দরকার, অন্যথায় এটি মেমরি ফাঁস হতে পারে।
এমজিড্যাভিস

2

জাভা 8 ওয়ে ( বাফার্ডারিডার এবং অ্যাডাম বিয়েনকে ধন্যবাদ )

private static byte[] readFully(InputStream input) throws IOException {
    try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
        return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
    }
}

নোট করুন যে এই দ্রবণটি ক্যারিজ রিটার্ন ('\ r') মুছবে এবং অনুপযুক্ত হতে পারে।


4
যে জন্য String। ওপি চাইছে byte[]
ফ্রোজেনফায়ার

এটি কেবল \rসমস্যা হতে পারে না । এই পদ্ধতিটি বাইটগুলিকে অক্ষরগুলিতে রূপান্তর করে এবং আবার ফিরে আসে (ইনপুটস্ট্র্রিমার্ডারের জন্য ডিফল্ট অক্ষর সেট ব্যবহার করে)। ডিফল্ট অক্ষর এনকোডিংয়ে বৈধ নয় এমন কোনও বাইট (লিনাক্সে ইউটিএফ -8 এর জন্য -1 বলুন) দূষিত হবে, সম্ভবত বাইটের সংখ্যাও পরিবর্তন করবে।
seanf

দেখে মনে হচ্ছে এটি ভাল উত্তর, তবে পাঠ্যমুখী। ক্রেতা হুঁশিয়ার.
হুইজিল

1

আমি জঞ্জাল ডেটা লেখার জন্য একটি ফিক্স সহ @ নুমানের উত্তর সম্পাদনা করার চেষ্টা করেছি তবে সম্পাদনা প্রত্যাখ্যান করা হয়েছিল। কোডের এই সংক্ষিপ্ত অংশটি উজ্জ্বল কিছু না হলেও আমি এর চেয়ে ভাল আর কোনও উত্তর দেখতে পাচ্ছি না। এখানে আমার কাছে সবচেয়ে বেশি অর্থবোধ রয়েছে:

ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // you can configure the buffer size
int length;

while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length); //copy streams
in.close(); // call this in a finally block

byte[] result = out.toByteArray();

বিটিডব্লিউ বাইটআরআউটপুট স্ট্রিম বন্ধ করার দরকার নেই। চেষ্টা / শেষ পর্যন্ত পাঠযোগ্যতার জন্য বাদ দেওয়া নির্মাণগুলি


1

InputStream.available()ডকুমেন্টেশন দেখুন :

এটি উপলব্ধি করা বিশেষভাবে গুরুত্বপূর্ণ যে আপনার কোনও ধারক আকারের জন্য এই পদ্ধতিটি ব্যবহার করা উচিত নয় এবং ধারনা করা হয় যে আপনি ধারকটির আকার পরিবর্তন করার প্রয়োজন ছাড়াই প্রবাহের পুরোতাটি পড়তে পারেন। এই জাতীয় কলকারীদের সম্ভবত তারা বাইটআরআর আউটপুট স্ট্রিমে পড়া সমস্ত কিছু লিখতে হবে এবং এটিকে একটি বাইট অ্যারেতে রূপান্তর করতে হবে। বিকল্পভাবে, আপনি যদি কোনও ফাইল থেকে পড়ছেন তবে ফাইল. দৈর্ঘ্য ফাইলের বর্তমান দৈর্ঘ্য ফেরত দেয় (যদিও ধরে নিলে ফাইলের দৈর্ঘ্য পরিবর্তন হতে পারে না ভুল হতে পারে, একটি ফাইল পড়া সহজাতভাবে বৈষম্য)।


1

কোনও কারণে এটি টেবিলের বাইরে থাকলে কোনও ডেটা ইনপুট স্ট্রিমে এটিকে আবদ্ধ করুন, এটি কোনও হাতুড়ি পঠন করতে ব্যবহার করুন যতক্ষণ না এটি আপনাকে একটি -1 দেয় বা আপনি যে ব্লকটি জিজ্ঞাসা করেছিলেন সম্পূর্ণ না দেয়।

public int readFully(InputStream in, byte[] data) throws IOException {
    int offset = 0;
    int bytesRead;
    boolean read = false;
    while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
        read = true;
        offset += bytesRead;
        if (offset >= data.length) {
            break;
        }
    }
    return (read) ? offset : -1;
}

1

এস 3 অবজেক্টকে বাইটআরেতে রূপান্তর করার সময় আমরা কয়েকটি AWS লেনদেনের জন্য কিছুটা বিলম্ব দেখছি।

দ্রষ্টব্য: এস 3 অবজেক্টটি পিডিএফ ডকুমেন্ট (সর্বোচ্চ আকার 3 এমবি)।

S3 অবজেক্টটিকে বাইটআররে রূপান্তর করতে আমরা # 1 বিকল্পটি ব্যবহার করছি (org.apache.commons.io.IOUtils)। আমরা লক্ষ করেছি যে এস 3 এস -3 অবজেক্টকে বাইটআররে রূপান্তর করার জন্য ইনবিল্ড আইইউটিস পদ্ধতি সরবরাহ করে, দেরি এড়াতে S3 অবজেক্টটি বাইটআররে রূপান্তর করার সর্বোত্তম উপায় কোনটি তা নিশ্চিত করার জন্য আমরা আপনাকে অনুরোধ করছি।

বিকল্প 1:

import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

বিকল্প # 2:

import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

এছাড়াও আমাদের কাছে s3 অবজেক্টকে বাইটায়ারে রূপান্তর করার আরও ভাল উপায় আছে কিনা তা আমাকে জানান let


0

অন্য ক্ষেত্রে স্ট্রিমের মাধ্যমে সঠিক বাইট অ্যারে পেতে সার্ভারে অনুরোধ প্রেরণের পরে এবং প্রতিক্রিয়ার জন্য অপেক্ষা করছে waiting

/**
         * Begin setup TCP connection to PC app
         * to open integrate connection between mobile app and pc app (or mobile app)
         */
        mSocket = new Socket(IP, port);
       // mSocket.setSoTimeout(30000);

        DataOutputStream mDos = new DataOutputStream(mSocket.getOutputStream());

        String str = "MobileRequest#" + params[0] + "#<EOF>";

        mDos.write(str.getBytes());

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /* Since data are accepted as byte, all of them will be collected in the
        following byte array which initialised with accepted data length. */
        DataInputStream mDis = new DataInputStream(mSocket.getInputStream());
        byte[] data = new byte[mDis.available()];

        // Collecting data into byte array
        for (int i = 0; i < data.length; i++)
            data[i] = mDis.readByte();

        // Converting collected data in byte array into String.
        String RESPONSE = new String(data);

0

আপনি যদি বাইটআর্যআউটপুট স্ট্রিম ব্যবহার করেন তবে আপনি একটি অতিরিক্ত অনুলিপি করছেন। আপনি যদি স্ট্রিমটি পড়া শুরু করার আগে দৈর্ঘ্য জানেন তবে (উদাহরণস্বরূপ ইনপুট স্ট্রিম আসলে একটি ফাইললাইনপ্রেস্টম, এবং আপনি ফাইলটিতে ফাইল.লেন্থ () কল করতে পারেন, বা ইনপুটস্ট্রিমটি জিপফাইলে প্রবেশকারী ইনপুটস্ট্রিম, এবং আপনি জিপইন্ট্রি কল করতে পারেন। দৈর্ঘ্য ()), তারপরে এটি সরাসরি বাইট [] অ্যারেতে লিখতে অনেক বেশি ভাল - এটি অর্ধেক স্মৃতি ব্যবহার করে এবং সময় সাশ্রয় করে।

// Read the file contents into a byte[] array
byte[] buf = new byte[inputStreamLength];
int bytesRead = Math.max(0, inputStream.read(buf));

// If needed: for safety, truncate the array if the file may somehow get
// truncated during the read operation
byte[] contents = bytesRead == inputStreamLength ? buf
                  : Arrays.copyOf(buf, bytesRead);

স্ট্রিমটি পড়ার সময় উপরের শেষ লাইনটি এনবি ফাইলগুলি কেটে ফেলা নিয়ে ডিল করে, আপনার যদি সেই সম্ভাবনাটি পরিচালনা করতে হয় তবে ফাইলটি যদি প্রবাহটি পড়ার সময় আরও বেশি হয়ে যায়, তবে বাইট [] অ্যারেতে থাকা সামগ্রীগুলি দীর্ঘায়িত করা হবে না নতুন ফাইলের বিষয়বস্তু অন্তর্ভুক্ত করতে অ্যারেটি কেবল পুরানো দৈর্ঘ্যের ইনপুটস্ট্রিমলাইনে ছাঁটা হবে


0

আমি এটি ব্যবহার করি

public static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            byte[] b = new byte[4096];
            int n = 0;
            while ((n = is.read(b)) != -1) {
                output.write(b, 0, n);
            }
            return output.toByteArray();
        } finally {
            output.close();
        }
    }

2
এই উত্তরটি কীভাবে বর্তমান সমস্যা সমাধানে
ওপিকে

0

এটি আমার অনুলিপি-সংস্করণ:

@SuppressWarnings("empty-statement")
public static byte[] inputStreamToByte(InputStream is) throws IOException {
    if (is == null) {
        return null;
    }
    // Define a size if you have an idea of it.
    ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
    byte[] read = new byte[512]; // Your buffer size.
    for (int i; -1 != (i = is.read(read)); r.write(read, 0, i));
    is.close();
    return r.toByteArray();
}

2
যদিও এই কোড স্নিপেট একটি ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে, সত্যিই আপনার পোস্টের মান উন্নত করতে সহায়তা করে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, এবং সেই লোকেরা আপনার কোড পরামর্শের কারণগুলি জানেন না।
ফেরিবিগ

0

জাভা 7 এবং তারপরে:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);

20
sun.misc.IOUtils"জাভা 7" নয়। এটি একটি মালিকানাধীন, বাস্তবায়ন নির্দিষ্ট শ্রেণি যা অন্য জেআরই বাস্তবায়নে উপস্থিত নাও হতে পারে এবং পরের রিলিজগুলির কোনও সতর্কতা ছাড়াই অদৃশ্য হয়ে যায়।
হোলার


0

এখানে একটি অনুকূলিত সংস্করণ, যা যতটা সম্ভব ডেটা বাইট অনুলিপি করা এড়াতে চেষ্টা করে:

private static byte[] loadStream (InputStream stream) throws IOException {
   int available = stream.available();
   int expectedSize = available > 0 ? available : -1;
   return loadStream(stream, expectedSize);
}

private static byte[] loadStream (InputStream stream, int expectedSize) throws IOException {
   int basicBufferSize = 0x4000;
   int initialBufferSize = (expectedSize >= 0) ? expectedSize : basicBufferSize;
   byte[] buf = new byte[initialBufferSize];
   int pos = 0;
   while (true) {
      if (pos == buf.length) {
         int readAhead = -1;
         if (pos == expectedSize) {
            readAhead = stream.read();       // test whether EOF is at expectedSize
            if (readAhead == -1) {
               return buf;
            }
         }
         int newBufferSize = Math.max(2 * buf.length, basicBufferSize);
         buf = Arrays.copyOf(buf, newBufferSize);
         if (readAhead != -1) {
            buf[pos++] = (byte)readAhead;
         }
      }
      int len = stream.read(buf, pos, buf.length - pos);
      if (len < 0) {
         return Arrays.copyOf(buf, pos);
      }
      pos += len;
   }
}

0

কোটলিনে সমাধান (অবশ্যই জাভাতেও কাজ করবে), আপনি যখন আকারটি জানেন বা না জানেন তখন উভয়েরই অন্তর্ভুক্ত রয়েছে:

    fun InputStream.readBytesWithSize(size: Long): ByteArray? {
        return when {
            size < 0L -> this.readBytes()
            size == 0L -> ByteArray(0)
            size > Int.MAX_VALUE -> null
            else -> {
                val sizeInt = size.toInt()
                val result = ByteArray(sizeInt)
                readBytesIntoByteArray(result, sizeInt)
                result
            }
        }
    }

    fun InputStream.readBytesIntoByteArray(byteArray: ByteArray,bytesToRead:Int=byteArray.size) {
        var offset = 0
        while (true) {
            val read = this.read(byteArray, offset, bytesToRead - offset)
            if (read == -1)
                break
            offset += read
            if (offset >= bytesToRead)
                break
        }
    }

আপনি যদি আকারটি জানেন তবে এটি অন্যান্য সমাধানের তুলনায় দ্বিগুণ মেমরি ব্যবহার করা বাঁচায় (একটি সংক্ষিপ্ত মুহূর্তে, তবে এটি কার্যকর হতে পারে)। এর কারণ আপনাকে পুরো স্ট্রিমটি শেষ পর্যন্ত পড়তে হবে এবং তারপরে এটিকে একটি বাইট অ্যারেতে রূপান্তর করতে হবে (অ্যারেলিস্টের সমান যা আপনি কেবল একটি অ্যারেতে রূপান্তর করেন)।

সুতরাং, উদাহরণস্বরূপ, আপনি যদি অ্যান্ড্রয়েডে থাকেন এবং আপনি হ্যান্ডেল করার জন্য কিছুটা উরি পেয়েছেন তবে আপনি এটি ব্যবহার করে আকারটি পাওয়ার চেষ্টা করতে পারেন:

    fun getStreamLengthFromUri(context: Context, uri: Uri): Long {
        context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE), null, null, null)?.use {
            if (!it.moveToNext())
                return@use
            val fileSize = it.getLong(it.getColumnIndex(MediaStore.MediaColumns.SIZE))
            if (fileSize > 0)
                return fileSize
        }
        //if you wish, you can also get the file-path from the uri here, and then try to get its size, using this: https://stackoverflow.com/a/61835665/878126
        FileUtilEx.getFilePathFromUri(context, uri, false)?.use {
            val file = it.file
            val fileSize = file.length()
            if (fileSize > 0)
                return fileSize
        }
        context.contentResolver.openInputStream(uri)?.use { inputStream ->
            if (inputStream is FileInputStream)
                return inputStream.channel.size()
            else {
                var bytesCount = 0L
                while (true) {
                    val available = inputStream.available()
                    if (available == 0)
                        break
                    val skip = inputStream.skip(available.toLong())
                    if (skip < 0)
                        break
                    bytesCount += skip
                }
                if (bytesCount > 0L)
                    return bytesCount
            }
        }
        return -1L
    }

-1
/*InputStream class_InputStream = null;
I am reading class from DB 
class_InputStream = rs.getBinaryStream(1);
Your Input stream could be from any source
*/
int thisLine;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((thisLine = class_InputStream.read()) != -1) {
    bos.write(thisLine);
}
bos.flush();
byte [] yourBytes = bos.toByteArray();

/*Don't forget in the finally block to close ByteArrayOutputStream & InputStream
 In my case the IS is from resultset so just closing the rs will do it*/

if (bos != null){
    bos.close();
}

বোস বন্ধ এবং ফ্লাশিং কীবোর্ড ক্লিকের অপচয়। ইনপুট স্ট্রিমটি বন্ধ করা সাহায্যের সম্ভাবনা বেশি। একবারে একটি বাইট পড়া অকার্যকর। নুমানের উত্তর দেখুন।
akostadinov
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.