ホームページ  >  記事  >  バックエンド開発  >  phpファイルと文字コードについて詳しく解説

phpファイルと文字コードについて詳しく解説

小云云
小云云オリジナル
2018-03-14 15:15:051950ブラウズ


私の最初の疑問は、テキスト ファイルとバイナリ ファイルの違いは何だろうかということでした。一方のコンテンツは表示できるのに、もう一方のコンテンツは通常 (テキスト エディターを使用して) 表示できないことがよくあるのはなぜですか?

メリーランド大学のこのトレーニング ノートでは、この 2 つの違いが明確に説明されています。テキスト ファイルはバイナリ ファイルの一種であり、基礎となるストレージも 0 と 1 です。テキスト ファイルは可読性と移植性に優れていますが、パフォーマンスが制限されています。バイナリ ファイル データ ストレージはコンパクトで、文字エンコーディングの制限はありません。テキスト ファイルは基本的に数字、テキスト、句読点などの限られた文字で構成されるコンテンツのみを保存できます。バイナリ ファイルには文字の制限がなく、画像、音声、ビデオなどのデータを自由に保存できます。 数値を保存する例を使用すると、テキスト ファイルとバイナリ ファイルの保存内容の違いが明確にわかります。たとえば、数値 1234567890 を保存するには、テキスト ファイルに 0 ~ 9 の 10 個の数値の ASCII コードを保存する必要があります。対応する 16 進表現は、31 32 33 34 35 36 37 38 39 30、10 バイトを占有; 1234567890 の対応するバイナリは " 0100 1001 1001 0110 0000 0010 1101 0010 "、4 バイトを占め (バイナリ表現は 32 ビット、1 バイトは 8 ビット)、ファイルに格納される 16 進表現は (ビッグ エンディアン) です: 49 96 02 D2

テキスト ファイルはコンテンツを 31 32 33 34 35 36 37 38 39 30,占用10个字节;1234567890对应的二进制为“‭0100 1001 1001 0110 0000 0010 1101 0010‬”,占用4个字节(二进制表示32位,一个字节8位),存储到文件的16进制表示为(大端):49 96 02 D2

文本文件按字符存放内容,二进制按字节存放,这是两种文件最本质的区别。根据这个特性,可以推断出一些常见结论:二进制文件常常比文本文件紧凑,占用空间少;文本文件更友好易用,能用所见即所得的方式编辑;二进制文件常常需要专用程序打开,等等。

回过头看文本编辑器打开二进制文件常常是乱码的现象。例如一个二进制文件存放了一个整数1234(四个字节),用16进制表示为:00 00 04 D2文字

で保存し、バイナリ ファイルはコンテンツを 🎜バイト🎜 で保存します。これが 2 つのファイルの最も重要な違いです。この特性に基づいて、次のような一般的な結論が得られます。多くの場合、バイナリ ファイルはテキスト ファイルよりもコンパクトで、使用するスペースが少なくなります。テキスト ファイルは、より使いやすく、WYSIWYG 方法で編集できるため、特別なプログラムが必要です。オープン等。 🎜🎜テキストエディタを見てみると、バイナリファイルが文字化けしていることがよくあります。たとえば、バイナリ ファイルには整数 1234 (4 バイト) が格納され、16 進数で次のように表現されます: 00 00 04 D2。テキスト エディタを開いて 1 文字ずつ解釈すると、これらのバイトでは表示可能な文字をスペルアウトできないことがわかり、意味不明なものとして扱う必要があります。文字化けの原因は、テキストエディタがバイトストリームを正しく解析できないため、バイナリファイルを特殊なソフトで開く必要があるためです。例えば、jpgファイルは画像閲覧ソフトで開く必要がありますが、音楽プレーヤーで開いたら終わりです。動画ファイルはプレーヤーと圧縮ソフトで開く必要があるので、さっそく始めましょう! 🎜

ファイル形式

テキストファイルとバイナリファイルの違いを理解した後、ファイル形式を見てみましょう。 Windows はファイル拡張子に応じてファイル形式を認識し、ファイルを開くために対応するプログラムを呼び出すことはわかっていますが、Unix システムでは拡張子はオプションです。では、ファイルの形式をどうやって知ることができるのでしょうか。

幸いなことに、ファイルの形式を知ることができる file コマンドがあります。ファイル形式の本質的な違いはファイル拡張子ではなく、内容です。 a.zip を a.txt/a.jgp/a.mp3 に変更します。ファイル名が何であっても、ファイルの元の形式が表示されます: Zip archive data, at least v1.0 to extract

エンコーディング

ファイルについて話した後、ファイルコンテンツのエンコーディングについて話しましょう。一般的な ASCII 文字は 127 種類あり、エンコーディングはありません。ほぼすべてのエンコーディング方式に対応しています。ダブルバイト文字とマルチバイト文字、エンコード方法とバイト順序は、プログラマを悩ませる問題です。中国語の文字の場合、GBK エンコードには 2 バイトが必要であり、ローカル マシンのエンディアンを考慮してストレージの最終形式を決定する必要があります。ネットワーク通信中に、受信側が受信できるようにネットワーク バイト オーダー (ビッグ エンディアン) に変換する必要があります。普通に解析してみます。開発者が文字コードに慣れていなくて、通信中に文字化けが発生した場合、デバッグが困難になります。

UCS (Universal Multiple Octet Coded Character Set) 標準の策定により、開発者は混乱を招くマルチバイト文字セットを避けることができます。 UCS 標準では、すべての文字に一意のコード ポイントがあり、コード ポイントに基づいて対応する文字を見つけることができます。 UCS は、1 文字に対応する 2 バイトを使用してコード ポイントを表します (UCS-4 標準は 4 バイト)。 2 バイトを使用するため、2^16-1 (6w+) 文字を収容でき、基本的にはさまざまな国で一般的に使用される文字を収容できます (UCS-4 は理論的には最大 20 億文字を収容でき、現在は 16W を超える文字を収容できます)。 UCS は、コード ポイントと文字の 1 対 1 の対応を規定する規格にすぎず、コンピュータに格納する方法を定義するものではないことに注意してください。

Unicode 文字の保存方法を規定する作業は、UTF (Unicode Transformation Format) によって完了します。最も一般的に使用されるソリューションは UTF-16 と UTF-8 です。 UTF-16 は、2 バイトを使用して文字を表します。Windows、MacOS、および Java プラットフォームのデフォルトの文字エンコード スキームは UTF-16 です。 2 バイトがあるため、ビッグエンディアンとリトルエンディアンの 2 つのスキームがあります。 ASCII 文字のみを含むファイルの場合、UTF-16 エンコーディングを使用すると、スペースが大幅に浪費されます (ストレージの 50% を浪費します) Ken Thompson (C 言語の発明者) と Robe Pike (Go 言語の発明者) によって提案された UTF-8 エンコーディング スキーム。それはすぐに人気になりました。 UTF-8 はシングルバイト ストリームであり、バイト順序の問題はなく、BOM も必要ありません。 UTF-8 は現在、一般的な Web 標準です。

対応

USC-2の値の範囲はU+0000~U+FFFFで、UTF-8との対応関係は以下の通りです:

16進数 2進数
0000 - 0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 1 0xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

从编码可以看出,与二进制相比,浪费了很多空间。不过这也没办法,可显示的字符更容易阅读和理解,人类很难抗拒这个诱惑。

UTF-8转换规则为: 1. 如果某字节第一位是 0 ,那么判定为 ASCII 字节,除了 0 外余下的 7 位是 ASCII 码,所以 UTF-8 是兼容 ASCII 码的; 2. 如果第一个字节是 1 ,那么连续的几个 “1” 代表从这个字符开始,后面连续的几个字节其实是一个字位,且后面的字节都要以10开头。

了解如上规则,我们的程序便可轻松的处理UTF-8编码的字节流。例如要找出“中”的UTF-8编码,则可以这样处理(注意文件是UTF-8编码):

$char = "中";
$length = strlen($char);
$bytes = pack("a" . $length, $char);echo "UTF-8:" . bin2hex($bytes) . "\n";
// 或者echo "UTF-8:";for ($index = 0; $index < $length; ++ $index) 
{    echo bin2hex($char{$index});
}echo PHP_EOL;

也可以写出针对UTF-8编码的strlen函数:

function myStrlen(string $string){
    $slen = strlen($string);
    $mlen = 0;
    $maxByteLength = 4;
    $maxOffset = 7;    for ($i = 0; $i < $slen; ++ $i) {
        $byte = ord($string{$i});        // 从01xxxxxx开始对比,直到11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx。只需要对比第一个字节即可
        for ($offset = 0; $offset < $maxByteLength; ++ $offset) {
            $result = $byte & (1 << ($maxOffset - $offset));            if ($result === 0) {
                $i += $offset;
                ++ $mlen;                break;
            }
        }
    }    return $mlen;
}

$string = "Coder不是工程师!";echo "mb_strlen:" . mb_strlen($string) . "\n";echo "mStrlen:" . myStrlen($string) . "\n";

相关推荐:

关于字符编码问题的详细介绍

以上がphpファイルと文字コードについて詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。