我一直在寻找答案,但实际上找不到任何东西。今天早些时候,我问我如何通过字节数组将文件转换为字符串,然后再返回,以便稍后检索。
人们告诉我的是,我必须只存储字节数组,以避免讨厌的编码问题。所以现在我已经开始研究这个了,但我现在已经碰壁了。
基本上,我之前使用过无缓冲的流,将文件转换为字节数组。这在理论上很好用,但它会占用大量内存,最终会导致堆大小异常。我应该使用缓冲流(或者我被告知),而我现在遇到的问题是从BufferedInputStream到byte []。我试图复制并使用本文档中的方法
我在哪里交换缓冲流的无缓冲流。唯一的问题是,我不能直接将缓冲的输出流转换为字节数组,就像我可以使用无缓冲的流一样。
帮助? :)
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public final class BufferedByteStream {
private static final int BUF_SIZE = 1024000;
public static long copy(BufferedInputStream from, BufferedOutputStream to) throws IOException {
byte[] buf = new byte[BUF_SIZE];
long total = 0;
while(true) {
int r = from.read(buf);
if(r == -1) {
break;
}
to.write(buf, 0, r);
total += r;
}
return total;
}
public static byte[] toByteArray(BufferedInputStream in) throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new ByteArrayOutputStream());
copy(in, out);
return out. // <--- Problem is here
}
}
编辑:
我仍然遇到堆空间错误。所以我现在发布所有代码:
main.java
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jserver.io.BufferedByteStream;
/**
*
* @author Vipar
*/
public class main {
public static void main(String[] args) {
File f = new File("<doesn't matter>");
try {
byte[] buf;
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f))) {
buf = BufferedByteStream.toByteArray(bis);
bis.close();
}
File f2 = new File("<doesn't matter>");
try (FileOutputStream fos = new FileOutputStream(f2)) {
fos.write(buf);
fos.close();
}
} catch (FileNotFoundException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
BufferedByteStream.java
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public final class BufferedByteStream {
private static final int BUF_SIZE = 1024000;
public static long copy(BufferedInputStream from, BufferedOutputStream to) throws IOException {
byte[] buf = new byte[BUF_SIZE];
long total = 0;
while(true) {
int r = from.read(buf);
if(r == -1) {
break;
}
to.write(buf, 0, r);
total += r;
}
return total;
}
public static byte[] toByteArray(BufferedInputStream in) throws IOException {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
BufferedOutputStream out = new BufferedOutputStream(bytesOut);
copy(in, out);
return bytesOut.toByteArray();
}
}
答案 0 :(得分:10)
看看ByteArrayOutputStream: Java 7 API java.io.ByteArrayOutputStream
bytesOut = new ByteArrayOutputStream();
byte[] bytes = bytesOut.toByteArray();
更新: 如果你坚持做你正在做的事情,你可以将中间的ByteArrayOutputStream分配给一个变量并以这种方式获取数组:
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream()
BufferedOutputStream out = new BufferedOutputStream(bytesOut);
copy(in, out);
return bytesOut.toByteArray();
更新2: 真正的问题似乎是如何复制文件而不首先将其全部读入内存:
1)手动:
byte[] buff = new byte[64*1024]; //or some size, can try out different sizes for performance
BufferedInputStream in = new BufferedInputStream(new FileInputStream("fromFile"));
BufferedOutputStream out = new BufferedOutputStream(new FileoutputStream("toFile"));
int n = 0;
while ((n = in.read(buff)) >= 0) {
out.write(buff, 0, n);
}
in.close();
out.close();
2)操作系统有效且没有循环等:
FileChannel from = new FileInputStream(sourceFile).getChannel();
FileChanngel to = new FileOutputStream(destFile).getChannel();
to.transferFrom(from, 0, from.size());
//or from.transferTo(0, from.size(), to);
from.close();
to.close();
3) 如果你有Java 7,你可以简化异常和流关闭,或者只是用java 7中的新API复制文件:
java.nio.file.Files.copy(...);
答案 1 :(得分:-1)
DataFetcher非常适合:
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/DataFetcher.java?revision=34&view=markup
如果内存不足,可以使用clearBuffer清除读取之间的缓冲区
您还需要Timeout类 - 它位于同一个包中的同一个项目中。