大きなファイルのアップロードとダウンロードの中間スループットを測定する必要があります ( Apache Commons Net APIを使用した FTP 経由)。
ダウンロード: (問題ありません)
次のようなコードを使用するダウンロードにはすべて問題ありません。
InputStream is = ftp.retrieveFileStream(filePath);
byte[] buffer = new byte[256 * 1024];
int read;
while ((read = is.read(buffer, 0, buffer.length)) != -1) {
Log.v(TAG, "Read = " + read);
}
ここでは、バッファのサイズは 256 KB で、ダウンロードされるファイルの合計サイズは 1 MB です。それでも、個々の呼び出しis.read()
は約 2 KB しか返しません。この場合、バッファがいっぱいになるまでread()
ブロックしません。これにより、中間のダウンロード スループットを測定できます。ここまでは順調ですね。
アップロード: (問題あり)
今、痛みが来ます。に書き込むために同様のサイズのバッファを割り当てると、256 KB 全体が書き込まれるまでOutputStream
呼び出しがブロックされます。write()
write()
ブロックしないのに、ブロックするだけなのはなぜread()
ですか?
ということで使ってみましたnio
。の write()とは異なりOutputstream
、 の write() メソッドはWritableByteChannel
、実際に書き込まれたバイト数を返します。だから、それはノンブロッキングでなければなりませんよね?そのような幸運はありません。これwrite()
も、バッファ全体が書き込まれるまでブロックされます。コードは次のとおりです。
byte[] buffer = new byte[256 * 1024];
new Random.nextBytes(byteArray);
OutputStream os = ftp.storeFileStream(filePath);
WritableByteChannel channel = Channels.newChannel(os);
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
int written = channel.write(byteBuffer);
では、アップロードがブロックされているときに中間スループットを測定するにはどうすればよいでしょうか?
1 つの方法は、Android のTrafficStats
APIを使用することです。しかし、それには独自の一連のフラストレーションが伴います。ドキュメントによると、これらの統計はすべてのプラットフォームで利用できるわけではありません。また、整数カウンター オーバーフロー (2GB 以降) や、3G と Wifi を切り替える際の一部のプラットフォームでのカウンター リセット バグ などのシナリオの処理も必要です。
誰かが抜け道を教えてくれますか?