Làm cách nào để chuyển đổi a java.io.File
thành a byte[]
?
Làm cách nào để chuyển đổi a java.io.File
thành a byte[]
?
Câu trả lời:
Nó phụ thuộc vào những gì tốt nhất có nghĩa cho bạn. Năng suất khôn ngoan, không phát minh lại bánh xe và sử dụng Apache Commons. Đó là đây IOUtils.toByteArray(InputStream input)
.
File
đến byte[]
? Tôi đang sử dụng Java6 vì vậy tôi không thể sử dụng các phương thức NIO :(
Từ JDK 7 bạn có thể sử dụng Files.readAllBytes(Path)
.
Thí dụ:
import java.io.File;
import java.nio.file.Files;
File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());
Kể từ JDK 7 - một lớp lót:
byte[] array = Files.readAllBytes(Paths.get("/path/to/file"));
Không cần phụ thuộc bên ngoài.
import java.nio.file.Files;
và import java.nio.file.Paths;
nếu bạn chưa có.
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
Tài liệu cho Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
Về cơ bản bạn phải đọc nó trong bộ nhớ. Mở tệp, phân bổ mảng và đọc nội dung từ tệp vào mảng.
Cách đơn giản nhất là một cái gì đó tương tự như thế này:
public byte[] read(File file) throws IOException, FileTooBigException {
if (file.length() > MAX_FILE_SIZE) {
throw new FileTooBigException(file);
}
ByteArrayOutputStream ous = null;
InputStream ios = null;
try {
byte[] buffer = new byte[4096];
ous = new ByteArrayOutputStream();
ios = new FileInputStream(file);
int read = 0;
while ((read = ios.read(buffer)) != -1) {
ous.write(buffer, 0, read);
}
}finally {
try {
if (ous != null)
ous.close();
} catch (IOException e) {
}
try {
if (ios != null)
ios.close();
} catch (IOException e) {
}
}
return ous.toByteArray();
}
Điều này có một số sao chép không cần thiết của nội dung tệp (thực tế dữ liệu được sao chép ba lần: từ tệp đến buffer
, từ buffer
đến ByteArrayOutputStream
, từ ByteArrayOutputStream
mảng kết quả thực tế).
Bạn cũng cần đảm bảo rằng bạn chỉ đọc trong bộ nhớ các tệp có kích thước nhất định (điều này thường phụ thuộc vào ứng dụng) :-).
Bạn cũng cần phải điều trị IOException
các chức năng bên ngoài.
Một cách khác là thế này:
public byte[] read(File file) throws IOException, FileTooBigException {
if (file.length() > MAX_FILE_SIZE) {
throw new FileTooBigException(file);
}
byte[] buffer = new byte[(int) file.length()];
InputStream ios = null;
try {
ios = new FileInputStream(file);
if (ios.read(buffer) == -1) {
throw new IOException(
"EOF reached while trying to read the whole file");
}
} finally {
try {
if (ios != null)
ios.close();
} catch (IOException e) {
}
}
return buffer;
}
Điều này không có sao chép không cần thiết.
FileTooBigException
là một ngoại lệ ứng dụng tùy chỉnh. Các MAX_FILE_SIZE
hằng số là một thông số ứng dụng.
Đối với các tệp lớn, có lẽ bạn nên nghĩ thuật toán xử lý luồng hoặc sử dụng ánh xạ bộ nhớ (xem java.nio
).
Như ai đó đã nói, những người sử dụng tệp Apache Commons có thể có những gì bạn đang tìm kiếm
public static byte[] readFileToByteArray(File file) throws IOException
Ví dụ sử dụng ( Program.java
):
import org.apache.commons.io.FileUtils;
public class Program {
public static void main(String[] args) throws IOException {
File file = new File(args[0]); // assume args[0] is the path to file
byte[] data = FileUtils.readFileToByteArray(file);
...
}
}
Bạn cũng có thể sử dụng api NIO để làm điều đó. Tôi có thể làm điều này với mã này miễn là tổng kích thước tệp (tính bằng byte) sẽ vừa với một int.
File f = new File("c:\\wscp.script");
FileInputStream fin = null;
FileChannel ch = null;
try {
fin = new FileInputStream(f);
ch = fin.getChannel();
int size = (int) ch.size();
MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);
byte[] bytes = new byte[size];
buf.get(bytes);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (fin != null) {
fin.close();
}
if (ch != null) {
ch.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Tôi nghĩ rằng nó rất nhanh kể từ khi sử dụng MappedByteBuffer.
Nếu bạn không có Java 8 và đồng ý với tôi rằng bao gồm một thư viện đồ sộ để tránh viết một vài dòng mã là một ý tưởng tồi:
public static byte[] readBytes(InputStream inputStream) throws IOException {
byte[] b = new byte[1024];
ByteArrayOutputStream os = new ByteArrayOutputStream();
int c;
while ((c = inputStream.read(b)) != -1) {
os.write(b, 0, c);
}
return os.toByteArray();
}
Người gọi có trách nhiệm đóng luồng.
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
// 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
throw new IOException("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;
InputStream is = new FileInputStream(file);
try {
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
} finally {
is.close();
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
return bytes;
}
throw new IOException("File is too large!");
Chúng ta nên làm gì khi tệp quá lớn? Có bất kỳ ví dụ về nó?
Cách đơn giản để làm điều đó:
File fff = new File("/path/to/file");
FileInputStream fileInputStream = new FileInputStream(fff);
// int byteLength = fff.length();
// In android the result of file.length() is long
long byteLength = fff.length(); // byte count of the file-content
byte[] filecontent = new byte[(int) byteLength];
fileInputStream.read(filecontent, 0, (int) byteLength);
Cách đơn giản nhất để đọc byte từ tệp
import java.io.*;
class ReadBytesFromFile {
public static void main(String args[]) throws Exception {
// getBytes from anyWhere
// I'm getting byte array from File
File file = null;
FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));
// Instantiate array
byte[] arr = new byte[(int) file.length()];
// read All bytes of File stream
fileStream.read(arr, 0, arr.length);
for (int X : arr) {
System.out.print((char) X);
}
}
}
.*
, nó được coi là thông lệ xấu.
Quả ổi có Files.toByteArray () để cung cấp cho bạn. Nó có một số lợi thế:
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
File file = getYourFile();
Path path = file.toPath();
byte[] data = Files.readAllBytes(path);
Sử dụng cách tiếp cận tương tự như câu trả lời wiki cộng đồng, nhưng dọn dẹp và biên dịch ra khỏi hộp (cách tiếp cận ưa thích nếu bạn không muốn nhập libs Commons của Apache, ví dụ như trên Android):
public static byte[] getFileBytes(File file) throws IOException {
ByteArrayOutputStream ous = null;
InputStream ios = null;
try {
byte[] buffer = new byte[4096];
ous = new ByteArrayOutputStream();
ios = new FileInputStream(file);
int read = 0;
while ((read = ios.read(buffer)) != -1)
ous.write(buffer, 0, read);
} finally {
try {
if (ous != null)
ous.close();
} catch (IOException e) {
// swallow, since not that important
}
try {
if (ios != null)
ios.close();
} catch (IOException e) {
// swallow, since not that important
}
}
return ous.toByteArray();
}
Tôi tin rằng đây là cách dễ nhất:
org.apache.commons.io.FileUtils.readFileToByteArray(file);
ReadFully Đọc các byte b.length từ tệp này vào mảng byte, bắt đầu từ con trỏ tệp hiện tại. Phương pháp này đọc lặp lại từ tệp cho đến khi số byte được yêu cầu được đọc. Phương thức này chặn cho đến khi số byte được yêu cầu được đọc, kết thúc luồng được phát hiện hoặc ném ngoại lệ.
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
Nếu bạn muốn đọc byte vào bộ đệm byte được phân bổ trước, câu trả lời này có thể hữu ích.
Dự đoán đầu tiên của bạn có thể sẽ được sử dụng InputStream read(byte[])
. Tuy nhiên, phương pháp này có một lỗ hổng khiến nó khó sử dụng một cách vô lý: không có gì đảm bảo rằng mảng sẽ thực sự được lấp đầy hoàn toàn, ngay cả khi không gặp phải EOF.
Thay vào đó, hãy xem DataInputStream readFully(byte[])
. Đây là một trình bao bọc cho các luồng đầu vào và không có vấn đề được đề cập ở trên. Ngoài ra, phương pháp này ném khi gặp EOF. Đẹp hơn nhiều.
Cách sau đây không chỉ chuyển đổi java.io.File thành byte [], tôi cũng thấy đó là cách nhanh nhất để đọc trong tệp, khi kiểm tra nhiều phương thức đọc tệp Java khác nhau :
java.nio.file.Files.read ALLBytes ()
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class ReadFile_Files_ReadAllBytes {
public static void main(String [] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
File file = new File(fileName);
byte [] fileBytes = Files.readAllBytes(file.toPath());
char singleChar;
for(byte b : fileBytes) {
singleChar = (char) b;
System.out.print(singleChar);
}
}
}
Hãy để tôi thêm một giải pháp khác mà không cần sử dụng thư viện của bên thứ ba. Nó sử dụng lại một mẫu xử lý ngoại lệ được đề xuất bởi Scott ( link ). Và tôi đã chuyển phần xấu xí thành một tin nhắn riêng biệt (tôi sẽ ẩn trong một số lớp FileUtils;))
public void someMethod() {
final byte[] buffer = read(new File("test.txt"));
}
private byte[] read(final File file) {
if (file.isDirectory())
throw new RuntimeException("Unsupported operation, file "
+ file.getAbsolutePath() + " is a directory");
if (file.length() > Integer.MAX_VALUE)
throw new RuntimeException("Unsupported operation, file "
+ file.getAbsolutePath() + " is too big");
Throwable pending = null;
FileInputStream in = null;
final byte buffer[] = new byte[(int) file.length()];
try {
in = new FileInputStream(file);
in.read(buffer);
} catch (Exception e) {
pending = new RuntimeException("Exception occured on reading file "
+ file.getAbsolutePath(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
if (pending == null) {
pending = new RuntimeException(
"Exception occured on closing file"
+ file.getAbsolutePath(), e);
}
}
}
if (pending != null) {
throw new RuntimeException(pending);
}
}
return buffer;
}
public static byte[] readBytes(InputStream inputStream) throws IOException {
byte[] buffer = new byte[32 * 1024];
int bufferSize = 0;
for (;;) {
int read = inputStream.read(buffer, bufferSize, buffer.length - bufferSize);
if (read == -1) {
return Arrays.copyOf(buffer, bufferSize);
}
bufferSize += read;
if (bufferSize == buffer.length) {
buffer = Arrays.copyOf(buffer, bufferSize * 2);
}
}
}
Một cách khác để đọc byte từ tệp
Reader reader = null;
try {
reader = new FileReader(file);
char buf[] = new char[8192];
int len;
StringBuilder s = new StringBuilder();
while ((len = reader.read(buf)) >= 0) {
s.append(buf, 0, len);
byte[] byteArray = s.toString().getBytes();
}
} catch(FileNotFoundException ex) {
} catch(IOException e) {
}
finally {
if (reader != null) {
reader.close();
}
}
//The file that you wanna convert into byte[]
File file=new File("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4");
FileInputStream fileInputStream=new FileInputStream(file);
byte[] data=new byte[(int) file.length()];
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);
//Now the bytes of the file are contain in the "byte[] data"
Thử cái này :
import sun.misc.IOUtils;
import java.io.IOException;
try {
String path="";
InputStream inputStream=new FileInputStream(path);
byte[] data=IOUtils.readFully(inputStream,-1,false);
}
catch (IOException e) {
System.out.println(e);
}
Trong JDK8
Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();