programing

Java에서 InputStream을 바이트 배열로 변환

goodsources 2022. 7. 17. 18:16
반응형

Java에서 InputStream을 바이트 배열로 변환

하나요?InputStream이트트 배열 ?? ????

Apache Commons IO를 사용하여 이 작업과 유사한 작업을 처리할 수 있습니다.

IOUtils 메서드를 하여 static static을 .InputStreambyte[].

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

으로는, 「」, 「」, 「」가 작성됩니다.ByteArrayOutputStream한 후 "Calling" 을 호출합니다.toByteArray()4KiB 블록으로 바이트를 복사하여 대용량 파일을 처리합니다.

한 자 한 해요.InputStream을 쓰다.ByteArrayOutputStream

그런 "Byte Array"를 호출하여 수 .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();

마지막으로 20년이 지난 후 Java 9 덕분에 서드파티 라이브러리가 필요 없는 심플한 솔루션이 등장했습니다.

InputStream is;
…
byte[] array = is.readAllBytes();

또, 편리한 방법이나 반복적인 요구에의 대처에도 주의해 주세요.

DataInputStream 그 ★★★readFully1.4

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

이 방법에는 다른 맛도 있습니다만, 이 사용 예에서는 항상 사용하고 있습니다.

Google Guava를 사용하는 경우 다음과 같이 간단하게 사용할 수 있습니다.

byte[] bytes = ByteStreams.toByteArray(inputStream);

항상 그렇듯이 스프링 프레임워크(3.2.2 이후 스프링 코어)에도 다음과 같은 특징이 있습니다.StreamUtils.copyToByteArray()

안전한 솔루션(스트림을 올바르게 닫음):

  • Java 9+:

     final byte[] bytes;
     try (inputStream) {
         bytes = inputStream.readAllBytes();
     }
    

  • Java 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);
             }
         }
     }
    

  • Kotlin(Java 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여기를 봐주세요.


  • Scala(Java 9+에 액세스할 수 없는 경우)(@Joan에 의해).Thx):

    def readAllBytes(inputStream: InputStream): Array[Byte] =
      Stream.continually(inputStream.read).takeWhile(_ != -1).map(_.toByte).toArray
    
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();
}

인 케이스에서는, 의존성이 없는 솔루션을 찾고 있어 파일이 있는 경우는, 계속 솔루션을 찾고 있습니다.

데이터 입력 스트림

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

바이트 어레이 출력 스트림

 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);
 }

랜덤 액세스 파일

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

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★byte[]에서는 정확히 이 시점에서 정확히 무엇을 기대하십니까?byte[], 값 - 이미지 파일의 완전한 내용, RGB 픽셀 값.

다른 '읽는 '을 .byte[]의 . . . . . . . .byte[]파일의 정확한 내용이 포함됩니다.이미지 데이터를 사용하려면 , 그 내용을 디코딩 할 필요가 있습니다.

이미지 API입니다. IO API에 있는 APIjavax.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.Rastersyslog.

ImageIO는 기본적으로 JPEG, PNG, BMP, WBMP 및 GIF 등 다양한 이미지 형식을 지원합니다.더 많은 포맷에 대한 지원을 추가할 수 있습니다(이미지를 구현하는 플러그인이 필요함).IO 서비스 프로바이더인터페이스).

다음의 튜토리얼도 참조해 주세요.이미지 조작

Apache commons-io 라이브러리를 사용하지 않으려면 이 스니펫을 sun.misc에서 가져옵니다.차용증 수업ByteBuffer를 사용한 일반적인 구현보다 거의 두 배 빠릅니다.

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;
}
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();
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();

@Adamski:버퍼를 완전히 회피할 수 있습니다.

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;
}

Java 9가 드디어 좋은 방법을 제공합니다.

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

너무 늦은 건 알지만, 여기 보다 읽기 쉬운 더 깔끔한 솔루션이 있다고 생각합니다.

/**
 * 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();
}

S3 오브젝트를 ByteArray로 변환하는 동안 AWS 트랜잭션의 지연이 발생하고 있습니다.

주의: S3 오브젝트는 PDF 문서입니다(최대 사이즈는 3MB).

옵션 #1(org.apache.commons.io을 사용하고 있습니다.IOUtils)를 사용하여 S3 개체를 ByteArray로 변환합니다.S3가 S3 객체를 ByteArray로 변환하는 inbuild IOUtils 메서드를 제공하고 있음을 알게 되었습니다.지연을 피하기 위해 S3 객체를 ByteArray로 변환하는 최선의 방법이 무엇인지 확인해 주십시오.

옵션 #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 오브젝트를 byearray로 변환할 수 있는 더 좋은 방법이 있으면 알려주세요.

가비지 데이터를 쓰는 수정 프로그램을 사용하여 @numan의 답변을 편집하려고 했지만 편집이 거부되었습니다.이 짧은 코드 조각이 훌륭한 것은 아니지만 더 나은 해답은 없다.내가 가장 이해할 수 있는 것은 다음과 같다.

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();

btw ByteArrayOutputStream을 닫을 필요가 없습니다. 가독성을 위해 구성을 시도/마침내 생략합니다.

「 」를 .InputStream.available()★★★★

컨테이너 크기를 조정하고 컨테이너 크기를 조정하지 않고도 스트림 전체를 읽을 수 있다고 가정할 때 이 방법을 사용하지 않는 것이 특히 중요합니다.이러한 발신자는 읽은 내용을 모두 ByteArrayOutputStream에 쓰고 그것을 ByteArrayOutputStream으로 변환해야 합니다.또는 파일에서 읽을 경우 File.length는 파일의 현재 길이를 반환합니다(파일 길이를 변경할 수 없다고 가정할 수 있지만 파일을 읽는 것은 본질적으로 래시입니다).

어떤 이유로 테이블에서 벗어난 경우 DataInputStream으로 랩합니다. -1 또는 전체 블록을 얻을 수 있을 때까지 read를 사용하여 자세히 읽어 보십시오.

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;
}

Java 8way (Buffered Reader 및 Adam Bien 지원)

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')을 지우는 것으로 부적절할 수 있습니다.

다른 하나는 서버에 요청을 전송하고 응답을 기다린 후 스트림을 통해 올바른 바이트 배열을 얻는 경우입니다.

/**
         * 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);

ByteArrayOutputStream을 사용하면 추가 복사를 해야 합니다.스트림을 읽기 전에 스트림의 길이를 알고 있는 경우(예를 들어 InputStream은 실제로 FileInputStream이며 파일 상에서 file.length()를 호출할 수 있습니다.또는 InputStream은 zip 파일엔트리의 InputStream을 호출할 수 있습니다.)는 바이트[ 어레이]에 직접 쓰는 것이 좋습니다.시간을.

// 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);

위의 마지막 행은 스트림이 읽히는 동안 파일이 잘리는 문제를 처리합니다.그 가능성을 처리할 필요가 있지만 스트림이 읽히는 동안 파일이 길어지면 바이트[] 배열의 내용이 새로운 파일 내용을 포함하도록 길지 않고 배열이 오래된 길이의 입력 스트림 링트로 잘라집니다.h.

이거 써요.

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();
        }
    }

복사 붙여넣기 버전입니다.

@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();
}

Java 7 이후:

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

선인장을 맛볼 수 있습니다.

byte[] array = new BytesOf(stream).bytes();

데이터 바이트의 복사를 가능한 한 회피하기 위해 최적화된 버전을 다음에 나타냅니다.

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;
   }
}

Kotlin의 솔루션(물론 Java에서도 동작합니다)에는 크기를 알 수 있는지 없는지가 포함됩니다.

    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
        }
    }

사이즈를 알면, 다른 솔루션보다 2배의 메모리를 사용하는 것을 절약할 수 있습니다(단순간에 편리할 수 있습니다).그 이유는 스트림 전체를 끝까지 읽은 후 바이트 배열로 변환해야 하기 때문입니다(배열로만 변환하는 ArrayList와 유사).

예를 들어 Android에서 URI를 처리해야 하는 경우 다음과 같이 크기를 확인할 수 있습니다.

    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
    }

재사용 가능한 개체 지향 Java 구성 요소를 제공하는 선인장 라이브러리를 사용할 수 있습니다.OOP는 이 라이브러리에서 강조되므로 정적 메서드나 NULL 등은 사용하지 않고 실제 객체와 그 계약(인터페이스)만 강조합니다.InputStream 읽기 등의 간단한 조작을 수행할 수 있습니다.

final InputStream input = ...;
final Bytes bytes = new BytesOf(input);
final byte[] array = bytes.asBytes();
Assert.assertArrayEquals(
    array,
    new byte[]{65, 66, 67}
);

타입의 「」가 .Bytes 구조 byte[]OOP 전술을 사용하여 당면한 작업을 해결할 수 있습니다.절차상의 "유틸리티" 방법 때문에 우리가 할 수 없는 것.를 들어, 이 에서 읽은 .InputStreamBase64로 이동합니다.이 경우 Base64의 구현 내에서 Decorator 패턴과 랩 바이트 개체를 사용합니다.선인장은 이미 이러한 구현을 제공하고 있습니다.

final Bytes encoded = new BytesBase64(
    new BytesOf(
        new InputStreamOf("XYZ")
    )
);
Assert.assertEquals(new TextOf(encoded).asString(), "WFla");

데코레이터 패턴을 사용하여 동일한 방법으로 디코딩할 수 있습니다.

final Bytes decoded = new Base64Bytes(
    new BytesBase64(
        new BytesOf(
            new InputStreamOf("XYZ")
        )
    )
);
Assert.assertEquals(new TextOf(decoded).asString(), "XYZ");

을 하든지 간에 여러분은 자신만의 수 .Bytes해결할 수 있습니다.

언급URL : https://stackoverflow.com/questions/1264709/convert-inputstream-to-byte-array-in-java

반응형