【发布时间】:2015-06-09 01:20:30
【问题描述】:
我对执行此操作的最佳方法有点困惑。我在这里看到了很多关于 SO 的例子,许多答案都有不同的解决方案。所以我想知道将很长的字符串写入新的 html 文件(即从字符串创建 html 文件)的最有效方法。是否真的更喜欢将所有内容包装到缓冲区中?喜欢:
fileWriter = new FileWriter(new File(dir, appBook.getPath()));
bufferWritter = new BufferedWriter(fileWriter);
bufferWritter.append(htmlContent);
或者我可以这样做(不损失性能)
fileWriter = new FileWriter(new File(dir, appBook.getPath()));
fileWriter .append(htmlContent);
..
这是我已经使用了一段时间的方法:
//Will run out of memory if i dont split the string in 650000 chunks
String[] bookPieces = splitString(htmlContent, Math.round(htmlContent.length()/650000));
OutputStream outputStream = null;
InputStream inputStream = null;
try {
outputStream = new FileOutputStream(new File(dir, appBook.getPath())); //.html path
for (String text : bookPieces) {
byte[] theBytes = text.getBytes(Charset.forName("UTF-16"));
inputStream = new ByteArrayInputStream(theBytes);
byte[] bufferData = new byte[1024];
int bytesRead = inputStream.read(bufferData);
while (bytesRead != -1) {
outputStream.write(bufferData, 0, bytesRead); //add the bufferData data to the "new file"
bytesRead = inputStream.read(bufferData); // keep on reading and filling the dynamic byte araay until it returns -1
}
//need to GC the inputsteam myself!!!!
inputStream = null;
}
toReturn = true;
}
比我读到它更喜欢使用 BufferedReader 来处理长文本字符串。所以我改为:
String[] bookPieces = splitString(htmlContent, Math.round(htmlContent.length()/650000));
OutputStream outputStream = null;
InputStream inputStream = null;
OutputStreamWriter oo;
try {
outputStream = new FileOutputStream(new File(dir, appBook.getPath()));
for (String text : bookPieces) {
byte[] theBytes = text.getBytes(Charset.forName("UTF-16"));
inputStream = new ByteArrayInputStream(theBytes);
InputStreamReader iReader = new InputStreamReader(inputStream,Charset.forName("UTF-16"));
BufferedReader bufferedReader = new BufferedReader(iReader);
oo = new OutputStreamWriter(outputStream);
String nextLine;
while ((nextLine = bufferedReader.readLine())!=null) {
oo.write(nextLine);
}
//need to GC the inputsteam myself!!!!
inputStream = null;
}
但我无法使用该方法正确编码,某些字符会有所不同,例如“-”变成“〔。而且我仍然必须将字符串分成块,所以我看不到更改的目的(我是否以错误的方式执行此操作?请告诉我使用 bufferedReader 的正确方法)。
...而且我终于找到了两种更快的方法,甚至不需要我将字符串分成这么多块。
String[] bookPieces = splitString(htmlContent, Math.round(htmlContent.length()/100));
FileWriter fileWriter = null;
BufferedWriter bufferWritter = null;
try {
fileWriter = new FileWriter(new File(dir, appBook.getPath()));
bufferWritter = new BufferedWriter(fileWriter);
//Has to append, if write than OOM.
bufferWritter.append(htmlContent);
toReturn = true;
}
// 比上面的 Encoding 略慢
//Need to split large strings in 100 chuncks
String[] bookPieces = splitString(htmlContent, Math.round(htmlContent.length()/100));
BufferedWriter bufferWritter = null;
OutputStreamWriter osw= null;
try {
// Create osw and assign it an Encoding
osw = new OutputStreamWriter(
new FileOutputStream(new File(dir, appBook.getPath())),
Charset.forName("UTF-16"));
bufferWritter = new BufferedWriter(osw);
for (String text : bookPieces) {
bufferWritter.write(text); //write faster than append here
}
toReturn = true;
}
【问题讨论】:
-
write()并不比append().快而且您不需要“自己对输入流进行 GC”。它是一个局部变量,在方法退出时会超出范围,并且会自动被 GC 处理。并且清空引用变量并不一定会导致 GC。 -
只是在类似的步骤上阅读您的答案,帮助我将字符串分块:)。如果我不将 inputStream 设为 null,我将收到 OOM 错误:/,因此它必须在某处的堆中徘徊(如果有任何区别,请在 android 手机上运行它)。
-
嗯,我的立场是正确的,只是尝试过并将其设置为 null 并没有任何区别。不过,在此之前,由于某种原因,这个小变化阻止了我离开 OOME,肯定是别的原因。但是,这些方法中的哪一个是最好的。我是否应该将其包装在缓冲区中?
-
你应该总是缓冲。
标签: java inputstream nio bufferedreader filewriter