追加の書き込みなしにファイルに挿入できないのはなぜですか?(私は追加も上書きも意味しません)


8

これは、プログラミング言語に依存しない問題として発生します。

内容のファイルがあります

aaabddd

私がC後ろに挿入したいときはb私のコードを書き直す必要dddがあります

aaabCddd

Cこの位置に挿入できないのはなぜですか?

Java、Pythonなどではできません。Linux、Windowsなどではできません。私は正しいですか?

C追加の書き込みなしに単純に挿入できない理由がわかりません。なぜこれがそうであるのか誰かが説明してくれませんか?


2
2ギガバイトのファイルのバイト128に何かを「挿入」したい場合、ディスクのビットで何が起こるかを考えてください。

間にオペレーティングシステムとファイルシステムがないということですか?その後、それは動作しません。他の2つが配置されていると、なぜ機能しないのかわかりません。
ユーザー

12
ドミノを500個取り、それらを一列に並べます。次に、他の行を移動せずに、その行に1つ挿入してみます。
GrandmasterB

2
私の夢の世界では@MichaelT、あなたがすべき唯一のファイルを構成するブロックの文字列に別のブロックを挿入し、最初の二つのブロックに現在の第1のブロックの内容を配布する必要があります。確かに、これにはファイルシステムの実装者が奇数サイズのブロックを処理する必要がありますが、この操作必要な状況では効率が大幅に向上し、面白くもありません。
キリアンフォス14

1
@Userファイルシステムの断片化の問題とExt4の動作がSuperUserの領域にしっかりと移行します。問題を完全に指定することを忘れないでください。そうしないと、バイトについて再度質問されます。ブロックやファイルシステム、論理ボリュームマネージャーなどについて質問しています。

回答:


8

ほとんどのファイルシステムは、物理ディスク上で必ずしも連続しているわけではないが、ポインター構造を介してリンクされている個々のブロックにファイルの内容を格納するため、このようなモード(「追加」または「上書き」ではなく「挿入」)が必要と思われます。コンテンツ全体を読み取り、バイトストリームを編集して、コンテンツ全体を再書き込みします。

ただし、良くも悪くも、ファイルシステムのUNIXセマンティクスは1970年代の「ラフでシンプルな」パラダイムに沿って設計されました。すべてのことを実行できますが、必ずしも最も効率的な方法ではありません。現在、仮想ファイルシステムレイヤーに新しいファイルオープンモードを導入し、主要なファイルシステムがそれをサポートすることを期待することはほとんど考えられません。これは私のうんざりですが、残念ながらすぐに解決される可能性は低いです。


2
しばらく興味深いサイドプロジェクトになる可能性のあるビルド...
FrustratedWithFormsDesigner 2014

1
ブロックレベルのストレージは、質問をさらに一歩複雑にします。OPの元の例をそのまま使用すると、2つのバージョンの文字列は1つのブロック内に収まるはずです。バイトは順番に書き出される必要があり、そのため、挿入された量だけ文字列の末尾を下にシフトする必要があります。

あなたが挿入するようにしている場合にのみ効率的になり、正確には、1つのブロックに格納できるデータの量を正確に既存の2つのブロック間の境界線。
Idan Arye 14

キリアンフォースは正しい縫い目です。私はこれについて教授に尋ねたところ、彼は私に同じことについて話してくれました。ポータブルインターフェイスに適用するために、挿入を許可するファイルシステムは多くなく、オペレーティングシステムがそれを公開することはあまりありません。@ GlenH7私の質問を編集した2人が、バイトについて尋ねるように見せかけ、説明を元に戻しました。本当の問題は、私たちが使用するインターフェースについてです。
ユーザー

はい、ブロックはポインターを介してリンクされているため、ファイルのコンテンツを連続して保存する必要はありませんが、連続して保存すると、ハードウェアはブロックすることなくブロックを読み取ることができます。ポインターをポインターごとに追跡する必要がある場合、読み取りヘッドは常に移動します。そのため、デフラグはコンピュータの高速化に役立ちます。ファイルのブロックポインターを連続したブロックに配置します。その場合、コマンドはブロック1、ブロック3、ブロック9、ブロック9の読み取りではなく、ブロック1〜nになります。ハードウェアは、それをはるかに効率的に実行できます。
2014

12

理論的には、このようなことを可能にするファイルを実装できます。ただし、最大の柔軟性を得るには、ファイル内のすべてのバイトと共に次のバイトへのポインタを格納する必要があります。64ビットのポインターを想定すると、ファイルの9バイトごとに8つが内部ポインターで構成されることになります。したがって、1000バイトの実際のデータを格納するには、9000バイトのスペースが必要になります。また、ディスクから大きな連続したデータブロックを読み取るのではなく、各バイトを読み取り、ポインターを読み取り、ポインターに従って次のバイトを読み取る必要があるため、ファイルの読み取りも遅くなります。

明らかに、この種のアプローチは実用的ではありません。ただし、ファイルを32 kbブロックなどに分割することもできます。これにより、ファイル内の32 kbの境界に32 kbのデータを追加するのが比較的簡単になります。ファイルの5番目のバイトとして1バイトを追加するのは簡単ではありません。ただし、すべてのブロックにいくらかの空き領域を予約すると、その単一ブロック内のデータにのみ影響するデータの小さな追加が行われる可能性があります。もちろん、ファイルサイズの点でペナルティはありますが、合理的なペナルティになる可能性があります。ただし、予約する領域とブロックを分割する方法を理解することは、特定のアプリケーションでは汎用システムよりもはるかに簡単になる傾向があります。あるコンテキストで機能するものは、ファイルアクセスや修正特性。

実際、ファイルとのやり取りに多くの時間を費やす多くのシステムは、特定のファイル抽象化を実装するときに、上で説明したようなものを実装しています。たとえば、データベースは一般的に、「ブロック」の概念をI / Oの最小単位として実装し、通常、将来の拡張に備えてある程度のスペースを確保するので、テーブルの行を更新すると、ファイル全体を再書き込みするのではなく、そのデータが格納される1つのブロック。もちろん、データベースが異なれば、実装も異なり、トレードオフも異なります。


3
「2ギガバイトのファイルの1ギガバイトにあるブロックを探す」という課題は、リンクされたバイトの実装リストで少し時間がかかる可能性があることについても触れておきます。

挿入時に発生する問題は、ストレージシステムの重複除外を設計する人々の間で多くの混乱を引き起こす問題です。
Blrfl 2014

バイトの話ではなく、全体像について話していることを理解していただきありがとうございます。
ユーザー

8

「問題」は、ファイルがバイト単位でストレージメディアに書き出される方法に要約されます。

最も基本的な表現では、ファイルはディスク(別名ストレージメディア)に書き込まれた一連のバイトにすぎません。したがって、元の文字列は次のようになります。

Address  Value
0x00     `a`
0x01     `a`
0x02     `a`
0x03     `b`
0x04     `d`
0x05     `d`
0x06     `d`

そしてC、位置0x04 に挿入したいとします。これには、新しい値を挿入できるように、バイト4〜6を1バイト下にシフトする必要があります。そうしないと、現在0x04にある値が上書きされてしまい、必要な値が上書きされます。

Address  Value
0x00     `a`
0x01     `a`
0x02     `a`
0x03     `b`
0x04     `C`
0x05     `d`
0x06     `d`
0x07     `d`

したがって、新しい値を挿入した後にファイルの末尾を再書き込みする必要があるのは、挿入された値を受け入れるためのスペースがファイル内にないためです。そうしないと、そこにあったものを上書きします。


補遺1:の値をで置き換えたい場合は、文字列の末尾を書き換える必要ありませ。値を同じサイズの値で置き換える場合、書き換えは必要ありません。bC

補遺2:あなたは、文字列交換したい場合abC、あなたが考えに必要なファイルのギャップを作成してきたように、ファイルの残りの部分を再書き込み。

補遺3:ブロックレベルの構成が作成され、大きなファイルの処理が容易になりました。1M分のファイルの連続したスペースを見つける必要はなく、代わりに1M分のブロックを見つけて書き込むだけで済みます。

理論的には、ブロックが提供するのと同様のバイト単位のリンクを行うファイルシステムを構築できます。次に、|を更新して新しいバイトを挿入できます。適切なポイントのポインタから。私はそれでのパフォーマンスがかなり悪いだろうという推測を危険にさらすでしょう。


グランドマスターBが示唆され、視覚的にファイルがどのように表現されるかを理解するために積み重ねられたドミノの画像を使用しています。

ドミノ

すべてを転倒させることなく、ドミノの行内に別のドミノを挿入することはできません。他の人を線の下に移動して、新しいドミノ用のスペースを作成する必要があります。行の下にドミノを移動することは、挿入ポイントの後にファイルの末尾を書き換えることと同じです。


ab Cとdが文字ではなく、ギガバイトの文字であるとします。あなたの答えでこれに対処できますか?私は絵が好きですが、人々が1000ドミノを2000ドミノに挿入するのは、1ドミノを6ドミノに挿入するのとは異なるアプローチを取ると思います。
ユーザー

@User-バイトの代わりにGBの文字は根本的にあなたの質問の性質を変更し、今ストレージのためのブロックを考慮する必要があります。単純なレベルでは、答えは同じです。スペースを作成せずに、連続する一連の「何でも」内に何かを挿入することはできません。

0

ファイルへの挿入は、潜在的に長期的な「高価な」影響と追加の障害モードを伴う「高価な」(時間を浪費し、スペースを消費する)操作と見なされるため、ほとんどのファイルシステムでは実装されていません。

挿入のセマンティクスを持つファイルシステムは、おそらくshift&insert(大きなファイルの前に挿入すると非常に高価になる可能性がありますが、長期的な副作用はほとんどありません)、または可変長の割り当てサイズを持つ一般的なヒープの割り当て(場合によっては、非常に不適切なパフォーマンス([Stop-the-world GC]の最中にファイルを保存しようとするインタラクティブユーザーの顔を想像してください!))。

実験したい場合は、挿入を実装するJavaまたはPythonでファイルI / O抽象化を簡単に構築できます。あなたが成功し、それが行儀の良いパフォーマンス特性を持っている場合、あなたは優れた研究論文の基礎を持っています。幸運を。


これは、以前の6つの回答に対して実質的なものを提供していないようです
gnat

必要なすべてのソフトウェアを作成できますが、ハードウェアの動作は変わりません。ハードウェアは、ブロック/ページの読み取り/書き込みによって機能します。HDDでは、そのデータが連続していない場合、読み取りヘッドを移動する必要があるため、ファイルアクセス時間が大幅に遅くなります。挿入操作は、「挿入であるという事実自体によって」、連続してではなく、別の場所に格納する必要があります。確かに、挿入はおそらく非常に高速ですが(非常に大きなファイルの場合)、読み取りははるかに遅くなります。
2014

0

ファイルの途中にバイトのブロックを挿入する最も効率的な方法は、次のとおりです。

  1. ファイルをメモリにマッピングする
  2. ファイルのメモリイメージの最後にバイトを追加します。
  3. これらのファイルを所定の場所にローテーションします(たとえば、C ++標準ライブラリで利用可能な標準アルゴリズムを使用)
  4. ディスクにダーティブロックを書き込む処理をOSに任せる

-1

最初に、挿入ポイントの後のすべてを読み取り、次に挿入するスペース分だけ書き戻す必要があります。次に、「挿入」データを正しい場所に書き込むことができます。パフォーマンスが非常に低いため、ネイティブでサポートされていません。


1
ランダムアクセスのSSDに隣接しているものは何ですか?また、ファイルはファイルシステムによって断片に分割されます。それはすべてをもう一度書くこととどう関係していますか?
ユーザー

@ ユーザーはランダムにそれにアクセスできることを確認します(ビットレベルのアクセスは行っていませんが、ブロックレベルはまだ行っています)...しかし、次に来るバイトをどのように言うのですか?

1
SSDはまだ一度にページを読み書きします。したがって、挿入する1バイトを書き込むには、対応するすべてのファイルシステムテーブル/ポインタを更新するとともに、データのページ全体を書き込む必要があります。初期のファイルシステムに挿入のような操作があったとしても驚くことはありませんが、節約よりもはるかに多くのオーバーヘッドが追加されることに気付きました。
ダンク

-1

ファイルに直接アクセスする場合、より高度な構造を構築するために使用できる低レベルを使用しています。挿入など、必要な種類のアクセスを可能にするデータを使用してデータベースを構築することを検討してください。

ファイルを反復処理するだけで、指定したオフセットへのランダムアクセスを実行しない場合は、コストが低くなります。ファイル内のオフセットによるランダムアクセスが必要な場合は、挿入ポイント以降のすべてのバイトのインデックスを更新する必要があります。

一般に、インデックスのデータ構造、インデックスを格納するためのメモリ、およびインデックスを更新するための追加のディスクアクセスに料金がかかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.