gpt4 book ai didi

java - 在较大的文件上出现 java.lang.OutOfMemoryError

转载 作者:行者123 更新时间:2023-12-01 17:30:44 28 4
gpt4 key购买 nike

我正在尝试将大文件发送到我的服务器,但出现错误:java.lang.OutOfMemoryError:无法分配 268435468 字节分配,其中包含 33554432 可用字节和 100MB,直至 OOM。尽管如果我尝试使用小文件,那么一切都会很好。

这是我的代码:

public static byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];

int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}

return byteBuffer.toByteArray();


}

上传功能

public static void uploadPDF(final String pdfname, Uri pdffile, String title, String photo, Context context, String ids){
InputStream iStream;
try {
iStream = context.getContentResolver().openInputStream(pdffile);
assert iStream != null;
final byte[] inputData = getBytes(iStream);

VolleyMultipartRequest volleyMultipartRequest = new VolleyMultipartRequest(Request.Method.POST, upload_URL,
response -> {
rQueue.getCache().clear();
try {
JSONObject jsonObject = new JSONObject(new String(response.data));

} catch (JSONException e) {
e.printStackTrace();
}
},
error -> Toast.makeText(context, error.getMessage(), Toast.LENGTH_SHORT).show()) {

@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("ids", ids);
params.put("title", title);
params.put("photo", photo);
return params;
}

@Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
params.put("filename", new DataPart(pdfname ,inputData));
return params;
}
};


volleyMultipartRequest.setRetryPolicy(new DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rQueue = Volley.newRequestQueue(context);
rQueue.add(volleyMultipartRequest);



} catch (IOException e) {
e.printStackTrace();
}
<小时/>
public class VolleyMultipartRequest extends Request<NetworkResponse> {

private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();

private Response.Listener<NetworkResponse> mListener;
private Response.ErrorListener mErrorListener;
private Map<String, String> mHeaders;


public VolleyMultipartRequest(int method, String url,
Response.Listener<NetworkResponse> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders != null) ? mHeaders : super.getHeaders();
}

@Override
public String getBodyContentType() {
return "multipart/form-data;boundary=" + boundary;
}

@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);

try {
// populate text payload
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
textParse(dos, params, getParamsEncoding());
}

// populate data byte payload
Map<String, DataPart> data = getByteData();
if (data != null && data.size() > 0) {
dataParse(dos, data);
}

// close multipart form data after text and file data
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* Custom method handle data payload.
*
* @return Map data part label with data byte
* @throws AuthFailureError
*/
protected Map<String, DataPart> getByteData() throws AuthFailureError {
return null;
}

@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(
response,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}

@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}

@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}

/**
* Parse string map into data output stream by key and value.
*
* @param dataOutputStream data output stream handle string parsing
* @param params string inputs collection
* @param encoding encode the inputs, default UTF-8
* @throws IOException
*/
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
}
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + encoding, uee);
}
}

/**
* Parse data into data output stream.
*
* @param dataOutputStream data output stream handle file attachment
* @param data loop through data
* @throws IOException
*/
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
for (Map.Entry<String, DataPart> entry : data.entrySet()) {
buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
}
}

/**
* Write string data into header and data output stream.
*
* @param dataOutputStream data output stream handle string parsing
* @param parameterName name of input
* @param parameterValue value of input
* @throws IOException
*/
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(parameterValue + lineEnd);
}

/**
* Write data file into header and data output stream.
*
* @param dataOutputStream data output stream handle data parsing
* @param dataFile data byte as DataPart from collection
* @param inputName name of data input
* @throws IOException
*/
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
}
dataOutputStream.writeBytes(lineEnd);

ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
int bytesAvailable = fileInputStream.available();

int maxBufferSize = 1024 * 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];

int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

dataOutputStream.writeBytes(lineEnd);
}

public class DataPart {
private String fileName;
private byte[] content;
private String type;

public DataPart() {
}

public DataPart(String name, byte[] data) {
fileName = name;
content = data;
}

String getFileName() {
return fileName;
}

byte[] getContent() {
return content;
}

String getType() {
return type;
}

}
}

此行发生错误:

  byteBuffer.write(buffer, 0, len);

最佳答案

输入流为您提供了太多数据,无法将其保存在 RAM 中。

选项 1:

在读取文件的同时处理数据(在循环中)

选项 2:

将其保存到文件并从文件中处理它,而不将整个内容加载到 RAM 中。

您可以在文件中来回跳转。

<小时/>

OutOfMemoryError 表示您尝试在堆上分配数据,但您的应用程序没有足够的可用 RAM 来使用。在 32 位设备(很多手机都是)上,这也可能意味着您用完了可寻址空间。

它在写入ByteArrayOutputStream时发生,因为ByteArrayOutoutStream将其内容(字节数组)存储在堆中,并且无法分配足够的空间来增加大小内部字节数组。

关于java - 在较大的文件上出现 java.lang.OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61126294/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com