サンプル(NG)
import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public abstract class Main { // ★ここは自分で書き直してください★ private static final String InputData = "http://k.yimg.jp/images/top/sp2/cmn/logo-ns-131205.png"; private static final String OutputData = "C:\\Temp\\yahoobloglogo.png"; public static void main(String[] args) { try { URL url = new URL(InputData); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // false の場合、ユーザーとの対話処理は許可されていません。 connection.setAllowUserInteraction(false); // true の場合、プロトコルは自動的にリダイレクトに従います connection.setInstanceFollowRedirects(true); // URL 要求のメソッドを"GET"に設定 connection.setRequestMethod("GET"); connection.connect(); // HTTP 応答メッセージから状態コードを取得します int httpStatusCode = connection.getResponseCode(); if (httpStatusCode != HttpURLConnection.HTTP_OK) { throw new Exception(); } try (DataInputStream inputStream = new DataInputStream( connection.getInputStream()); DataOutputStream outputStream = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(OutputData)))) { writeStream(inputStream, outputStream); } catch (Exception ex) { ex.printStackTrace(); } System.out.println("Completed!!"); } catch (Exception ex) { ex.printStackTrace(); } } private static void writeStream(InputStream inputStream, OutputStream outputStream) throws IOException { int availableByteNumber; // ★ここも問題があった★ while ((availableByteNumber = inputStream.available()) > 0) { byte[] buffers = new byte[availableByteNumber]; int readByteNumber = inputStream.read(buffers); if (readByteNumber < 0) { break; } outputStream.write(buffers, 0, readByteNumber); } } }
原因
* InputStream.available()で、0Byteを返していたため。http://stackoverflow.com/questions/23161119/urlconnection-returning-empty-inputstream
によると、 「InputStream.available() がブロックせずに、全てデータが入手できるまで待ちます。 そして、InputStream.available()を呼び出した時には完全に受信できていないかもしれません」
Java API/ クラス InputStream
https://docs.oracle.com/javase/jp/6/api/java/io/InputStream.html#available()解決策
* InputStream.available() を使用せずに実装する。 ~~~ int availableByteNumber; byte[] buffers = new byte[100000]; while((availableByteNumber= dataInputStream.read(buffers)) > 0){ // Do something here with buffer } ~~~
サンプル(OK)
http://blogs.yahoo.co.jp/dk521123/34362429.htmlに載っているが
// 略 private static void writeStream(InputStream inputStream, String outputPath) throws Exception { int availableByteNumber; byte[] buffers = new byte[100000]; try (DataInputStream dataInputStream = new DataInputStream(inputStream); DataOutputStream outputStream = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(outputPath)))) { while ((availableByteNumber = dataInputStream.read(buffers)) > 0) { outputStream.write(buffers, 0, availableByteNumber); } } catch (Exception ex) { throw ex; } }