web-dev-qa-db-ja.com

ファイルの内容をASCIIまたはバイナリとして識別する方法

ファイルの内容がASCIIまたはC++を使用してバイナリであるとどのように識別しますか?

28
san

ファイルにonlyの10進バイト9–13、32–126が含まれている場合、それはおそらく純粋なASCIIテキストファイルですそれ以外の場合はそうではありません。ただし、別のエンコーディングのテキストである可能性があります。

上記のバイトへのadditionで、ファイルにonlyが含まれている場合10進バイト128〜255、おそらくISO-8859-1、UTF-8、ASCII + Big5などの8ビットまたは可変長ASCIIベースのエンコーディングのテキストファイルです。そうでない場合は、目的によっては、ここで停止してファイルをバイナリと見なすことができる場合があります。ただし、16ビットまたは32ビットエンコーディングのテキストである可能性があります。

ファイルが上記の制約を満たしていない場合は、ファイルの最初の2〜4バイトで バイトオーダーマーク を調べます。

  • 最初の2バイトが16進数の場合FE FF、ファイルは暫定的にUTF-16BEです。
  • 最初の2バイトが16進数の場合FF FE、および次の2バイトはnothex 00 00、ファイルは暫定的にUTF-16LEです。
  • 最初の4バイトが16進数の場合00 00 FE FF、ファイルは暫定的にUTF-32BEです。
  • 最初の4バイトが16進数の場合FF FE 00 00、ファイルは暫定的にUTF-32LEです。

上記のチェックで暫定的なエンコーディングを決定した場合は、以下の対応するエンコーディングのみをチェックして、ファイルがバイトオーダーマークと一致するバイナリファイルではないことを確認します。

暫定的なエンコーディングを決定していない場合でも、バイトオーダーマークは必須ではないため、ファイルはこれらのエンコーディングのいずれかのテキストファイルである可能性があります。次のリストですべてのエンコーディングを確認してください。

  • ファイルにonlyの10進値が9〜13、32〜126、および128以上のビッグエンディアンの2バイトワードが含まれている場合、ファイルは次のようになります。おそらくUTF-16BE。
  • ファイルにonlyの10進値が9〜13、32〜126、および128以上のリトルエンディアンの2バイトワードが含まれている場合、ファイルは次のようになります。おそらくUTF-16LE。
  • ファイルにonlyの10進値が9〜13、32〜126、および128以上のビッグエンディアンの4バイトワードが含まれている場合、ファイルは次のようになります。おそらくUTF-32BEです。
  • ファイルにonlyの10進値が9〜13、32〜126、および128以上のリトルエンディアンの4バイトワードが含まれている場合、ファイルは次のようになります。おそらくUTF-32LE。

これらすべてのチェックを行ってもまだエンコーディングを決定していない場合、ファイルは私が知っているASCIIベースのエンコーディングのテキストファイルではないため、ほとんどの目的で、おそらくバイナリと見なすことができます(それでもEBCDICなどの非ASCIIエンコーディングのテキストファイルである必要がありますが、それはあなたの懸念の範囲外であると思われます)。

51
Daniel Cassidy

Stream.get()で通常のループを使用して繰り返し処理し、読み取ったバイト値が<= 127であるかどうかを確認します。それを行う多くの方法の1つの方法:

int c;
std::ifstream a("file.txt");
while((c = a.get()) != EOF && c <= 127) 
    ;
if(c == EOF) {
    /* file is all ASCII */
}

しかし、誰かが言ったように、すべてのファイルは結局のところバイナリファイルです。さらに、「ASCII」が何を意味するのかは明確ではありません。あなたが文字コードを意味するならば、それから確かにこれはあなたが行く方法です。ただし、英数字の値のみを意味する場合は、別の方法が必要になります。

私のテキストエディタは、nullバイトの存在を決定します。実際には、これは非常にうまく機能します。nullバイトのないバイナリファイルは非常にまれです。

12
bart

file command がどのように機能するかを見てください;ファイルのタイプを決定するための3つの戦略があります。

プラットフォーム、および関心のある可能性のあるファイルに応じて、その実装を確認したり、呼び出すこともできます。

10
philant

everyファイルの内容はバイナリです。だから、他に何も知らないので、あなたは確信が持てません。

ASCIIは解釈の問題です。テキストエディタでバイナリファイルを開くと、私が言っていることがわかります。

ほとんどのバイナリファイルには、検索できる固定ヘッダー(タイプごと)が含まれています。または、ファイル拡張子をヒントとして使用することもできます。 UTFでエンコードされたファイルが必要な場合は、バイトオーダーマークを探すことができますが、それらもオプションです。

質問をより厳密に定義しない限り、決定的な答えはありません。

8
Tomalak

質問が本当にASCIIだけを検出する方法である場合、litbの答えは的を射ています。ただし、sanがファイルにテキストが含まれているかどうかを判断する方法を知っていた場合、問題はさらに複雑になります。 ASCIIは1つだけです-ますます人気がなくなります-テキストを表現する方法です。Unicodeシステム-UTF16、UTF32、UTF8の人気が高まっています。理論的には、最初の2つかどうかを確認することで簡単にテストできます。バイトはunicocdeバイトオーダーマーク(BOM)0xFEFF(またはバイト順序が逆の場合は0xFFFE)です。ただし、これらの2バイトはLinuxシステムの多くのファイル形式を台無しにするため、存在することを保証できません。さらに、バイナリファイルは0xFEFFから始めます。

ファイルがUnicodeの場合、0x00(または他の制御文字)を探しても役に立ちません。ファイルがUFT16と言っており、ファイルに英語のテキストが含まれている場合、1文字おきに0x00になります。

テキストファイルが書き込まれる言語がわかっている場合は、バイトを分析して、テキストが含まれているかどうかを統計的に判断することができます。たとえば、英語で最も一般的な文字はEの後にTが続きます。したがって、ファイルにZとXよりも多くのEとTが含まれている場合は、テキストである可能性があります。もちろん、これをASCIIおよびさまざまなユニコードとしてテストして、確認する必要があります。

ファイルが英語で書かれていない場合、または複数の言語をサポートしたい場合、残っている2つのオプションは、Windowsでファイル拡張子を確認し、最初の4バイトを「マジックファイル」コードのデータベースと照合することです。ファイルのタイプを判別して、テキストが含まれているかどうかを判別します。

7
David Arno

まあ、これはASCIIの定義に依存します。 ASCII code <128の値、または定義した文字セット( 'a'-'z'、 'A'-'Z'、 '0'-'9など)のいずれかを確認できます。 '...)ファイルに他の文字が含まれている場合は、ファイルをバイナリとして扱います。

通常の改行(0x10または0x13,0x10)をチェックして、テキストファイルを検出することもできます。

1
schnaader

確認するには、ファイルをバイナリとして開く必要があります。ファイルをテキストとして開くことはできません。 ASCIIは事実上バイナリのサブセットです。その後、バイト値を確認する必要があります。ASCIIのバイト値は0-127ですが、0-31が制御です。文字。TAB、CR、およびLFのみが一般的な制御文字です。「A」および「Z」を(移植的に)使用することはできません。これらがASCII(!)。必要な場合は、定義する必要があります。

const unsigned char ASCII_A = 0x41; // NOT 'A'
const unsigned char ASCII_Z = ASCII_A + 25;
1
MSalters

この質問には、正解も不正解もありません。考えられるすべてのテキストファイルで機能するとは限らない複雑なソリューションだけです。

これは、メモ帳がASCIIファイルのタイプを検出する方法に関するa The Old New Thing Article のリンクです。完璧ではありませんが、Microsoftがそれをどのように処理するかを見るのは興味深いことです。

1
Shane Powell

Githubの言語学者charlock holmes library を使用してバイナリファイルを検出し、バイナリファイルは [〜#〜] icu [〜#〜] 's-を使用します 文字セットの検出

ICUライブラリは、CやJavaを含む多くのプログラミング言語で利用できます。

0
cweiske