답변:
Apache Commons IO 를 사용 하여 이와 유사한 작업을 처리 할 수 있습니다 .
IOUtils
유형은을 읽을 수있는 정적 메소드가 InputStream
와를 반환을 byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
내부적으로 이것은 a를 생성 ByteArrayOutputStream
하고 바이트를 출력에 복사 한 다음을 호출합니다 toByteArray()
. 4KiB의 블록으로 바이트를 복사하여 큰 파일을 처리합니다.
FastArrayList
또는 소프트 및 취약한 참조 맵을 살펴보고이 라이브러리가 어떻게 "잘 테스트"되었는지 알려주십시오. 쓰레기 더미입니다
InputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
에서 각 바이트를 읽고에 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
방법을 사용하십시오 (적어도 Java 1.4부터 존재합니다).
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
이 방법에는 다른 맛이 있지만이 사용 사례에는 항상 이것을 사용합니다.
DataInputStream
는 스트림에서 기본 유형 (Longs, Shorts, Chars ...)을 읽는 데 사용되는 기본 클래스 이므로이 사용법을 클래스의 오용으로 볼 수 있습니다.
InputStream.read
.
google guava 를 사용하면 다음 과 같이 간단합니다.
byte[] bytes = ByteStreams.toByteArray(inputStream);
ByteStreams
님이 주석을 추가했습니다@Beta
항상 그렇듯이 Spring 프레임 워크 (3.2.2 이후의 스프링 코어)에는 다음과 같은 것이 있습니다.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();
}
안전한 솔루션 (close
스트림기능이올바르게 제공됨) :
Java 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);
}
}
}
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()
}
}
당신은 정말 이미지가 필요 byte[]
합니까? byte[]
이미지 파일의 전체 내용, 이미지 파일의 형식 또는 RGB 픽셀 값으로 인코딩 된 정확한 내용은 무엇입니까?
다른 답변은 파일을로 읽는 방법을 보여줍니다 byte[]
. 사용자는 byte[]
파일의 정확한 내용을 포함, 당신은 이미지 데이터와 아무것도 할 것을 디코딩에 필요한 것입니다.
이미지 읽기 및 쓰기를위한 Java의 표준 API는 패키지에서 찾을 수있는 ImageIO API javax.imageio
입니다. 단 한 줄의 코드로 파일에서 이미지를 읽을 수 있습니다.
BufferedImage image = ImageIO.read(new File("image.jpg"));
이것은 당신에게 a 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 서비스 제공자 인터페이스를 구현하는 플러그인이 필요함).
다음 자습서를 참조하십시오. 이미지 작업
경우에 누군가가 여전히 의존성이없는 솔루션을 찾고 있고 파일이있는 경우 .
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);
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;
}
@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;
}
is.close()
하는 경우 offset < bytes.length
또는는 InputStream
그 예외가 발생하면 닫히지 않습니다.
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();
InputStream
A의를 BufferedInputStream
운영 체제-통화를 줄이고 크게 성능의 단점을 완화시킬 그 코드 전에, 그 코드는 또 다른 하나의 버퍼에서 불필요한 수동 복사 작업을 할 것입니다.
Java 9는 마침내 멋진 방법을 제공합니다.
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
InputStram.readAllBytes()
그 차이점은 무엇입니까 ?
너무 늦었다는 것을 알고 있지만 더 읽기 쉬운 솔루션이라고 생각합니다 ...
/**
* 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 방식 ( BufferedReader 및 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')를 부적절 할 수있다.
String
입니다. OP가 요청합니다 byte[]
.
\r
그건 문제가 될 수 있습니다. 이 메소드는 바이트를 문자로 변환 한 후 다시 변환합니다 (InputStreamReader의 기본 문자 세트 사용). 기본 문자 인코딩에서 유효하지 않은 바이트 (예 : Linux에서 UTF-8의 경우 -1)는 손상되어 바이트 수를 변경하기도합니다.
가비지 데이터를 쓰는 수정으로 @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는 파일의 현재 길이를 반환합니다 (파일의 길이를 변경할 수 없다고 가정 할 경우 파일을 읽는 것이 본질적으로 정확하지 않음).
어떤 이유로 테이블에서 꺼져 있으면 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;
}
S3 객체를 ByteArray로 변환하는 동안 AWS 트랜잭션이 약간 지연 될 수 있습니다.
참고 : S3 Object는 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 객체를 바이트 배열로 변환하는 다른 더 좋은 방법이 있는지 알려주십시오.
다른 경우는 서버에 요청을 보내고 응답을 기다린 후 스트림을 통해 올바른 바이트 배열을 얻는 것입니다.
/**
* 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);
위의 마지막 줄은 스트림을 읽는 동안 파일이 잘리는 것을 처리합니다.이 가능성을 처리해야하지만 스트림을 읽는 동안 파일이 길어 지면 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();
}
다음은 가능한 한 많이 데이터 바이트를 복사하지 않도록하는 최적화 된 버전입니다.
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
}
}
크기를 알면 다른 솔루션에 비해 두 배의 메모리를 사용하는 시간을 절약 할 수 있습니다 (짧은 시간이지만 여전히 유용 할 수 있음). 전체 스트림을 끝까지 읽은 다음 바이트 배열 (배열 만 변환하는 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
}
/*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();
}