72

非公式に言うと、私たちのほとんどは、「バイナリ」ファイル (オブジェクト ファイル、画像、動画、実行可能ファイル、独自のドキュメント形式など) と「テキスト」ファイル (ソース コード、XML ファイル、HTML ファイル、電子メールなど) があることを理解しています。

一般に、ファイルを使って何か役に立つことができるようにするには、ファイルの内容を知る必要があり、エンコーディングが「バイナリ」または「テキスト」であるかどうかは問題ではありません。そしてもちろん、ファイルはバイト単位のデータを保存するだけなので、それらはすべて「バイナリ」であり、「テキスト」はエンコーディングを知らなければ意味がありません。それでも、「バイナリ」ファイルと「テキスト」ファイルについて話すことは依然として有用ですが、この不正確な定義で誰かを怒らせないように、引き続き「怖がらせる」引用符を使用します。

ただし、幅広いファイルに対応するさまざまなツールがあり、実際には、ファイルが「テキスト」であるか「バイナリ」であるかに基づいて、別のことを行いたいと考えています。この例は、コンソールにデータを出力するツールです。プレーンな「テキスト」は見栄えがよく、便利です。「バイナリ」データは端末を台無しにし、一般的に見ても役に立ちません。GNU grep は、一致をコンソールに出力するかどうかを決定する際に、少なくともこの区別を使用します。

問題は、ファイルが「テキスト」か「バイナリ」かをどのように見分けるかということです。さらに制限を加えると、Linux のようなファイル システムではどのように判断しますか? ファイルの「タイプ」を示すファイルシステムのメタデータを認識していないため、ファイルの内容を調べて、それが「テキスト」か「バイナリ」かをどのように判断すればよいのでしょうか? 簡単にするために、「テキスト」を、ユーザーのコンソールで印刷可能な文字を意味するように制限しましょう。特に、これをどのように実装しますか? (これはこのサイトで暗示されていると思いましたが、一般的に、これを行う既存のコードを指摘することは役立つと思います。指定する必要がありました)、既存のプログラムを使用して何ができるかについてはあまり知りませんこれ。

4

11 に答える 11

64

コマンドを使用できますfile。ファイル( )に対して一連のテストを実行して、man fileバイナリかテキストかを判断します。Cからそれを行う必要がある場合は、そのソースコードを見る/借りることができます.

file README
README: ASCII English text, with very long lines

file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
于 2009-02-19T23:54:20.287 に答える
18

ファイルのMIME タイプを判別するには、

file --mime FILENAME

省略形はfile -iLinux では、file -ImacOS では (大文字の i) です (コメントを参照)。

で始まる場合はtext/テキスト、それ以外の場合はバイナリです。唯一の例外は XML アプリケーションです。+xmlファイルタイプの最後を探すことで、それらを一致させることができます。

于 2009-02-19T23:55:50.627 に答える
17

私の会社が作成した表計算ソフトウェアは、テキスト ファイルだけでなく、多くのバイナリ ファイル形式を読み取ります。

最初に、認識できるマジック ナンバーの最初の数バイトを確認します。読み取ったバイナリ タイプのマジック ナンバーを認識できない場合は、ファイルの最初の 2K バイトまでを調べて、エンコードされたUTF-8UTF-16、またはテキスト ファイルであるかどうかを確認します。ホスト オペレーティング システムの現在のコード ページで。これらのテストのいずれにも合格しない場合は、処理できるファイルではないと見なし、適切な例外をスローします。

于 2009-02-20T01:10:00.417 に答える
4

ファイル全体を調べているだけなら、すべての文字が で印刷可能かどうかを確認してくださいisprint(c)。Unicode の場合は、もう少し複雑になります。

Unicode テキスト ファイルを区別するために、MSDN は何をすべきかについていくつかの優れたアドバイスを提供しています

その要点は、最初の 4 バイトまでを最初に検査することです。

EF BB BF     UTF-8 
FF FE        UTF-16, little endian 
FE FF        UTF-16, big endian 
FF FE 00 00  UTF-32, little endian 
00 00 FE FF  UTF-32, big-endian 

それはあなたにエンコーディングを教えてくれます。次に、iswprint(c)テキスト ファイル内の残りの文字に使用します。UTF-8 および UTF-16 の場合、1 文字は可変バイト数で表すことができるため、データを手動で解析する必要があります。また、あなたが本当にアナル好きiswprintなら、あなたのプラットフォームで利用可能なロケールバリアントを使用したいと思うでしょう。

于 2009-02-19T23:51:10.717 に答える
3

Perl には適切なヒューリスティックがあります。演算子を使用して-B、バイナリをテストします (-Tテキストをテストするには、その反対です)。テキストファイルを一覧表示するシェルのワンライナーは次のとおりです。

$ find . -type f -print0 | perl -0nE 'say if -f and -s _ and -T _'

(前にドルがないアンダースコアは正しいことに注意してください (RTFM))。

于 2013-01-30T12:00:55.850 に答える
3

libmagicUnixfileコマンドラインのライブラリバージョンであるこれを使用できます。

多くの言語のラッパーがあります。

于 2016-06-23T14:24:27.580 に答える
3

古いトピックですが、誰かがこれを役に立つと思うかもしれません。何かがファイルであるかどうかをスクリプトで決定する必要がある場合は、次のように簡単に実行できます。

if file -i $1 | grep -q text;
then 
.
.
fi

これによりファイルの種類が取得され、サイレント grep を使用してテキストかどうかを判断できます。

于 2015-05-23T20:59:35.543 に答える
2

違いを見分けようとするほとんどのプログラムは、ファイルの最初のnバイトを調べて、それらのバイトがすべて「テキスト」とみなされるかどうか (つまり、それらがすべて印刷可能な ASCII 文字の範囲内にあるかどうか) を調べるなどのヒューリスティックを使用します。 . より細かく区別するために、UNIX ライクなシステムでは常に「file」コマンドがあります。

于 2009-02-19T23:52:22.430 に答える
1

簡単なチェックの 1 つは、\0文字があるかどうかです。テキストファイルにはそれらがありません。

于 2009-02-20T00:59:21.737 に答える
1

前述のように、*nix オペレーティング システムには file コマンド内でこの機能があります。このコマンドは、多くの一般的なファイル構造に含まれるマジック ナンバーを定義する構成ファイルを使用します。

マジックと呼ばれるこのファイルは、歴史的に /etc に保存されていましたが、一部のディストリビューションでは /usr/share に保存されている場合があります。マジック ファイルは、ファイル内に存在することがわかっている値のオフセットを定義し、これらの場所を調べてファイルのタイプを判別できます。

マジック ファイルの構造と説明は、関連するマニュアル ページ (man magic) を参照することで見つけることができます。

実装に関しては、 file.c自体の中にありますが、読み取り可能なテキストかどうかを判断するfileコマンドの関連部分は次のとおりです。

/* Make sure we are dealing with ascii text before looking for tokens */
    for (i = 0; i < nbytes - 1; i++) {
        if (!isascii(buf[i]) ||
            (iscntrl(buf[i]) && !isspace(buf[i]) &&
             buf[i] != '\b' && buf[i] != '\032' && buf[i] != '\033'
            )
           )
            return 0;   /* not all ASCII */
    }
于 2009-02-20T01:47:57.300 に答える