アプリ版:「スタンプのみでお礼する」機能のリリースについて

いつもお世話になっています。
数GB単位のファイルデータを送受信するプログラムを作っています。

途中で受信が途切れても、途切れたとこから受信できるようにしたいと思います。
(途中からの受信不可のは組めました)

そこで以下のように考えました。(4MBごとに送信しています)
ファイル名受信
→ファイルが存在したら、ファイルサイズ取得
→ファイルサイズを4MBで割った商を求める。
→fseek( fp, 求めた商×4MB, SEK_SET)で書き込み始める場所を設定する

しかし、ファイルを開くタイプで、”wb”だと、ファイルは開いた瞬間に空になりますし、"ab"だと追加書き込みで消すことができません。

どうしたら、途中からデータを上書きすることができるのでしょうか?

A 回答 (9件)

>しかし、ファイルを開くタイプで、”wb”だと、ファイルは開いた瞬間に空になりますし、"ab"だと追加書き込みで消すことができません。



"ab"でオープンした後、fseek()で移動させる。
でしょうかね。
ただし、Windowsの方ではファイルサイズを「切り詰める」のは難しそうです。
# APIならある…みたいですが。
切り詰めるのではなく、上書きするのであればfseek()で移動した後にそのままfwrite()で書き込んでいけばよいでしょう。
# fwrite()での上書きが元ファイルのサイズより小さい場合は後ろに意図しないゴミが残ることになるでしょうけど。

他の方法としては…
別名で新たにファイルを作成して必要な分だけ元ファイルから読み込んで新しいファイルに書き出す。
とかでしょうか。
コピーが終わった後で元ファイルは削除することになりますが。

この回答への補足

>切り詰めるのではなく、上書きするのであればfseek()で移動した後にそのまま>fwrite()で書き込んでいけばよいでしょう。
最初にやってみたのですが、
># fwrite()での上書きが元ファイルのサイズより小さい場合は後ろに意図しないゴミが残ることになるでしょうけど。
まさにこの状況でした。

>別名で新たにファイルを作成して必要な分だけ元ファイルから読み込んで新しいファイルに書き出す。
やっぱりその方が確実ですよね・・・・

補足日時:2012/03/23 17:32
    • good
    • 0

"rb+"では駄目でしたか?

この回答への補足

いえ、やってみたこと無いです。
やってみます

補足日時:2012/03/23 17:33
    • good
    • 0
この回答へのお礼

ベストアンサーをどの方にするか悩みましたが、質問の答えとして一番適していると思われ、かつ一番最初にお答えいただいたduke_kimuraさんにしようと思います。
みなさんありがとうございました

お礼日時:2012/03/27 14:16

>数GB単位のファイルデータを



保存しようとしているファイルシステムによっては問題起こすこともあるのでご注意を。
ランタイムライブラリの方は…どうでしたかねぇ。
# 2Gを越える場合は_fseeki64()とかになる場合も。

ゲームのデータファイルで1ファイルが2G越えるとかは…ちょっと遠慮して頂きたいところではありますけどねぇ。
# もう少し分割するなりして管理すべき…でしょうし。

この回答への補足

>ゲームのデータファイルで1ファイルが2G越えるとかは…ちょっと遠慮して頂き>たいところではありますけどねぇ。
ゲームに限った話ではないんです。動画とかetc
まとめて圧縮ファイルにしてあるのですが、中身を一つずつ送るのも面倒ですし・・・・・

補足日時:2012/03/23 17:39
    • good
    • 0

fopen のモードを適切に選べばいいだけなんだけど....



ど~いうロジックで組んだら「途中からデータを上書きする」必要があるんだろう.

この回答への補足

4MBを一発で受信できるとは限らないので、
途中で回線が落ちたとかした場合、最後に保存されたデータが4MBに満たない可能性があるからです。
完全に続きから、というのは面倒だったので、いっそのこと最後の端数は再受信しなおそうかと

補足日時:2012/03/23 17:42
    • good
    • 0

ファイルタイプは、多分、r+b



たとえば、「ファイルを開くタイプ」で困ったら、fopen() のマニュアルを確認するような癖をつけておくと、幸せになれるかもしれません。

この回答への補足

一応、質問する前にこのサイト(http://www9.plala.or.jp/sgwr-t/c/sec17.html)で確認したのですが
w・a・w+・a+しか見てませんでした・・・・・
rは読み込みだからr+は脳内で勝手に(思い込みで)認識されなかったんじゃ・・・・

補足日時:2012/03/24 07:39
    • good
    • 0

「正しく受信できたデータのみがファイルに書き込まれている」という条件さえ成り立っていれば, 「追加する」だけでできるはず.

この回答への補足

なるほど。4MBを受信しきってから書き込めばいいんですね

補足日時:2012/03/24 07:36
    • good
    • 0

>4MBを一発で受信できるとは限らないので、


>途中で回線が落ちたとかした場合、最後に保存されたデータが4MBに満たない可能性があるからです。

私なら4Mには設定しませんね…。
16kか32k、せいぜい64kくらいでしょうかね。
回線が速いとしても。
# LAN内しか想定しないのであれば、もう少し増やすかも知れませんが。

この回答への補足

インターネットを介して遠方の友人に送るつもりです。
>16kか32k、せいぜい64kくらいでしょうかね。
多ければいいと思っていました。
一番いいのは16kでしょうか?

補足日時:2012/03/25 07:20
    • good
    • 0

rb+でオープンすれば、やりたいことはできると思いますが、


他の方も言っているとおり、通常追記だけで十分なように仕様を作った方がよいです。

レジューム機能を実現したいなら、
4MBとか区切りじゃなくても継続して受信できるように
接続時の初期化を工夫したほうがいいですよ。
送受信独自のアプリっぽいですし?

ところで、途中から始めるときにハッシュ値の採取してますか?
途中だからと言って前回と今回のファイルの内容が同じとは限りませんよ。

この回答への補足

>レジューム機能を実現したいなら、
日曜プログラマ程度ですし、友達にSkype使うより早く大容量データを送りたいというだけなので、難しい話は極力回避したいです。

>途中だからと言って前回と今回のファイルの内容が同じとは限りませんよ
え・・・・そうなんですか?ハッシュ値についてネットで調べてみましたが良く分かりませんでした・・・・・

補足日時:2012/03/25 07:54
    • good
    • 0

>>途中だからと言って前回と今回のファイルの内容が同じとは限りませんよ


>え・・・・そうなんですか?ハッシュ値についてネットで調べてみましたが良く分かりませんでした・・・・・

その受信途中のファイルのファイル名を削除して
別のファイルを、そのファイル名にする。
とかされない保証はどこにもありませんから。

この回答への補足

>その受信途中のファイルのファイル名を削除して
>別のファイルを、そのファイル名にする。
>とかされない保証はどこにもありませんから。

なるほど。相手は友達ですし、そういうことはしないように頼むことにします。

補足日時:2012/03/26 15:02
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!