日記を埋めるためだけのネタつぶし(8)

以前記述した、Javaのデータダウンロードのプログラムの一部に間違いが発覚した。
現行では、VodafoneのSH53と601Tのみでしか、確認をしていないが
ダウンロードの際のreadメソッドが一度で全てのデータを読み込んでくれないという現象だ。
まあ、WinSockなんかでは、結構よくある話ではあるが、InputStreamのreadメソッドの説明は


read
public int read(byte[] b)
throws IOException入力ストリームからバイト数を読み込み、それをバッファ配列 b に格納します。
実際に読み込まれたバイト数は整数として返されます。このメソッドは、入力データが読み込めるようになるか、
ファイルの終わりが検出されるか、あるいは例外がスローされるまでブロックします。
と記述してあったため、ストリームの位置が、一回で終端に来ると思われるのだが
実際は、そのようなことになっていなかった。

以下は、修正しなおしたCHttpクラス


/*!
* @brief 通信クラス
*/
final public class CHttp implements Runnable
{
private boolean ret; //!< 現在の接続状態
private boolean dflg; //!< ダウンロードフラグ
private Exception e; //!< エラー
private HttpConnection hc; //!< コネクト
private String rstr; //!< 返す文字列
private byte[] buf; //!< ダウンロードしたバッファ
private int length; //!< データの長さ
private int size; //!< 読み込んだサイズ
private int offset; //!< バッファのオフセット
private String url; //!< 接続先のURL

/*!
* @brief コンストラク
*/
public CHttp() {
ret = true;
dflg = false;
rstr = new String();
}
/*!
* @brief データの長さを取得
*
* @retval データの長さを返す
*/
public int getLength() {
return length;
}
/*!
* @brief 読み込んだサイズを取得
*
* @retval 読み込んだサイズを返す
*/
public int getSize() {
return size;
}
/*!
* @brief 現在の接続状態
*
* @retval true:接続中
* @retval false:接続終了
*/
public boolean nowConnect() {
return ret;
}
/*!
* @brief エラーコードを取得
*
* @retval エラーコードを返す
* @retval エラーがない場合はnullを返す
*/
public Exception getError() {
return e;
}
/*!
* @brief 文字列を取得
*
* @retval 取得した文字列を返す
*/
public String getString() {
return rstr;
}
/*!
* @brief 接続開始
*
* @param url 接続先のURL
*/
public void connect(String url){
ret = true;
e = null;
dflg = false;
this.url = url;
size = 0;
length = 0;

(new Thread(this)).start();
}
/*!
* @brief 接続開始
*
* @param url 接続先のURL
* @param buf ダウンロードしたデータを受け取るバッファ
*/
public void connect(String url, byte[] buf, int off){
ret = true;
e = null;
dflg = true;
this.url = url;
this.buf = buf;
size = 0;
length = 0;
offset = off;

(new Thread(this)).start();
}
/*!
* @brief 接続中
*/
public void run(){
InputStream is = null;
try {
#if (DOCOMO)
hc = (HttpConnection)Connector.open(url, Connector.READ, true);
hc.setRequestMethod(HttpConnection.GET);
hc.connect();
#elif (VODAFONE)
hc = (HttpConnection)Connector.open(url, Connector.READ);
hc.setRequestMethod(HttpConnection.GET);
#endif

if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
length = (int)hc.getLength();
if (length > 0) {
is = hc.openInputStream();
if (dflg == true) {
// データのダウンロード
size = 0;
int ret;
while ((ret = is.read(buf, offset, (buf.length - offset))) != -1) {
if (ret != -1) {
size += ret;
offset += ret;
if (size >= length || offset >= buf.length) {
break;
}
}
}
} else {
// 文字列取得
InputStreamReader reader = null;
StringBuffer stBuffer = new StringBuffer();
char[] readChars = new char[256];
int readLeng;

reader = new InputStreamReader(is);
while ( (readLeng = reader.read(readChars, 0, readChars.length) ) != -1){
//処理
stBuffer.append(readChars, 0, readLeng);
}
rstr = stBuffer.toString();
}
}
} else {
this.e = new Exception("ResponseCode:" + hc.getResponseCode());
var(e);
}
} catch(Exception e) {
this.e = e;
var(e);
} finally {
try {
is.close();
} catch(Exception e2) {
}
try {
hc.close();
} catch(Exception e2) {
}
}
ret = false;
}
};