blob: fda040499a74e432c99ac5fc164b16bf4dfeb95f [file] [log] [blame]
package org.testng.reporters;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Random;
/**
* A string buffer that flushes its content to a temporary file whenever the internal
* string buffer becomes larger than MAX. If the buffer never reaches that size, no file
* is ever created and everything happens in memory, so the overhead compared to
* StringBuffer/StringBuilder is minimal.
*
* Note: calling toString() will force the entire string to be loaded in memory, use
* toWriter() if you need to avoid this.
*
* @author Cedric Beust <cedric@beust.com>
*
* @since Nov 9, 2012
*/
public class FileStringBuffer implements IBuffer {
private static int MAX = 100000;
private static final boolean VERBOSE = System.getProperty("fileStringBuffer") != null;
private File m_file;
private StringBuilder m_sb = new StringBuilder();
private final int m_maxCharacters;
public FileStringBuffer() {
this(MAX);
}
public FileStringBuffer(int maxCharacters) {
m_maxCharacters = maxCharacters;
}
@Override
public FileStringBuffer append(CharSequence s) {
if (m_sb.length() > m_maxCharacters) {
flushToFile();
}
m_sb.append(s);
return this;
}
@Override
public void toWriter(Writer fw) {
try {
BufferedWriter bw = new BufferedWriter(fw);
if (m_file == null) {
bw.write(m_sb.toString());
bw.close();
} else {
flushToFile();
copy(new FileReader(m_file), bw);
}
} catch(IOException ex) {
ex.printStackTrace();
}
}
private static void copy(Reader input, Writer output)
throws IOException {
char[] buf = new char[MAX];
while (true) {
int length = input.read(buf);
if (length < 0) break;
output.write(buf, 0, length);
}
try {
input.close();
} catch (IOException ignore) {
}
try {
output.close();
} catch (IOException ignore) {
}
}
private void flushToFile() {
if (m_sb.length() == 0) return;
if (m_file == null) {
try {
m_file = File.createTempFile("testng", "fileStringBuffer");
m_file.deleteOnExit();
p("Created temp file " + m_file);
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter fw;
try {
p("Size " + m_sb.length() + ", flushing to " + m_file);
fw = new FileWriter(m_file, true /* append */);
fw.append(m_sb);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
m_sb = new StringBuilder();
}
private static void p(String s) {
if (VERBOSE) {
System.out.println("[FileStringBuffer] " + s);
}
}
@Override
public String toString() {
String result = null;
if (m_file != null) {
flushToFile();
try {
result = Files.readFile(m_file);
} catch (IOException e) {
e.printStackTrace();
}
} else {
result = m_sb.toString();
}
return result;
}
private static void save(File expected, String s) throws IOException {
expected.delete();
FileWriter expectedWriter = new FileWriter(expected);
expectedWriter.append(s);
expectedWriter.close();
}
public static void main(String[] args) throws IOException {
String s = "abcdefghijklmnopqrstuvwxyz";
FileStringBuffer fsb = new FileStringBuffer(10);
StringBuilder control = new StringBuilder();
Random r = new Random();
for (int i = 0; i < 1000; i++) {
int start = Math.abs(r.nextInt() % 26);
int length = Math.abs(r.nextInt() % (26 - start));
String fragment = s.substring(start, start + length);
p("... Appending " + fragment);
fsb.append(fragment);
control.append(fragment);
}
File expected = new File("/tmp/expected");
expected.delete();
FileWriter expectedWriter = new FileWriter(expected);
expectedWriter.append(control);
expectedWriter.close();
File actual = new File("/tmp/actual");
actual.delete();
FileWriter actualWriter = new FileWriter(actual);
fsb.toWriter(actualWriter);
actualWriter.close();
// Assert.assertEquals(fsb.toString(), control.toString());
}
}