DOBON.NET DOBON.NETプログラミング掲示板過去ログ

HttpWebRequestとHttpWebResponseを使った方法でプログレスバーの表示(コンソール)

環境/言語:[C#.NET 3.0]
分類:[.NET]

http://dobon.net/vb/dotnet/internet/webrequestpost.html#multipart
のHttpWebRequestとHttpWebResponseを使った方法で、
送信するファイルが比較的大きめなので(40MB程度)プログレスバーを表示させようかと考えています。
ただし、コンソールアプリケーションのため
|====================| のような形で5%刻みに=を増やすようなことを思いつきました。
できれば|====================| 50% 500KB/s
などとパーセント表示とアップロード速度も計りたいのですが、どのようにやればいいのでしょうか。
アップロード速度はありませんが、
サンプルコードのwhile文付近に
System.IO.FileInfo fi = new System.IO.FileInfo(@"C:\picture.jpg");
double filebyte = fi.Length;
double loop = 1 / filebyte;
double percent;
Console.Write("|");
while(true)
{
percent = loop * i;
if (Math.Floor(loop % 5) == 0)
Console.Write("=");
Console.WriteLine(Math.Floor(percent).ToString("P"));
readSize = fs.Read(readData, 0, readData.Length);
if (readSize == 0)
break;
reqStream.Write(readData, 0, readSize);
i++;
}
Console.WriteLine("|");
fs.Close();
reqStream.Write(endData, 0, endData.Length);
reqStream.Close();
というものを書いてみました。
このソースコードだとloopが溢れてしまい、溢れていない場合でも常に0.00%と異常です。どのように直せばよいですか?

しかも、これだと
|=5%=10%=15%・・・=100%|
となってしまいます。
最初に|(半角スペースx20)| 0% と先に表示しておいて、
|=(半角スペースx19)| 5% と新しく表示せずに書き換える方法はないですか?
|==(半角スペースx18)| 10% 500KB/s
> percent = loop * i;
この式明らかにおかしいですよね? ループ回数じゃなくて書き込んだバイト数に比例するものですから。それに loop * ファイルサイズでようやく 1 になるわけで、ループカウンタごときをいくら掛けたところでほぼ 0 でしょう。
wroteSize をループの外に置き、ループごとに readSize を加算、んで wroteSize からファイルサイズを割って 100 掛けたのが読み込み済み(で書き込んだ)パーセンテージになるでしょう。
変数の名前が悪かったです。
ループ回数はiだと思います。
loopというのは1/ファイルのサイズ(byte)です。
8byteなら1/8で0.125になり、iがまだ0なので
0.125 * 0 ということになりまだ0%です。
もう1度ループすると
0.125 * 1 で小数以下切捨てになり12%と表示されます。
さらにループすると
0.125 * 2 で25%になると思うのですが。
■No25907に返信(Hongliangさんの記事)
>>percent = loop * i;
> この式明らかにおかしいですよね? ループ回数じゃなくて書き込んだバイト数に比例するものですから。それに loop * ファイルサイズでようやく 1 になるわけで、ループカウンタごときをいくら掛けたところでほぼ 0 でしょう。
> wroteSize をループの外に置き、ループごとに readSize を加算、んで wroteSize からファイルサイズを割って 100 掛けたのが読み込み済み(で書き込んだ)パーセンテージになるでしょう。
変数名が不適当なのは確かですが、解釈は私の前のレスに書いたもので正しいようです。
> 8byteなら1/8で0.125になり、iがまだ0なので
> 0.125 * 0 ということになりまだ0%です。
> もう1度ループすると
> 0.125 * 1 で小数以下切捨てになり12%と表示されます。
> さらにループすると
> 0.125 * 2 で25%になると思うのですが。
ループをファイルサイズ回繰り返すのですか? つまり一回のループで 1 バイトしか読み書きしないのでしょうか?
8 バイトのファイルなら、8 バイトまとめて読み取って 8 バイトまとめて書き込みますよね?
もう少し分かりやすくするため、8 バイトのファイルを 4 バイトずつ読み書きすることを考えましょう。
ループ 1 回目、4 バイト読み取って書き込みます。0.125 にループ回数を掛けると 0.125 。8 バイト中 4 バイトを読み書きしたのに 12 % しか進んでないことになります。実際には 50 % ですよね?
また loop はファイルサイズに対して一定の数値ですから、loop % 5 は何回ループしようと常に同じ値を返すことになります。loop は最大 1 ですから loop % 5 も最大 1 しか返しませんけど。
ステップを行って、自分の予想通りの動きをするか確認しましょうよ。
これじゃデバッグを他人に任せてるようなものですよ。

小数点の変数にMath.Floorもどうかと思いますし。
2009/11/25(Wed) 12:52:40 編集(投稿者)

Hongliangさん
>変数名が不適当なのは確かですが、解釈は私の前のレスに書いたもので正しいようです。
そのようですね。失礼致しました。
>ループをファイルサイズ回繰り返すのですか? つまり一回のループで 1 バイトしか読み書きしないのでしょうか?
>8 バイトのファイルなら、8 バイトまとめて読み取って 8 バイトまとめて書き込みますよね?
>もう少し分かりやすくするため、8 バイトのファイルを 4 バイトずつ読み書きすることを考えましょう。
>ループ 1 回目、4 バイト読み取って書き込みます。0.125 にループ回数を掛けると 0.125 。8 バイト中 4 バイトを読み書きしたのに 12 % しか進んでないことになります。実際には 50 % ですよね?
単純にwhileのカウントではいけないことは分かりました。では書き込んだバイト数をチェックするにはどうすればいいのでしょうか。
if (readSize == 0)
break;
をみて分かるとおり、readSizeは減っていくものです。
ループごとにreadSizeを加算 とはどうするのですか?
>また loop はファイルサイズに対して一定の数値ですから、loop % 5 は何回ループしようと常に同じ値を返すことになります。loop は最大 1 ですから loop % 5 も最大 1 しか返しませんけど。
気づきませんでした。たしかに一定の数値ですね。

ヴァンさん
>ステップを行って、自分の予想通りの動きをするか確認しましょうよ。
>これじゃデバッグを他人に任せてるようなものですよ。
そうですね。ステップを行ってみます。

>小数点の変数にMath.Floorもどうかと思いますし。
これは見やすさを優先してこの結果になりました。12.5%と出るのと12%と出るのでは違いますので。

DOBON.NET | プログラミング道 | プログラミング掲示板