最初のナイーブ バージョン:ファイルをローカル バッファーにロードします。次に、入力の長さがわかります。次に、バッファーから XML を解析します。
URL url = new URL("...");
InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream buffer1 = new ByteArrayOutputStream();
int c = 0;
while((c = in.read()) >= 0) {
buffer1.write(c);
}
System.out.println(String.format("Length in Bytes: %d",
buffer1.toByteArray().length));
ByteArrayInputStream buffer2 = new ByteArrayInputStream(buffer1.toByteArray());
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(buffer2);
欠点は、RAM の追加バッファです。
より洗練された 2 番目のバージョン:java.io.FilterInputStream
入力ストリームを、それを介してストリーミングされるバイト数をカウントするカスタムでラップします。
URL url = new URL("...");
CountInputStream in = new CountInputStream(url.openStream());
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
System.out.println(String.format("Bytes: %d", in.getCount()));
これがCountInputStream
です。すべてのread()
メソッドが上書きされ、スーパー クラスにデリゲートされ、結果のバイト数がカウントされます。
public class CountInputStream extends FilterInputStream {
private long count = 0L;
public CountInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
final int c = super.read();
if(c >= 0) {
count++;
}
return c;
}
public int read(byte[] b, int off, int len) throws IOException {
final int bytesRead = super.read(b, off, len);
if(bytesRead > 0) {
count += bytesRead;
}
return bytesRead;
}
public int read(byte[] b) throws IOException {
final int bytesRead = super.read(b);
if(bytesRead > 0) {
count += bytesRead;
}
return bytesRead;
}
public long getCount() {
return count;
}
}