現在cを勉強中なのですがファイル入出力に関して質問があります。
たとえばint型の2つの要素を持つ構造体
typedef struct{
int first,second;
}ex;
のex型の変数 datをFILE *fpにfwriteで書き込むとすると
fwrite(&dat,sizeof(ex),1,fp);
と書きますよね。書き込まれる位置はr+モードならファイルポインタの位置から上書き、aなら末尾から追加です。今データは残しておきたいのでwモードは考えていません。
ここで質問なのですが末尾ではなく任意のファイルポインタの位置から追加で書き込んだり、ある特定のレコードを削除したりと言う操作は不可能なのでしょうか?
今のところ、削除については削除したマークをつける方法、レコードの追加についてはテンポラリファイルに追加する前までのレコードをコピーして追加したいレコードを書いてそのあとに残りのデータをコピーした後テンポラリファイルの名前を変える、ということが考えられるのですがもっと効率のよい方法はないのでしょうか?
よろしくお願いします。cで無理ならc++でもかまいません。
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
回答としては、
「現在のWindows・Unixの標準のファイルシステムにはそのような機能がありませんし、CやC++の標準入出力機能においては、そのような操作を想定していないので、不可能です。」
となります。
データベースシステムは、データベースファイル上に専用のファイルシステムを構築しています。
また、そのような追加削除に対応した汎用のファイルシステムを作る試みもあるようです。
しかし、どちらのケースにおいてもその場合はCまたはC++で標準で定義されている低水準の入出力関数とは別の低水準の入出力関数を用意してそこを経由してアクセスすることになります。
当然、CやC++の標準入出力の互換機能を用意したとしても、標準入出力の関数そのものにそのような機能はありませんので、中間に追加する機能や中間部分を削除する機能は結局別の関数を作成して標準ライブラリを拡張する必要があるでしょう。
ここからは蛇足ですが、多分、実際に実装するとなると、以下のようになるのではないでしょうか。
POSIX.1では、低水準入出力関数として
int open(char *filename, int flags, ...);
off_t lseek(int fd, off_t offset, int whence);
int read(int fd, void *buf, size_t nbytes);
int write(int fd, void *buf, size_t nbytes);
void close(int fd);
が定義されています。
ここに
int insert(int fd, void *buf, size_t nbytes);
→ファイルディスクリプタfdで示される現在のファイルの現在のファイル位置にnbytesのデータをbufから挿入する。挿入できたバイト数を返す。エラーの場合は-1を返し、errnoをセットする。
int delete(int fd, size_t nbytes);
→ファイルディスクリプタfdで示される現在のファイルの現在のファイル位置からnbytesのデータを削除する。削除できたバイト数を返す。エラーの場合は-1を返し、errnoをセットする。
という風な関数を追加するような形になると思います。
これをさらに
size_t finsert(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fdelete(size_t size, size_t nmemb, FILE *stream);
という感じで高水準入出力としてラップ関数を用意することになるでしょう。
でも現実にはそのようなファイルシステムは普及していませんね。確かにあると便利かもしれません。
No.1
- 回答日時:
>末尾ではなく任意のファイルポインタの位置から追加で書き込んだり、ある特定のレコードを削除したりと言う操作は不可能なのでしょうか?
ファイルストリームと言われるように、CやC++で扱うファイルはシーケンシャルなものですから、途中に追加したり、一部分だけを削除(して繰り上がる)ということはできません。(そういうことを実現しようとすると結局全ての部分の移動(アクセス)が必要になります。
そういうのが望ましくない場合は、ISAMファイルみたいなものを扱うようにするか、DBにしてしまうしかないと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
- Excel(エクセル) 1つのファイルを3つのフォルダにファイル名を【明日の日付】にして、コピーをしたい 2 2022/12/21 17:43
- Visual Basic(VBA) 複数ブックの統合について Excel VBA 1 2022/05/13 09:48
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- その他(データベース) c言語の問題です。これを踏まえてコーディングしたいのでおしえていただきたいです。 3 2023/08/03 09:27
- Excel(エクセル) マクロの付いたExcelが開けません 3 2023/02/01 10:54
- ドメイン・サーバー・クラウドサービス 独自ドメインでのNSレコード設定 1 2023/07/12 18:36
- その他(プログラミング・Web制作) Windowsのマクロプログラムで、こんなことできますか? 3 2022/06/28 14:30
- Visual Basic(VBA) 複数ファイルのデータの統合について 12 2022/05/14 12:03
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「指定されたキャストは有効で...
-
比較回数と交換回数表示について
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
#define _CRT_SECURE_NO_WARNIN...
-
std::set<int> で、ある値が何...
-
C言語で三目並べをするプログラ...
-
商と剰余を同時に求める(C言語)
-
if と配列の組み合わせ
-
【C++】関数ポインタの使い方
-
並列プログラミングのπ計算につ...
-
c言語
-
HANDLEて何ですか?
-
read関数をノンブロッキングで...
-
卒業研究でよく分からないとこ...
-
DLLをGetProcAddress()で実行で...
-
GlobalAllocの変数を関数に引き...
-
シグマ公式・・・C言語
-
ファイルから読みこむ方法
-
c言語の問題です
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
「指定されたキャストは有効で...
-
C言語 配列と関数の練習問題
-
複数桁10進数の*桁目だけを抽出...
-
(int *)の意味
-
if と配列の組み合わせ
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
c言語
-
足して100になるような乱数のア...
-
C言語初心者です、、、お助けく...
-
数字列を3桁ごとにカンマで区切...
-
C言語 エラーの原因がわからな...
-
実数の整数部,小数部の取得
-
課題でつまってます・・・
-
商と剰余を同時に求める(C言語)
-
C言語の配列をC++のvectorに高...
-
std::set<int> で、ある値が何...
おすすめ情報