Programing

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

crosscheck 2020. 9. 29. 07:20
반응형

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


전체 InputStream를 바이트 배열로 읽으려면 어떻게합니까 ?


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

IOUtils유형은을 읽을 수있는 정적 메소드가 InputStream와를 반환을 byte[].

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

내부적으로 이것은를 생성 ByteArrayOutputStream하고 출력에 바이트를 복사 한 다음 toByteArray(). 4KiB 블록으로 바이트를 복사하여 대용량 파일을 처리합니다.


당신은 당신의에서 각 바이트를 읽을 필요 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();

마지막으로, 20 년 후 Java 9 덕분에 타사 라이브러리가 필요없는 간단한 솔루션이 있습니다 .

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

편리한 방법 readNBytes(byte[] b, int off, int len)transferTo(OutputStream)반복되는 요구 사항을 해결하는 방법도 확인하십시오 .


바닐라 자바 DataInputStream와 그 readFully방법을 사용하세요 (최소한 자바 1.4부터 존재) :

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

이 방법에는 몇 가지 다른 맛이 있지만이 사용 사례에서는 항상 이것을 사용합니다.


Google 구아바 를 사용하는 경우 다음 과 같이 간단합니다.

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

언제나 그렇듯이 Spring 프레임 워크 (3.2.2 이후의 spring-core)도 당신을위한 무언가를 가지고 있습니다.StreamUtils.copyToByteArray()


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[]합니까? byte[]이미지 파일의 형식에 관계없이 인코딩 된 이미지 파일의 전체 내용 또는 RGB 픽셀 값 에서 정확히 무엇을 기대 합니까?

여기에있는 다른 답변은 파일을 byte[]. 사용자는 byte[]파일의 정확한 내용을 포함, 당신은 이미지 데이터와 아무것도 할 것을 디코딩에 필요한 것입니다.

이미지 읽기 (및 쓰기)를위한 Java의 표준 API는 패키지에서 찾을 수있는 ImageIO API javax.imageio입니다. 단 한 줄의 코드로 파일에서 이미지를 읽을 수 있습니다.

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

이것은 당신 줄 것 BufferedImage아닌에게 byte[]. 이미지 데이터를 얻으려면, 당신은 호출 할 수 있습니다 getRaster()BufferedImage. 이렇게하면 Raster픽셀 데이터에 액세스 할 수있는 메서드가 있는 객체 가 제공 됩니다 (여러 getPixel()/ getPixels()메서드가 있음).

API 문서를 조회에 javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Raster

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

다음 튜토리얼도 참조하십시오 : 이미지 작업


Apache commons-io 라이브러리를 사용하지 않으려는 경우이 코드 조각은 sun.misc.IOUtils 클래스에서 가져옵니다. 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;
}

누군가가 여전히 종속성이없는 솔루션을 찾고 있다면 파일이있는 경우 .

1) DataInputStream

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

2) ByteArrayOutputStream

 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

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

안전한 솔루션 (close올바른 스트림기능 포함) :

  • 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 버전 (자바 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 참조 하십시오 .


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

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

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

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

Java 8 방식 ( BufferedReaderAdam 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')를 부적절 할 수있다.


가비지 데이터 작성에 대한 수정으로 @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을 닫을 필요가 없습니다. 가독성을 위해 생략 된 try / finally 구문


InputStream.available()설명서를 참조하십시오 .

컨테이너 크기를 조정하는 데이 메서드를 사용해서는 안되며 컨테이너 크기를 조정할 필요없이 스트림 전체를 읽을 수 있다고 가정하는 것이 특히 중요합니다. 이러한 호출자는 읽은 모든 것을 ByteArrayOutputStream에 쓰고이를 바이트 배열로 변환해야합니다. 또는 파일에서 읽는 경우 File.length는 파일의 현재 길이를 반환합니다 (파일의 길이를 변경할 수 없다고 가정하면 파일을 읽는 것은 본질적으로 선정적입니다).


Java 7 이상 :

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

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

/**
         * 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이고 zipEntry를 호출 할 수 있습니다. length ())이면 byte [] 배열에 직접 쓰는 것이 훨씬 낫습니다. 메모리의 절반을 사용하고 시간을 절약합니다.

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

NB 위의 마지막 줄은 스트림을 읽는 동안 잘리는 파일을 다룹니다. 이러한 가능성을 처리해야하는 경우 스트림을 읽는 동안 파일이 길어 지면 byte [] 배열의 내용이 길어지지 않습니다. 새 파일 내용을 포함하기 위해 배열은 단순히 이전 길이 inputStreamLength 로 잘립니다 .


나는 이것을 사용한다.

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

어떤 이유로 테이블에서 벗어난 경우 DataInputStream으로 래핑하고 -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;
}

Cactoos 를 사용해 볼 수 있습니다 .

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

S3 객체를 ByteArray로 변환하는 동안 몇 가지 AWS 트랜잭션에 대해 약간의 지연이 발생합니다.

참고 : S3 개체는 PDF 문서입니다 (최대 크기는 3MB).

S3 객체를 ByteArray로 변환하기 위해 옵션 # 1 (org.apache.commons.io.IOUtils)을 사용하고 있습니다. 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 객체를 bytearray로 변환하는 다른 더 좋은 방법이 있는지 알려주십시오.


다음은 가능한 한 데이터 바이트 복사를 방지하는 최적화 된 버전입니다.

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

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

이것은 나를 위해 작동합니다.

if(inputStream != null){
                ByteArrayOutputStream contentStream = readSourceContent(inputStream);
                String stringContent = contentStream.toString();
                byte[] byteArr = encodeString(stringContent);
            }

readSourceContent ()

public static ByteArrayOutputStream readSourceContent(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int nextChar;
        try {
            while ((nextChar = inputStream.read()) != -1) {
                outputStream.write(nextChar);
            }
            outputStream.flush();
        } catch (IOException e) {
            throw new IOException("Exception occurred while reading content", e);
        }

        return outputStream;
    }

encodeString ()

public static byte[] encodeString(String content) throws UnsupportedEncodingException {
        byte[] bytes;
        try {
            bytes = content.getBytes();

        } catch (UnsupportedEncodingException e) {
            String msg = ENCODING + " is unsupported encoding type";
            log.error(msg,e);
            throw new UnsupportedEncodingException(msg, e);
        }
        return bytes;
    }

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

반응형