第042回_EncodingDecl2
»
前回のコラムの最後に予告した通り、ファイル情報から文字符号化方式を判別する処理の細かい処理機構について議論します。
文字符号化方式の決定方法
W3Cの勧告は次のように説明しています。少し長いので部分毎にわけて説明します。
プログラムと文字コードの仕様としては矛盾に満ちた仕様
です。矛盾に満ちたといえるのは、
この後のセクションでは文字符号化方式を決定する方法について説明しています。
そこで表を書き直すと次のようになります。
ここまでの処理の判定は次のようになります。
■XMLプロセッサがサポート可能な文字符号化方式
----W3C勧告----
E Autodetection of Character Encodings (Non-Normative)
The XML encoding declaration functions as an internal label on each entity, indicating which character encoding is in use. Before an XML processor can read the internal label, however, it apparently has to know what character encoding is in use -- which is what the internal label is trying to indicate. In the general case, this is a hopeless situation. It is not entirely hopeless in XML, however, because XML limits the general case in two ways: each implementation is assumed to support only a finite set of character encodings, and the XML encoding declaration is restricted in position and content in order to make it feasible to autodetect the character encoding in use in each entity in normal cases. Also, in many cases other sources of information are available in addition to the XML data stream itself. Two cases may be distinguished, depending on whether the XML entity is presented to the processor without, or with, any accompanying (external) information. We consider the first case first.
----W3C勧告----The XML encoding declaration functions as an internal label on each entity, indicating which character encoding is in use. Before an XML processor can read the internal label, however, it apparently has to know what character encoding is in use -- which is what the internal label is trying to indicate. In the general case, this is a hopeless situation. It is not entirely hopeless in XML, however, because XML limits the general case in two ways: each implementation is assumed to support only a finite set of character encodings, and the XML encoding declaration is restricted in position and content in order to make it feasible to autodetect the character encoding in use in each entity in normal cases. Also, in many cases other sources of information are available in addition to the XML data stream itself. Two cases may be distinguished, depending on whether the XML entity is presented to the processor without, or with, any accompanying (external) information. We consider the first case first.
----日本語訳----
XMLのエンコーディング宣言は、
E 文字符号化方式の自動検知(非規範的)
----日本語訳----
XMLのエンコーディング宣言はそれぞれの実体で使われている文字符号化方式を示す内部的な名前として機能する。しかし、XMLプロセッサが内部的な名前を読む前に使われている文字符号化方式---内部的な名前がなんであるか---
を知らなけばならないことは明らかである。一般的に、こういった状況は対処のしようがない。といっても、XMLという仕様の中では対処のしようはある。なぜなら、XMLは2つの仕様によって一般的な状況を制限しているからである。:XMLのそれぞれの実装は有限の文字符号化方式のしかサポートしないことを想定していて、一般的な状況でもそれぞれの実体で使われている文字符号化方式を自動検知することが可能になるようにエンコーディング宣言の位置と内容が制限されている。また、多くの場合、XMLのデータストリームに加えて、他の情報源も利用可能である。XML実体が(外部の)情報を伴ってプロセッサに渡されるか否かによって2つの場合に分けることができる。外部情報が渡されない場合について考えてみる。
を知らなけばならないことは明らかである。一般的に、こういった状況は対処のしようがない。といっても、XMLという仕様の中では対処のしようはある。なぜなら、XMLは2つの仕様によって一般的な状況を制限しているからである。:XMLのそれぞれの実装は有限の文字符号化方式のしかサポートしないことを想定していて、一般的な状況でもそれぞれの実体で使われている文字符号化方式を自動検知することが可能になるようにエンコーディング宣言の位置と内容が制限されている。また、多くの場合、XMLのデータストリームに加えて、他の情報源も利用可能である。XML実体が(外部の)情報を伴ってプロセッサに渡されるか否かによって2つの場合に分けることができる。外部情報が渡されない場合について考えてみる。
プログラムと文字コードの仕様としては矛盾に満ちた仕様
です。矛盾に満ちたといえるのは、
XMLの入力ストリームにエンコーディング宣言を書いたからといってエンコーディング宣言を元に文字符号化方式を決定して入力ストリームの処理を切り替えできない
また、入力ストリームからエンコーディング宣言までの内容が一致したからといってユーザが指定した文字符号化方式と入力ストリーム全体を調べて文字符号化方式を決めるべきである
という仕様だからです。また、入力ストリームからエンコーディング宣言までの内容が一致したからといってユーザが指定した文字符号化方式と入力ストリーム全体を調べて文字符号化方式を決めるべきである
この後のセクションでは文字符号化方式を決定する方法について説明しています。
----W3C勧告----
E.1 Detection Without External Encoding Information
Because each XML entity not accompanied by external encoding information and not in UTF-8 or UTF-16 encoding must begin with an XML encoding declaration, in which the first characters must be '<?xml', any conforming processor can detect, after two to four octets of input, which of the following cases apply. In reading this list, it may help to know that in UCS-4, '<' is "#x0000003C" and '?' is "#x0000003F", and the Byte Order Mark required of UTF-16 data streams is "#xFEFF". The notation ## is used to denote any byte value except that two consecutive ##s cannot be both 00.
With a Byte Order Mark:
00 00 FE FF UCS-4, big-endian machine (1234 order)
FF FE 00 00 UCS-4, little-endian machine (4321 order)
00 00 FF FE UCS-4, unusual octet order (2143)
FE FF 00 00 UCS-4, unusual octet order (3412)
FE FF ## ## UTF-16, big-endian
FF FE ## ## UTF-16, little-endian
EF BB BF UTF-8
----W3C勧告----Because each XML entity not accompanied by external encoding information and not in UTF-8 or UTF-16 encoding must begin with an XML encoding declaration, in which the first characters must be '<?xml', any conforming processor can detect, after two to four octets of input, which of the following cases apply. In reading this list, it may help to know that in UCS-4, '<' is "#x0000003C" and '?' is "#x0000003F", and the Byte Order Mark required of UTF-16 data streams is "#xFEFF". The notation ## is used to denote any byte value except that two consecutive ##s cannot be both 00.
With a Byte Order Mark:
00 00 FE FF UCS-4, big-endian machine (1234 order)
FF FE 00 00 UCS-4, little-endian machine (4321 order)
00 00 FF FE UCS-4, unusual octet order (2143)
FE FF 00 00 UCS-4, unusual octet order (3412)
FE FF ## ## UTF-16, big-endian
FF FE ## ## UTF-16, little-endian
EF BB BF UTF-8
----日本語訳----
ここでわかることは、前回説明したことを含めると、
E1. 外部の文字符号化方式情報のない検知
----日本語訳----
それぞれの外部の文字符号化方式情報を伴わず、UTF-8でもUTF-16でもない文字符号化方式のXML実体はXMLエンコーディング宣言で始まらなければならず、つまり最初の文字は'<?xml'であるから、仕様に適合するプロセッサは皆、入力の2オクテットから4オクテット目を見て、後述する場合のいずれを適用するかを検知することができる。このリストを読むとき、UCS-4の'<'は"#x0000003C"で'?'は"#x0000003F"であり、UTF-16のデータストリームのバイトオーダーマークは"#xFEFF"であるということを知っていると役に立つだろう。##という記法は"0000"を除く任意のバイト値を示すために使う。
バイトオーダーマークが付いている場合は次のようになる
00 00 FE FF UCS-4, ビッグエンディアン(1234の順)
FF FE 00 00 UCS-4, リトルエンディアン(4321の順)
00 00 FF FE UCS-4, 普通でないオクテットの並び(2143)
FE FF 00 00 UCS-4, 普通でないオクテットの並び(3412)
FE FF ## ## UTF-16, ビッグエンディアン
FF FE ## ## UTF-16, リトルエンディアン
バイトオーダーマークが付いている場合は次のようになる
00 00 FE FF UCS-4, ビッグエンディアン(1234の順)
FF FE 00 00 UCS-4, リトルエンディアン(4321の順)
00 00 FF FE UCS-4, 普通でないオクテットの並び(2143)
FE FF 00 00 UCS-4, 普通でないオクテットの並び(3412)
FE FF ## ## UTF-16, ビッグエンディアン
FF FE ## ## UTF-16, リトルエンディアン
文字符号化方式指定しない場合
■文字集合UCS-4
ファイル情報から文字符号化方式を判別してファイルをオープンします。ファイル情報を知るために文字符号化方式を指定せずにファイルのバイト文字列を読み込みます。そのバイト列の先頭にBOMが付いている場合はBOMのバイト列からどの文字符号化方式かを判別します。また、BOMが付いていない場合は、"<?xml"の先頭文字"<"を示す文字コードを使って文字符号化方式を判別します。これらは完全ではないとしても、サポートする有限個の文字符号化方式の中では問題がありません。
ISO/IEC 10646 (UCS; Universal Coded Character Set) は、符号化文字集合や文字符号化方式を定めた文字コードの国際規格です。ISO/IEC 10646は31ビットを使います。ただし、Unicodeは21ビットつまり0-10FFFFを使う規格で(前回も余談で説明しましたが、ISO/IEC 10646はUnicodeに乗っ取られた規格のため)ISO/IEC 10646の110000以降は永久に文字として定義されないことになりました。
そのISO/IEC 10646の定義する4オクテット(32ビット)の符号化文字集合です。先に説明した通り、32ビットの内で使うのは0-10FFFFだけです。
UCS-4とは別にUCS-2もあります。
■ISO/IEC 10646の文字符号化方式そのISO/IEC 10646の定義する4オクテット(32ビット)の符号化文字集合です。先に説明した通り、32ビットの内で使うのは0-10FFFFだけです。
UCS-4とは別にUCS-2もあります。
UTF-1, UTF-8, UTF-16, UTF-32があります。
と異なる意味ですが、UTF-8とUTF-16の符号化方式の内容はほぼ同じです。
ということでW3C勧告の表の2列目は符号化文字集合と文字符号化方式が混在していてわかりにくくなっています。またXMLで扱える符号化文字集合は前回説明した通りUnicodeの範囲内のCharからRestricted Charを除いた差集合ですがXMLファイルを専用のエディタで編集しない限り、ファイルは特定の符号化文字集合と文字符号化方式で保存するXMLプロセッサが保存したファイルをデコードしながら読み込むという順序となります。XMLプロセッサとして許容できるかどうかはXMLプロセッサが判断することです。ISO/IEC 10646 | のUTFは | "UCS Transformation Format"の略 |
Unicode | のUTFは | "Unicode Transformation Format"の略 |
そこで表を書き直すと次のようになります。
BOMバイト列 | : | 符号化文字集合 | : | 文字符号化方式 | : | 備考 |
――――――――――――――――――――――――――――――――――― | ||||||
00 00 FE FF | : | UCS-4 | : | UTF-32 | : | ビッグエンディアン(1234の順) |
FF FE 00 00 | : | UCS-4 | : | UTF-32 | : | リトルエンディアン(4321の順) |
00 00 FF FE | : | UCS-4 | : | UTF-32 | : | 普通でないオクテットの並び(2143) |
FE FF 00 00 | : | UCS-4 | : | UTF-32 | : | 普通でないオクテットの並び(3412) |
FE FF ## ## | : | Unicode | : | UTF-16 | : | ビッグエンディアン |
FF FE ## ## | : | Unicode | : | UTF-16 | : | リトルエンディアン |
EF BB BF | : | Unicode | : | UTF-8 | : |
最初の1バイトが00の場合
最初の1バイトがFEの場合:
次のセクションを読んでいきましょう。
3バイト目がFEの場合:UCS-4 ビッグエンディアン(1234の順)
3バイト目がFFの場合:UCS-4 普通でないオクテットの並び(2143)
最初の1バイトがEFの場合:UTF-83バイト目がFFの場合:UCS-4 普通でないオクテットの並び(2143)
最初の1バイトがFEの場合:
3バイト目が00の場合:UCS-4 普通でないオクテットの並び(3412)
3バイト目が00でない場合:UTF-16 ビッグエンディアン
最初の1バイトがFFの場合:UTF-16 リトルエンディアン3バイト目が00でない場合:UTF-16 ビッグエンディアン
----W3C勧告----
Without a Byte Order Mark:
----W3C勧告----00 00 00 3C | UCS-4 or other encoding with a 32-bit code unit and ASCII characters encoded as ASCII values, in respectively big-endian (1234), little-endian (4321) and two unusual byte orders (2143 and 3412).The encoding declaration must be read to determine which of UCS-4 or other supported 32-bit encodings applies. |
3C 00 00 00 | |
00 00 3C 00 | |
00 3C 00 00 | |
00 3C 00 3F | UTF-16BE or big-endian ISO-10646-UCS-2 or other encoding with a 16-bit code unit in big-endian order and ASCII characters encoded as ASCII values (the encoding declaration must be read to determine which) |
3C 00 3F 00 | UTF-16LE or little-endian ISO-10646-UCS-2 or other encoding with a 16-bit code unit in little-endian order and ASCII characters encoded as ASCII values (the encoding declaration must be read to determine which) |
3C 3F 78 6D | UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns for the relevant ASCII characters, the encoding declaration itself may be read reliably |
4C 6F A7 94 | EBCDIC (in some flavor; the full encoding declaration must be read to tell which code page is in use) |
Other | UTF-8 without an encoding declaration, or else the data stream is mislabeled (lacking a required encoding declaration), corrupt, fragmentary, or enclosed in a wrapper of some kind |
----日本語訳----
次のセクションを読みます。
バイトオーダーマークが付いていない場合は次のようになる
----日本語訳----00 00 00 3C | UCS-4または他の32bitコード単位の文字符号化方式でASCII値で符号化したASCII文字。左のそれぞれはビッグエンディアン(1234)、リトルエンディアン(4321),それと普通ではないバイトの並び(2143と3412)。UCS-4か他の32bit符号化方式を適用するかを決定するためにエンコーディング宣言を読まなければならない。 |
3C 00 00 00 | |
00 00 3C 00 | |
00 3C 00 00 | |
00 3C 00 3F (<?) | UTF-16BE またはビッグエンディアンのISO-10646-UCS-2 もしくは、16bitコード単位のビッグエンディアンの文字符号化方式でASCII値で符号化したASCII文字 (3つの内のどれであるかはエンコーディング宣言を読まなければならない。) |
3C 00 3F 00 (<?) | UTF-16LE またはリトルエンディアンのISO-10646-UCS-2 もしくは、16bitコード単位のリトルエンディアンの文字符号化方式でASCII値で符号化したASCII文字 (3つの内のどれであるかはエンコーディング宣言を読まなければならない。) |
3C 3F 78 6D (<?xml) | UTF-8、ISO 646、ASCII、ISO 8859の各パート、Shift-JIS、EUC、 他の7ビットの固定長、8ビット固定長、7-8の可変長の符号化方式でASCII値で符号化したASCII文字 (それらの内のどれであるかはエンコーディング宣言を読まなければならない。) |
4C 6F A7 94 | EBCDIC (または、その一部。どのコードページを使うかを知るにはエンコーディング宣言を全部読まなければならない。) |
Other | エンコーディング宣言なしのUTF-8か、もしくは間違って名前付けされたデータストリーム(必要なエンコーディング宣言が欠落している)か、損傷しているか、文書の断片か、何らかの形式でラップされている。 |
----W3C勧告----
Note:
Because the contents of the encoding declaration are restricted to characters from the ASCII repertoire (however encoded), a processor can reliably read the entire encoding declaration as soon as it has detected which family of encodings is in use. Since in practice, all widely used character encodings fall into one of the categories above, the XML encoding declaration allows reasonably reliable in-band labeling of character encodings, even when external sources of information at the operating-system or transport-protocol level are unreliable. Character encodings such as UTF-7 that make overloaded usage of ASCII-valued bytes may fail to be reliably detected.
Once the processor has detected the character encoding in use, it can act appropriately, whether by invoking a separate input routine for each case, or by calling the proper conversion function on each character of input.
Like any self-labeling system, the XML encoding declaration will not work if any software changes the entity's character set or encoding without updating the encoding declaration. Implementors of character-encoding routines should be careful to ensure the accuracy of the internal and external information used to label the entity.
----W3C勧告----
In cases above which do not require reading the encoding declaration to determine the encoding, section 4.3.3 still requires that the encoding declaration, if present, be read and that the encoding name be checked to match the actual encoding of the entity. Also, it is possible that new character encodings will be invented that will make it necessary to use the encoding declaration to determine the encoding, in cases where this is not required at present.
This level of autodetection is enough to read the XML encoding declaration and parse the character-encoding identifier, which is still necessary to distinguish the individual members of each family of encodings (e.g. to tell UTF-8 from 8859, and the parts of 8859 from each other, or to distinguish the specific EBCDIC code page in use, and so on).Because the contents of the encoding declaration are restricted to characters from the ASCII repertoire (however encoded), a processor can reliably read the entire encoding declaration as soon as it has detected which family of encodings is in use. Since in practice, all widely used character encodings fall into one of the categories above, the XML encoding declaration allows reasonably reliable in-band labeling of character encodings, even when external sources of information at the operating-system or transport-protocol level are unreliable. Character encodings such as UTF-7 that make overloaded usage of ASCII-valued bytes may fail to be reliably detected.
Once the processor has detected the character encoding in use, it can act appropriately, whether by invoking a separate input routine for each case, or by calling the proper conversion function on each character of input.
Like any self-labeling system, the XML encoding declaration will not work if any software changes the entity's character set or encoding without updating the encoding declaration. Implementors of character-encoding routines should be careful to ensure the accuracy of the internal and external information used to label the entity.
----日本語訳----
仕様を整理すると次のようになります。
注意:
エンコーディング宣言の内容は(符号化されているとしても)ASCIIレパートリーの文字に制限してあるので、どの系統の符号化が使用されているかを検知すれば、プロセッサはエンコーディング宣言全体を確実に読み込むことができる。実際には、広く使荒れている文字符号化方式は上記のカテゴリのどれかに当てはまるので、OSや伝送プロトコルレベルが提供する外部情報が信頼できない場合であっても、エンコーディング宣言は文字符号化方式の(入力ストリームの)内部的な名前を使って合理的で信頼性のある手段となる。ASCIIのコード値のバイト列を上書きして使っている例えば、UTF-7のような文字符号化方式は確実に検出できないことがある。
プロセッサが一度、使われている文字符号化方式を検出すれば、それぞれの場合に応じた別の入力ルーチンを呼び出すか入力のそれぞれの文字に正しい変換関数を呼び出すことで、適切に動作することができる。
自分自身にラベルを付けるシステムならどんなものでも同様であるが、もし、エンコーディング宣言を更新せずにソフトウェアが実体の文字集合や文字符号化方式を変えた場合、エンコーディング宣言は機能しない。文字符号化方式のルーチンの実装者は、実体の名前付けに使用する内部と外部の情報の正確さを確保することに配慮すべきである。
----日本語訳----
上の場合の中で、文字符号化方式を決定するのにエンコーディング宣言を読み取ることを必要としない場合でも、セクション4.3.3がエンコーディング宣言の仕様に要求するように、もしあるなら、文字符号化方式名を読み込まねばらず、
実際に実体を符号化している文字符号化方式と一致するかをチェックしなければならない。また、現在、既存の文字符号化方式の中には決定するためにエンコーディング宣言を必要としないモノもあるが、新しい文字符号化方式ができることによって既存の文字符号化方式と同じようなバイト列になるためにエンコーディング宣言が必要になる可能性もある。
自動検知のレベルは、エンコーディング宣言を読み込み、文字符号化方式の識別子を解析すれば十分である。ただし、まだ同系統の文字符号化方式のどれになるか区別する必要はある。(例えば、UTF-8を8859から区別する、8859の各パート同士を区別する、または使用している特定のEBCDICコードページを区別する、等々)実際に実体を符号化している文字符号化方式と一致するかをチェックしなければならない。また、現在、既存の文字符号化方式の中には決定するためにエンコーディング宣言を必要としないモノもあるが、新しい文字符号化方式ができることによって既存の文字符号化方式と同じようなバイト列になるためにエンコーディング宣言が必要になる可能性もある。
エンコーディング宣言の内容は(符号化されているとしても)ASCIIレパートリーの文字に制限してあるので、どの系統の符号化が使用されているかを検知すれば、プロセッサはエンコーディング宣言全体を確実に読み込むことができる。実際には、広く使荒れている文字符号化方式は上記のカテゴリのどれかに当てはまるので、OSや伝送プロトコルレベルが提供する外部情報が信頼できない場合であっても、エンコーディング宣言は文字符号化方式の(入力ストリームの)内部的な名前を使って合理的で信頼性のある手段となる。ASCIIのコード値のバイト列を上書きして使っている例えば、UTF-7のような文字符号化方式は確実に検出できないことがある。
プロセッサが一度、使われている文字符号化方式を検出すれば、それぞれの場合に応じた別の入力ルーチンを呼び出すか入力のそれぞれの文字に正しい変換関数を呼び出すことで、適切に動作することができる。
自分自身にラベルを付けるシステムならどんなものでも同様であるが、もし、エンコーディング宣言を更新せずにソフトウェアが実体の文字集合や文字符号化方式を変えた場合、エンコーディング宣言は機能しない。文字符号化方式のルーチンの実装者は、実体の名前付けに使用する内部と外部の情報の正確さを確保することに配慮すべきである。
■XMLプロセッサがサポート可能な文字符号化方式
XMLの仕様はサポート可能な文字符号化方式は、ASCII互換を前提にしていると言って良いでしょう。そのため、ASCIIと互換性のないUTF-7のような文字符号化方式は仕様が許す処理では正しく行えないとしています。
■仕様が考える実装のヒント
BOMによって確定できる文字符号化方式は現在のところ1つです。一方BOM無で最初の数バイトによって確定できる文字符号化方式は現在においても複数(エンコーディングファミリ)です。
また、今後現れる文字符号化方式がBOMと同じバイト列を持つことによってBOMで確定できる文字符号化方式も1つではなく、複数になりえます。よって、文字符号化方式の処理は常に複数を対象にしてまとめておくほうが拡張性の観点で良いと言えます。
処理パターンは次のようにできます。
■処理の判定の修正また、今後現れる文字符号化方式がBOMと同じバイト列を持つことによってBOMで確定できる文字符号化方式も1つではなく、複数になりえます。よって、文字符号化方式の処理は常に複数を対象にしてまとめておくほうが拡張性の観点で良いと言えます。
処理パターンは次のようにできます。
1. | 先頭の4バイトを使って文字符号化方式のファミリ(同一の先頭バイト列を持つ異なる文字符号化方式)を分類する |
2. | エンコーディング宣言を使ってファミリの中から1つを選択する(ファミリが現在1つの場合もチェックする) |
処理パターンの整理を使って処理を修整します。
■本コラムで対応する文字符号化方式と処理の修正1. | 先頭の4バイトを使って文字符号化方式のファミリ(同一の先頭バイト列を持つ異なる文字符号化方式)を分類する |
1-1. | 4バイト分を取得する | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1-2. | 次の一致する文字符号化方式をListに追加する
|
2. | エンコーディング宣言を使ってファミリの中から1つを選択する(ファミリが現在1つの場合もチェックする) |
2-1. | 指定エンコーディング宣言まで読み込む |
2-2. | 指定エンコーディングの識別子がリスト内にあるかチェックする |
2-2-1. | 一致した場合 :一致した符号化方式を符号化方式として設定する。 |
2-2-2. | 一致しない場合:致命的なエラーにする |
対応する文字符号化方式は
とします。
処理は次のようになります。
■ソフトウェア構成における入力ストリーム作成位置の検討文字符号化方式 | : | EncName |
――――――――――― | ||
UTF-8 BOM無 | : | UTF-8 |
UTF-8 BOM付 | : | UTF-8 |
UTF-16 BOM付BE | : | UTF-16 |
UTF-16 BOM付LE | : | UTF-16 |
処理は次のようになります。
1. | 先頭の4バイトを使って文字符号化方式のファミリ(同一の先頭バイト列を持つ異なる文字符号化方式)を分類する |
1-1. | 4バイト分を取得する | |||||||||||||||||||||||||||||||||||
1-2. | 次の一致する文字符号化方式をListに追加する
※1.0のXML文書の場合、XML宣言は省略可能です。 |
2. | その他の場合:UTF-8にする |
3. | その他の場合以外の場合、エンコーディング宣言を使ってファミリの中から1つを選択する(ファミリが現在1つの場合もチェックする) |
3-1. | 指定エンコーディング宣言まで読み込む |
3-2. | 指定エンコーディングの識別子がファミリ内にあるかチェックする |
3-2-1. | ある場合:一致した符号化方式を符号化方式として設定する。 |
3-2-2. | ない場合:致命的なエラーにする |
-ソフトウェア構成の現状
現在の実装では、FileInputStreamとInputStreamReaderの処理はDocumentTokenizerのコンストラクタ内で継承先のBaseFileTokenizerが実行しています。
-実装と修正のための問題点
2つの問題があります。
1つ目は、自動検知機能の処理には、仕様上、致命的なエラーを発生させる場合がありますが、コンストラクタ内で致命的なエラーが発生するとインスタンスは不完全になり、利用してはいけないオブジェクトになることです。
2つ目は、JavaのInputStreamReaderのUTF-8への対応の問題です。残念なことに、InputStreamReaderに文字符号化方式としてUTF-8を指定して、UTF-8にBOM付を指定すると、BOM部分を文字として取得してしまい、これまでの字句解析の実装でWORDトークンとなるため構文解析でエラーになります。
-対策1つ目は、自動検知機能の処理には、仕様上、致命的なエラーを発生させる場合がありますが、コンストラクタ内で致命的なエラーが発生するとインスタンスは不完全になり、利用してはいけないオブジェクトになることです。
2つ目は、JavaのInputStreamReaderのUTF-8への対応の問題です。残念なことに、InputStreamReaderに文字符号化方式としてUTF-8を指定して、UTF-8にBOM付を指定すると、BOM部分を文字として取得してしまい、これまでの字句解析の実装でWORDトークンとなるため構文解析でエラーになります。
2つの問題に対処するために、無条件字句解析器の引数はBufferedReaderに変更します。BufferedReaderのインスタンスは、自動検知機能で取得した文字符号化方式のオブジェクトから取得し、無条件字句解析器に渡します。
また、UTF-8BOM付の文字符号化方式のオブジェクトでBufferdReaderを取得する場合は、先頭3バイトを読み捨ててから(BOMをスキップした後に)渡します。
また、UTF-8BOM付の文字符号化方式のオブジェクトでBufferdReaderを取得する場合は、先頭3バイトを読み捨ててから(BOMをスキップした後に)渡します。
コメント
コメントを投稿する
SpecialPR