Javaの文字タイプの詳細

Javaの1.1バージョンでは、文字を処理するためのいくつかのクラスが導入されています。これらの新しいクラスは、プラットフォーム固有の文字値の概念からUnicode値に変換するための抽象化を作成します。このコラムでは、何が追加されたか、およびこれらの文字クラスを追加する動機について説明します。

charと入力します

おそらく、C言語で最も乱用されている基本型はchar型です。チャー8ビットであると定義されているため、型は、部分的に悪用されており、過去25年間、8ビットはまた、コンピュータ上のメモリの最小不可分チャンクを定義しています。後者の事実とASCII文字セットが7ビットに収まるように定義されているという事実を組み合わせると、char型は非常に便利な「ユニバーサル」型になります。さらに、Cでは、char型の変数へのポインタがユニバーサルポインタ型になりました。これは、charとして参照できるものはすべて、キャストを使用して他の型としても参照できるためです。

C言語でのchar型の使用と乱用により、コンパイラの実装間で多くの非互換性が生じたため、CのANSI規格では、2つの特定の変更が行われました。ユニバーサルポインタがvoidの型を持つように再定義されたため、明示的なものが必要になりました。プログラマーによる宣言。また、文字の数値は符号付きであると見なされ、数値計算で使用される場合の文字の処理方法が定義されています。その後、1980年代半ばに、エンジニアとユーザーは、8ビットでは世界のすべての文字を表すには不十分であることに気づきました。残念ながら、その時までに、Cは非常に定着していたため、人々は文字の定義を変更することを望まず、おそらく不可能でさえありました。タイプ。今度は、90年代、Javaの初期の始まりに向けてフラッシュフォワードします。Java言語の設計に定められた多くの原則の1つは、文字は16ビットになるというものでした。この選択は、多くの異なる言語で多くの異なる種類の文字を表す標準的な方法であるUnicodeの使用をサポートします。残念ながら、それはまた、現在修正されつつあるさまざまな問題の準備を整えました。

とにかくキャラクターとは何ですか?

私は「だから何、私は自分自身が質問を見つけたとき、私はトラブルに知っていたある文字は?」ええと、キャラクターは文字ですよね?たくさんの文字が単語を構成し、単語が文を形成します。ただし、実際には、グリフと呼ばれるコンピュータ画面上の文字の表現と、と呼ばれるグリフを指定する数値との関係はcode point、実際にはまったく単純ではありません。

私は自分が英語のネイティブスピーカーであることを幸運だと思っています。第一に、それは現代のデジタルコンピュータの設計と開発に貢献したかなりの数の人々の共通言語だったからです。第二に、グリフの数が比較的少ないためです。 ASCII定義には、英語の記述に使用できる96個の印刷可能な文字があります。これを中国語と比較してください。中国語では、20,000を超えるグリフが定義されており、その定義は不完全です。 MorseおよびBaudotコードの初期の頃から、英語の全体的な単純さ(グリフが少ない、出現の統計的頻度)により、英語はデジタル時代の共通語になっています。しかし、デジタル時代に入る人々の数が増えるにつれて、英語を母国語としない人の数も増えています。数が増えるにつれて、コンピュータがASCIIを使用し、英語しか話せないことを受け入れることをますます嫌う人が増えています。これにより、コンピュータが理解する必要のある「文字」の数が大幅に増加しました。その結果、コンピューターによってエンコードされるグリフの数は2倍になりました。

由緒ある7ビットASCIIコードがISOLatin-1(またはISO 8859_1、「ISO」は国際標準機構)と呼ばれる8ビット文字エンコーディングに組み込まれると、使用可能な文字数が2倍になりました。エンコーディング名で収集したかもしれませんが、この標準では、ヨーロッパ大陸で使用されているラテン語由来の言語の多くを表現できました。ただし、標準が作成されたからといって、それが使用可能であるとは限りませんでした。当時、多くのコンピューターは、8ビット文字で表される可能性のある他の128個の「文字」をすでに使用し始めていました。これらの余分な文字の使用の2つの生き残った例は、IBMパーソナルコンピューター(PC)と、これまでで最も人気のあるコンピューター端末であるDigital Equipment CorporationVT-100です。後者は、ターミナルエミュレータソフトウェアの形で存続します。

8ビット文字の実際の死の時期は間違いなく数十年にわたって議論されるでしょうが、1984年のMacintoshコンピュータの導入でそれを釘付けにします。Macintoshは2つの非常に革新的な概念を主流のコンピューティングにもたらしました。羊;およびWorldScriptは、任意の言語で文字を表すために使用できます。もちろん、これはXeroxがタンポポクラスのマシンでスターワードプロセッシングシステムの形で出荷していたものの単なるコピーでしたが、Macintoshはこれらの新しい文字セットとフォントをまだ「ダム」端末を使用している聴衆にもたらしました。一度始めたら、異なるフォントの使用を止めることはできませんでした-それはあまりにも多くの人々にとってあまりにも魅力的でした。 80年代後半までに、これらすべての文字の使用を標準化するというプレッシャーは、1990年に最初の仕様を発表したユニコードコンソーシアムの設立で頭角を現しました。残念ながら、80年代から90年代にかけて、文字セットの数は倍増しました。当時、新しい文字コードを作成していたエンジニアのほとんどは、初期のUnicode標準が実行可能であると考えていたため、コードからグリフへの独自のマッピングを作成しました。したがって、Unicodeは十分に受け入れられていませんでしたが、使用可能な文字は128文字または最大256文字であるという概念は完全になくなりました。 Macintoshの後、さまざまなフォントのサポートがワードプロセッシングの必須機能になりました。 8ビットの文字が消えていきました。80年代から90年代にかけても、文字セットの数は倍増しました。当時、新しい文字コードを作成していたエンジニアのほとんどは、初期のUnicode標準が実行可能であると考えていたため、コードからグリフへの独自のマッピングを作成しました。したがって、Unicodeは十分に受け入れられていませんでしたが、使用可能な文字は128文字または最大256文字であるという概念は完全になくなりました。 Macintoshの後、さまざまなフォントのサポートがワードプロセッシングの必須機能になりました。 8ビットの文字が消えていきました。80年代から90年代にかけても、文字セットの数は倍増しました。当時、新しい文字コードを作成していたエンジニアのほとんどは、初期のUnicode標準が実行可能であると考えていたため、コードからグリフへの独自のマッピングを作成しました。したがって、Unicodeは十分に受け入れられていませんでしたが、使用可能な文字は128文字または最大256文字であるという概念は完全になくなりました。 Macintoshの後、さまざまなフォントのサポートがワードプロセッシングの必須機能になりました。 8ビットの文字が消えていきました。使用可能な文字が128文字または最大256文字しかないという概念は完全になくなりました。 Macintoshの後、さまざまなフォントのサポートがワードプロセッシングの必須機能になりました。 8ビットの文字が消えていきました。使用可能な文字が128文字または最大256文字しかないという概念は完全になくなりました。 Macintoshの後、さまざまなフォントのサポートがワードプロセッシングの必須機能になりました。 8ビットの文字が消えていきました。

JavaとUnicode

私は1992年にSunのOakグループ(Java言語は最初に開発されたときはOakと呼ばれていました)に参加したときにこの話に入りました。基本型charJavaで唯一の符号なし型である16個の符号なしビットとして定義されました。 16ビット文字の理論的根拠は、Unicode文字表現をサポートするため、JavaがUnicodeでサポートされる任意の言語で文字列を表現するのに適しているということでした。しかし、文字列を表現できることとそれを印刷できることは、常に別々の問題でした。 Oakグループでの経験のほとんどがUnixシステムとUnix派生システムからのものであることを考えると、最も快適な文字セットは、やはりISOLatin-1でした。また、グループのUnixの伝統により、Java I / Oシステムの大部分はUnixストリームの抽象化に基づいてモデル化され、すべてのI / Oデバイスを8ビットバイトのストリームで表すことができました。この組み合わせにより、8ビットの入力デバイスとJavaの16ビット文字の間の言語に何らかの誤りが残りました。したがって、Java文字列を8ビットストリームから読み書きする必要がある場合はどこでも、8ビット文字を16ビットユニコードに魔法のようにマッピングするための小さなコード、ハックがありました。

Java Developer Kit(JDK)の1.0バージョンでは、入力ハックはDataInputStreamクラス内にあり、出力ハックはPrintStreamクラス全体でした。 (実際には、TextInputStreamJavaのアルファ2リリースで名前が付けられた入力クラスがありましたが、実際のリリースではDataInputStreamハックに取って代わられました。)これは、Javaに相当するCを必死に検索するため、初心者のJavaプログラマーにとって引き続き問題を引き起こします。関数getc()。次のJava1.0プログラムについて考えてみます。

インポートjava.io. *; public class bogus {public static void main(String args []){FileInputStream fis; DataInputStream dis; char c; {fis = new FileInputStream( "data.txt");を試してください。 dis = new DataInputStream(fis); while(true){c = dis.readChar(); System.out.print(c); System.out.flush(); if(c == '\ n')break; } fis.close(); } catch(例外e){} System.exit(0); }}

一見すると、このプログラムはファイルを開き、一度に1文字ずつ読み取り、最初の改行が読み取られると終了するように見えます。ただし、実際には、ジャンク出力が得られます。また、ジャンクになる理由は、readCharが16ビットのUnicode文字を読み取りSystem.out.print、ISO Latin- 18ビット文字であると想定しているものを出力するためです。あなたが使用するために上記のプログラム変更する場合は、のreadlineの機能をDataInputStream、それが仕事に表示されますので、内のコードのreadLineUnicode仕様への受け渡しのうなずきで「変更されたUTF-8」として定義されている形式を読み取ります。 (UTF-8は、Unicodeが8ビット入力ストリームでUnicode文字を表すために指定する形式です。)したがって、Java 1.0の状況では、Java文字列は16ビットUnicode文字で構成されますが、マップするマッピングは1つだけです。 ISOLatin-1文字をUnicodeに変換します。幸い、Unicodeはコードページ「0」(つまり、上位8ビットがすべてゼロである256文字)をISOLatin-1セットに正確に対応するように定義しています。したがって、マッピングは非常に簡単であり、ISO Latin-1文字ファイルのみを使用している限り、データがファイルを離れ、Javaクラスによって操作されてから、ファイルに書き換えられるときに問題は発生しません。 。

入力変換コードをこれらのクラスに埋め込むことには、2つの問題がありました。すべてのプラットフォームが変更されたUTF-8形式で多言語ファイルを保存したわけではありません。そして確かに、これらのプラットフォーム上のアプリケーションは、必ずしもこの形式の非ラテン文字を期待していませんでした。したがって、実装サポートは不完全であり、後のリリースで必要なサポートを追加する簡単な方法はありませんでした。

Java1.1およびUnicode

The Java 1.1 release introduced an entirely new set of interfaces for handling characters, called Readers and Writers. I modified the class named bogus from above into a class named cool. The cool class uses an InputStreamReader class to process the file rather than the DataInputStream class. Note that InputStreamReader is a subclass of the new Reader class and the System.out is now a PrintWriter object, which is a subclass of the Writer class. The code for this example is shown below:

import java.io.*; public class cool { public static void main(String args[]) { FileInputStream fis; InputStreamReader irs; char c; try { fis = new FileInputStream("data.txt"); irs = new InputStreamReader(fis); System.out.println("Using encoding : "+irs.getEncoding()); while (true) { c = (char) irs.read(); System.out.print(c); System.out.flush(); if (c == '\n') break; } fis.close(); } catch (Exception e) { } System.exit(0); } } 

The primary difference between this example and the previous code listing is the use of the InputStreamReader class rather than the DataInputStream class. Another way in which this example is different from the previous one is that there is an additional line that prints out the encoding used by the InputStreamReader class.

The important point is that the existing code, once undocumented (and ostensibly unknowable) and embedded inside the implementation of the getChar method of the DataInputStream class, has been removed (actually its use is deprecated; it will be removed in a future release). In the 1.1 version of Java, the mechanism that performs the conversion is now encapsulated in the Reader class. This encapsulation provides a way for the Java class libraries to support many different external representations of non-Latin characters while always using Unicode internally.

Of course, like the original I/O subsystem design, there are symmetric counterparts to the reading classes that perform writing. The class OutputStreamWriter can be used to write strings to an output stream, the class BufferedWriter adds a layer of buffering, and so on.

Trading warts or real progress?

The somewhat lofty goal of the design of the Reader and Writerclasses was to tame what is currently a hodge-podge of representation standards for the same information by providing a standard way of converting back and forth between the legacy representation -- be it Macintosh Greek or Windows Cyrillic -- and Unicode. So, a Java class that deals with strings need not change when it moves from platform to platform. This might be the end of the story, except that now that the conversion code is encapsulated, the question arises as to what that code assumes.

このコラムを調べていると、秘書がカーボン紙を入れるのがかなり簡単だったので、コピー機が不要であるというゼロックスの幹部(ゼロックスになる前、ハロイド社だった)からの有名な引用を思い出しました。彼女のタイプライターと彼女がオリジナルを作成している間にドキュメントのコピーを作成します。もちろん、後から明らかなことは、コピー機は、文書を生成する人よりも、文書を受け取る人にはるかに多くの利益をもたらすということです。JavaSoftは、システムのこの部分の設計における文字エンコードクラスとデコードクラスの使用に関する同様の洞察の欠如を示しています。