2

私はすでに Web と SOF で「ファイル エンコーディング」について説明していますが、まだ質問があります。ファイルは関連するレコードのグループであり、ディスク上では、その内容は '1' と '0' として保存されます。実行中のプログラムがファイルを読み込んだりファイルに書き込んだりするたびに、ファイルは RAM に取り込まれ、実行中のプログラム (別名プロセス) のアドレス空間に配置されます。ファイル内のビット (またはバイト) をデコード/エンコードし、読み取り、表示/書き込みする方法を決定するものは何ですか?

SOF には、「ストレージ レベルでは、ファイルにはバイト配列が含まれています。この上に、テキスト ファイルのエンコーディング レイヤーがあります。フォーマット レイヤーは、テキスト ファイルのエンコーディング レイヤーの上、または他のすべてのバイナリ ファイルのバイト配列の上に最後に配置されます。私はこれで大丈夫ですが、100%正しいかどうか知りたいです。

この質問は基本的に、C++ でファイルを開くモードを理解するときに出てきました。

4

5 に答える 5

2

これが役立つかどうか見てみましょう...

Unixファイルは単なるビット配列(1/0)であり、ファイル内の現在の最小ビット数は8、つまり1バイトです。すべてのファイルの相互作用は、バイトレベル以上で行われます。今日のほとんどのシステムでは、ファイルの最大サイズを気にする必要はありません。オペレーティングシステムにはまだいくつかの小さなバリエーションがありますが、最大サイズが1GB未満のものはほとんどありません。

ファイルのエンコーディングまたはフォーマットは、それを使用するアプリケーションにのみ依存します。

'unix ASCII text'やPDFなど、多くの一般的なファイル形式があります。出くわすファイルのほとんどは、ネット上のどこかに文書化されたフォーマット仕様を持っています。たとえば、「UnixASCIIテキストファイル」の仕様は次のとおりです。

各行が行末文字で終了するASCII文字のコレクション。行末文字は、c++ではstd::endl'または引用符で囲まれた「\n」として指定されます。Unixは、この文字をバイナリ値として指定します-012(oct)または00001010。

お役に立てれば :)

于 2013-02-23T15:26:12.420 に答える
2

ここでレイヤーの順序の説明がわかりにくいと思います。フォーマットとエンコーディングは関連しているが、それほど密接に結びついていないと考えています。正式に定義してみましょう。

ファイルは、連続した一連のバイトです。バイトは連続した一連のビットです。

シンボルはデータの単位です。バイトは記号の一種です。バイトではない他のシンボルがあります。数字の 6 を考えてみましょう。これはシンボルですが、バイトではありません。ただし、通常はバイトとしてエンコードできます00000110(これは 6 の 2 の補数エンコードです)。

エンコーディングは、シンボルのセットを別のシンボルのセットにマップします。最も一般的には、バイト以外のシンボルのセットからバイトにマップし、ファイル全体に適用するとファイル encodingになります。2 の補数は、数値の表現を提供します。一方、たとえば ASCII は、ラテン アルファベットと関連する文字をバイト単位で表現します。ASCII をテキストの文字列に適用すると、"Hello, World!" と言うと、一連のバイトが得られます。この一連のバイトをファイルとして保存すると、ファイルは ASCII としてエンコードされます。

フォーマットは、シンボルの有効なシーケンスのセットを記述します。ファイルのバイトに適用される場合、それはファイル形式です。例として、ラスター グラフィックスを格納するための BMP ファイル形式があります。ファイル形式を BMP として識別するために最初に数バイトが必要であり、その後にイメージのサイズと深さを記述するために数バイトが続く必要があることを指定します。ファイル形式ではない形式の例は、英語での 10 進数の書き方です。基本的な形式は、一連の数字の後にオプションの小数点が続き、さらに数字が続く形式です。

テキストファイル

テキスト ファイルは、非常に単純な形式の一種のファイルです。構造がないため、フォーマットは非常にシンプルです。すぐに文字のエンコードで始まり、最後の文字のエンコードで終わります。通常、ヘッダーやフッター、メタデータなどはありません。最初からバイトを文字として解釈し始めるだけです。

しかし、ファイル内の文字をどのように解釈しますか? そこでエンコーディングの出番です。ファイルが ASCII としてエンコードされている場合、バイト01000001はラテン文字の A を表します。UTF-8 など、はるかに複雑なエンコーディングがあります。UTF-8 では、文字は必ずしも 1 バイトで表現できるわけではありません。できる人もいれば、できない人もいます。最初のバイトの最初の数ビットから、文字として解釈するバイト数を決定します。

お気に入りのテキスト エディターでファイルを開くとき、ファイルはどのようにバイトを解釈するかを知るのでしょうか? それは興味深い問題です。テキスト エディタは、ファイルのエンコーディングを決定する必要があります。さまざまな方法でこれを試みることができます。ファイル名の拡張子からヒントが得られる場合があります (.txt少なくとも ASCII 互換である可能性があります)。場合によっては、ファイルの最初の文字が、エンコーディングが何であるかについての良いヒントを与えてくれます。ただし、ほとんどのテキスト エディタには、ファイルをどのエンコーディングとして扱うかを指定するオプションがあります。

テキスト ファイルには形式があります。多くの場合、形式はテキストのエンコーディングから完全に独立しています。つまり、この形式は、有効なバイト シーケンスをまったく記述していません。代わりに、有効な文字シーケンスを記述します。たとえば、HTML はドキュメントをマークアップするためのテキスト ファイルの形式です。ドキュメントの内容を決定する文字のシーケンスを記述します (注: バイトのシーケンスではありません)。例として、一連の文字<html>が開始タグであり、ある時点で終了タグが続く必要があることを示してい</html>ます。もちろん、形式はこれよりもはるかに詳細です

バイナリーファイル

バイナリ ファイルは、そのファイル形式によって意味が決まるファイルです。ファイル形式は、ファイル内の有効なバイト シーケンスとそのシーケンスの意味を記述します。ファイル形式レベルで重要なのはバイトの解釈ではなく、バイトの順序と配置です。

前述のように、BMP ファイル形式は、ラスター グラフィックスを格納する方法を提供します。最初の 2 バイトは である必要が01000010 01001101あり、次の 4 バイトはファイルのサイズをバイト数のカウントとして指定する必要があるなどであり、実際のピクセル データに至ります。

バイナリ ファイルには、その中にエンコーディングを含めることができます。これを説明するために、前の例を考えてみましょう。BMP ファイルの最初の 2 バイトに続く 4 バイトは、ファイルのサイズをバイト単位で示していると言いました。これらのバイトはどのように解釈されますか? BMP ファイル形式は、これらのバイトがサイズを符号なし整数として与えると述べています。これは、それらのバイトのエンコーディングです。

では、コンピューターのディレクトリで BMP ファイルを参照して開く場合、システムはどのようにしてそのファイルを開く方法を認識しているのでしょうか? それを表示するために使用するプログラムをどのように知るのでしょうか? バイナリ ファイルの形式は、テキスト ファイルのエンコーディングよりも、ファイル拡張子によってはるかに強く示唆されます。ファイル名が.bmp最後にある場合、システムはおそらくそれを BMP ファイルと見なし、使用しているグラフィック プログラムで開くだけです。また、最初の数バイトを調べて、それらが何を示唆しているかを確認することもできます。

概要

ファイル内のバイトの意味を理解するための最初のレベルは、そのファイルの形式です。テキスト ファイルの形式は非常に単純です。最初から始めて、最後まで文字を解釈します。文字を解釈する方法は、そのテキスト ファイルの文字エンコーディングによって異なります。ただし、ほとんどの形式はより複雑で、エンコーディングがネストされている可能性があります。あるレベルでは、バイトから抽象的な情報の抽出を開始する必要があり、そこでエンコーディングが開始されます。しかし、エンコードされているものはすべて、それに適用されるフォーマットを持つこともできます。必要な情報が得られるまで、一連の形式とエンコーディングがあります。

于 2013-02-23T17:12:19.127 に答える
2

何かをエンコード/表示する方法の決定は、完全にプログラムの設計者次第です。もちろん、特定の種類のファイルには標準があります。PDF または JPG ファイルには、そのコンテンツの標準形式があります。PDF と JPG の定義は非常に複雑です。

テキスト ファイルには、少なくともある程度の標準があります。ただし、テキスト ファイルの内容を解釈または使用する方法は、JPEG と同じくらい複雑でわかりにくい場合があります。唯一の違いは、内容が (ある種の) テキストであることです。テキストエディタに読み込んで、意味を理解しようとすることができます。ただし、「データベース タイプ アプリケーション内のテキスト」の行の例については、以下を参照してください。

C および C++ では、本質的に 1 つの違いだけがあり、ファイルは「バイナリ」または「テキスト」(「非バイナリ」) のいずれかです。違いは、「特殊ビット」の扱いに関するもので、主に「エンディング」に関するものです。テキスト ファイルには、行末マーカーまたは改行 ( '\n') [改行について少し説明します] が含まれます。一部のオペレーティング システムでは、 「ファイルの終わりマーカー」を含みます。たとえば、古い CP/M では、ファイルのサイズは 128 または 256 バイトのブロック単位でした。もし私たちが持っていたら"Hello, World!\n"テキスト ファイルでは、そのファイルの長さは 128 バイトになり、残りの 114 バイトは「ファイルの終わり」マーカーになります。最新のオペレーティング システムのほとんどは、ファイル サイズをバイト単位で追跡するため、ファイル内にファイル終了マーカーを含める必要はありません。しかし、C は新旧両方の多くのオペレーティング システムをサポートしているため、言語にはこれが考慮されています。ファイルの終わりは通常、CTRL-Z (DOS、Windows など) または CTRL-D (Unix - Linux など) です。C ランタイム ライブラリがファイルの終わりの文字に達すると、読み取りを停止し、「ここで読み取るファイルがこれ以上ない」場合と同じように、エラー コード/動作を示します。

行末または改行は、ファイルが存在する OS で常に同じであるとは限らないため、特別な処理が必要です。たとえば、Windows と DOS は、「キャリッジ リターン、ライン フィード」(CR、LF - CTRL-M、CTRL-J、それぞれ ASCII 13 と 10) を行末として使用します。Unix のさまざまな形式 (Linux、MacOS X、BSD など) では、行末は "改行" (LF、CTRL-J) だけです。古い MacOS では、行末は「キャリッジ リターン」のみです。プログラマーが行末を正確に気にする必要がないように、C ランタイム ライブラリは、「ネイティブ」の行末を標準化された行末'\n'(「改行」または文字に変換) に変換します。値 10)。もちろん、これは C ランタイム ライブラリが「CR の後に LF が続く場合、

バイナリ ファイルの場合、ピクセルの値がたまたま 13 と 10 であるという理由だけで、データの変換はまったく必要ありません。10 バイトにマージしたいという意味ではありませんよね? そして、コードが値 26 (CTRL-Z) または 4 (CTRL-D) のバイトを読み取る場合、入力をそこで停止させたくありません...

ここで、以下を含むデータベース テキスト ファイルがあるとします。

 10 01353-897617 14000 Mats

あなたはおそらくそれが何を意味するのかほとんどわかっていないでしょう - つまり、「Mats」が私の名前であることはおそらく理解できるでしょう - しかし、それはメガネの下に置く小さな段ボールの物 (別名「ビアマット」) または何かに行くものかもしれません.ムスリム用の「祈りマット」など。

番号 10 は、顧客番号、商品番号、「行番号」などです。01353-896617 は、ほぼ何でもかまいません - おそらく私の電話番号 [いいえ、そうではありませんが、実際に似ています] - しかし、「製造元の部品番号」または何らかの形のシリアル番号などである可能性もあります。14000? アイテムごとの価格、在庫数、給料 [ないことを願っています!]、住所からオーストラリアのシドニーまでのマイル単位の距離 [おおよそだと思います]。

何も与えられていない他の誰かが、他の何百もの答えを思い付くことができると確信しています。

[真実は、有効な英国の市外局番である「電話番号」の先頭のビットを除いて、この回答の目的のためにナンセンスであるということです。テキストファイル内の一連のフィールドは、フィールドの意味を説明する何かがある場合にのみ理解できます。"]

もちろん、同じことがバイナリ ファイルにも当てはまります。ただし、区切り記号がないため、コンテンツが何であるかを把握するのがさらに困難になることがよくあります。上記のテキストにスペースとダッシュが含まれていなかった場合、何がどこに属しているか知っていますよね?通常、バイナリ ファイルには「スペース」などはありません。それはすべて、どこかのコードでの誰かの記述または定義、またはそのようなものにかかっています。

ここでのとりとめのない話があなたに何らかのアイデアを与えてくれることを願っています.

于 2013-02-23T15:41:04.807 に答える
1

ファイル内のビット (またはバイト) をデコード/エンコードし、読み取り、表示/書き込みする方法を決定するものは何ですか?

明らかに、ファイルの形式。BMP ファイルを読み込んでいる場合は、最初にヘッダーを読み込んでからheight*widthピクセル データを読み込む必要があります。を読んでいる場合は.txt、文字をそのまま読んでください。テキスト ファイルには、Unicode などのさまざまなエンコーディングを使用できます。

などの一部の形式.pngは圧縮されています。つまり、生データはディスク上のファイルよりも多くのメモリ領域を必要とします。

特定のアルゴリズムは、さまざまな要因に応じて選択されます。Windows では、通常、重要なのは拡張子です。ウェブでは、content typeが支配的です。

一般に、他の形式のファイルを読み取ろうとすると、通常はゴミが発生します。強制的に実行されることもあり.bmpます。たとえば、テキスト エディタでファイルを開いてみてください。

于 2013-02-23T15:17:31.617 に答える
1

つまり、基本的には主にテキスト ファイルについて話しているということですね。

要点: テキスト エディタがファイルをメモリにロードするとき、何らかの情報からファイル エンコーディングを推測します (指定するか、ファイルの最初の数バイトに特別なファイル フォーマット マーカーがあるかなど)。次に、生のバイトをどのように扱うかを決定するのはプログラム自体です。

たとえば、テキスト エディタにファイルを ASCII として開くように指示すると、テキスト エディタは各バイトを個別の文字として扱いA、現在表示するバイトとして数字 65 に遭遇するたびにその文字を表示します (65 はの ASCII 文字コードA)。

ただし、ファイルを UTF-16 で開くように指示すると、一度に 2 バイト (より正確には 2オクテット) が取得され、このいわゆる「単語」が数値として使用されます。たとえば、ç読み取った 2 バイトが231の Unicode 文字コードである に対応していた場合、文字を表示しますç

于 2013-02-23T15:18:43.360 に答える