Câu trả lời:
Bạn có thể sử dụng Apache Commons IO để xử lý các tác vụ này và các tác vụ tương tự.
Các IOUtils
loại có một phương pháp tĩnh để đọc một InputStream
và trả về một byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
Trong nội bộ, điều này tạo ra một ByteArrayOutputStream
và sao chép các byte vào đầu ra, sau đó gọi toByteArray()
. Nó xử lý các tệp lớn bằng cách sao chép các byte trong các khối 4KiB.
FastArrayList
hoặc Bản đồ tham khảo mềm & yếu của họ và quay lại để cho tôi biết thư viện này được "kiểm tra tốt" như thế nào. Đó là một đống rác
InputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Bạn cần đọc từng byte từ của bạn InputStream
và viết nó vào a ByteArrayOutputStream
.
Sau đó, bạn có thể truy xuất mảng byte bên dưới bằng cách gọi 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();
Cuối cùng, sau hai mươi năm, có một giải pháp đơn giản mà không cần thư viện của bên thứ 3, nhờ vào Java 9 :
InputStream is;
…
byte[] array = is.readAllBytes();
Cũng lưu ý các phương pháp thuận tiện readNBytes(byte[] b, int off, int len)
và transferTo(OutputStream)
giải quyết các nhu cầu định kỳ.
Sử dụng vanilla Java DataInputStream
và readFully
Phương thức của nó (tồn tại từ ít nhất Java 1.4):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Có một số hương vị khác của phương pháp này, nhưng tôi sử dụng tất cả thời gian cho trường hợp sử dụng này.
DataInputStream
này được sử dụng chính để đọc các loại chính (Longs, Quần short, Chars ...) từ một luồng, vì vậy chúng ta có thể thấy cách sử dụng này là lạm dụng của lớp.
InputStream.read
.
Như mọi khi, khung công tác Spring (core-core kể từ 3.2.2) có một cái gì đó dành cho bạn: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();
}
Giải pháp an toàn (với khả năng truyềnclose
phát chính xác):
Phiên bản Java 9+:
final byte[] bytes;
try (inputStream) {
bytes = inputStream.readAllBytes();
}
Phiên bản 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);
}
}
}
Phiên bản Kotlin (khi không thể truy cập 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()
}
}
Để tránh lồng nhau use
xem tại đây .
Bạn có thực sự cần hình ảnh như một byte[]
? Chính xác những gì bạn mong đợi trong byte[]
- nội dung đầy đủ của một tệp hình ảnh, được mã hóa ở bất kỳ định dạng nào mà tệp hình ảnh nằm trong hoặc các giá trị pixel RGB?
Các câu trả lời khác ở đây chỉ cho bạn cách đọc một tệp vào một byte[]
. Của bạn byte[]
sẽ chứa nội dung chính xác của tệp và bạn cần giải mã điều đó để làm bất cứ điều gì với dữ liệu hình ảnh.
API tiêu chuẩn của Java để đọc (và viết) hình ảnh là API ImageIO mà bạn có thể tìm thấy trong gói javax.imageio
. Bạn có thể đọc trong một hình ảnh từ một tệp chỉ với một dòng mã:
BufferedImage image = ImageIO.read(new File("image.jpg"));
Điều này sẽ cung cấp cho bạn một BufferedImage
, không phải a byte[]
. Để có được dữ liệu hình ảnh, bạn có thể gọi getRaster()
vào BufferedImage
. Điều này sẽ cung cấp cho bạn một Raster
đối tượng, có các phương thức để truy cập dữ liệu pixel (nó có một vài getPixel()
/ getPixels()
phương thức).
Tra cứu tài liệu API cho javax.imageio.ImageIO
, java.awt.image.BufferedImage
, java.awt.image.Raster
, vv
ImageIO hỗ trợ một số định dạng hình ảnh theo mặc định: JPEG, PNG, BMP, WBMP và GIF. Có thể thêm hỗ trợ cho nhiều định dạng hơn (bạn cần một trình cắm thực hiện giao diện nhà cung cấp dịch vụ ImageIO).
Xem thêm hướng dẫn sau: Làm việc với hình ảnh
Trong trường hợp ai đó vẫn đang tìm kiếm một giải pháp mà không cần phụ thuộc và Nếu bạn có một tập tin .
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);
Nếu bạn không muốn sử dụng thư viện commons-io của Apache, đoạn mã này được lấy từ lớp sun.misc.IOUtils. Nó nhanh gần gấp đôi so với triển khai phổ biến khi sử dụng ByteBuffers:
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: Bạn có thể tránh bộ đệm hoàn toàn.
Mã được sao chép từ http://www.examplingepot.com/egs/java.io/File2ByteArray.html (Có, nó rất dài dòng, nhưng cần một nửa kích thước bộ nhớ như giải pháp khác.)
// 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()
nếu offset < bytes.length
hoặc InputStream
sẽ không bị đóng nếu ngoại lệ đó được ném.
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
trong một BufferedInputStream
trước khi mã mà sẽ làm giảm các hệ điều hành các cuộc gọi và giảm thiểu những hạn chế hiệu suất đáng kể, mã mà vẫn sẽ làm công việc tay chân sao chép không cần thiết từ một bộ đệm khác.
Java 9 cuối cùng sẽ cung cấp cho bạn một phương thức hay:
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
InputStram.readAllBytes()
cái kia là gì?
Tôi biết rằng đã quá muộn nhưng ở đây tôi nghĩ là giải pháp sạch hơn, dễ đọc hơn ...
/**
* 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();
}
Cách Java 8 (nhờ BufferedReader và Adam Biên )
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>);
}
}
Lưu ý rằng giải pháp này xóa sạch trở lại vận chuyển ('\ r') và có thể không phù hợp.
String
. OP đang yêu cầu byte[]
.
\r
là một vấn đề. Phương thức này chuyển đổi các byte thành ký tự và quay lại (sử dụng bộ ký tự mặc định cho InputStreamReader). Bất kỳ byte nào không hợp lệ trong mã hóa ký tự mặc định (giả sử -1 cho UTF-8 trên Linux) sẽ bị hỏng, thậm chí có thể thay đổi số lượng byte.
Tôi đã cố chỉnh sửa câu trả lời của @ numan bằng cách sửa lỗi ghi dữ liệu rác nhưng chỉnh sửa đã bị từ chối. Mặc dù đoạn mã ngắn này không có gì xuất sắc, tôi không thể thấy câu trả lời nào tốt hơn. Đây là điều có ý nghĩa nhất đối với tôi:
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 không cần phải đóng. thử / cuối cùng các cấu trúc được bỏ qua để dễ đọc
Xem InputStream.available()
tài liệu:
Điều đặc biệt quan trọng là nhận ra rằng bạn không được sử dụng phương pháp này để định kích thước vùng chứa và giả sử rằng bạn có thể đọc toàn bộ luồng mà không cần thay đổi kích thước vùng chứa. Những người gọi như vậy có lẽ nên viết mọi thứ họ đọc vào ByteArrayOutputStream và chuyển đổi nó thành một mảng byte. Ngoài ra, nếu bạn đang đọc từ một tệp, File.length trả về độ dài hiện tại của tệp (mặc dù giả sử độ dài của tệp không thể thay đổi có thể không chính xác, việc đọc tệp vốn không phù hợp).
Vì vậy, hãy bọc nó trong DataInputStream nếu điều đó không có trong bảng vì một số lý do, chỉ cần sử dụng read để gõ vào nó cho đến khi nó cung cấp cho bạn -1 hoặc toàn bộ khối bạn yêu cầu.
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;
}
Chúng tôi đang thấy một số chậm trễ cho một vài giao dịch AWS, trong khi chuyển đổi đối tượng S3 sang ByteArray.
Lưu ý: Đối tượng S3 là tài liệu PDF (kích thước tối đa là 3 mb).
Chúng tôi đang sử dụng tùy chọn # 1 (org.apache.commons.io.IOUtils) để chuyển đổi đối tượng S3 thành ByteArray. Chúng tôi đã nhận thấy S3 cung cấp phương thức IOUtils sẵn có để chuyển đổi đối tượng S3 thành ByteArray, chúng tôi yêu cầu bạn xác nhận cách tốt nhất để chuyển đổi đối tượng S3 thành ByteArray để tránh sự chậm trễ.
Lựa chọn 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Lựa chọn 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Đồng thời cho tôi biết nếu chúng tôi có cách nào khác tốt hơn để chuyển đổi đối tượng s3 thành bytearray
Các trường hợp khác để có được mảng byte chính xác qua luồng, sau khi gửi yêu cầu đến máy chủ và chờ phản hồi.
/**
* 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);
Bạn đang thực hiện một bản sao bổ sung nếu bạn sử dụng ByteArrayOutputStream. Nếu bạn biết độ dài của luồng trước khi bạn bắt đầu đọc nó (ví dụ InputStream thực sự là FileInputStream và bạn có thể gọi file.length () trên tệp hoặc InputStream là mục nhập zipfile InputStream và bạn có thể gọi zipEntry. length ()), tốt hơn hết là ghi trực tiếp vào mảng byte [] - nó sử dụng một nửa bộ nhớ và tiết kiệm thời gian.
// 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);
Lưu ý dòng cuối cùng ở trên xử lý các tệp bị cắt bớt trong khi luồng đang được đọc, nếu bạn cần xử lý khả năng đó, nhưng nếu tệp bị dài hơn trong khi luồng đang được đọc, nội dung trong mảng byte [] sẽ không được kéo dài để bao gồm nội dung tệp mới, mảng sẽ đơn giản được cắt ngắn theo chiều dài inputStreamLpm .
Tôi sử dụng cái này
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();
}
}
Đây là phiên bản sao chép của tôi:
@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 trở lên:
import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
sun.misc.IOUtils
không phải là Java Java 7 7. Đó là một lớp cụ thể, triển khai cụ thể có thể không có trong các triển khai JRE khác và có thể biến mất mà không có bất kỳ cảnh báo nào trong một trong các bản phát hành tiếp theo.
Đây là một phiên bản được tối ưu hóa, cố gắng tránh sao chép dữ liệu byte càng nhiều càng tốt:
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;
}
}
Giải pháp trong Kotlin (tất nhiên cũng sẽ hoạt động trong Java), bao gồm cả hai trường hợp khi bạn biết kích thước hay không:
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
}
}
Nếu bạn biết kích thước, nó giúp bạn tiết kiệm gấp đôi bộ nhớ được sử dụng so với các giải pháp khác (trong một thời gian ngắn, nhưng vẫn có thể hữu ích). Đó là bởi vì bạn phải đọc toàn bộ luồng đến cuối, sau đó chuyển đổi nó thành một mảng byte (tương tự như ArrayList mà bạn chuyển đổi thành một mảng).
Vì vậy, nếu bạn đang ở trên Android, chẳng hạn, và bạn có một số Uri để xử lý, bạn có thể thử lấy kích thước bằng cách này:
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();
}