0x82,0xA8,0x82,0xC8,0x82,0xA9,0x82,0xB7,0x82,0xA2,0x82,0xBD
という文字列を見かけたら、文字コードっぽいから、何の文章になっているか知りたくなるのが人情。
変換プログラムを何の言語で作るか(あるいはバイナリエディターで直接ファイルを作っちゃうとか)は人それぞれだと思うけど、Javaで作るとこんな感じ。
public class Convert {
public static void main(String[] args) throws java.io.UnsupportedEncodingException {
final int[] xs = { 0x82,0xA8,0x82,0xC8,0x82,0xA9,0x82,0xB7,0x82,0xA2,0x82,0xBD };
final byte[] b = new byte[xs.length];
for (int i = 0; i < xs.length; i++) b[i] = (byte)xs[i];
System.out.println(new String(b, "MS932"));
}
}
ちなみに直接バイト配列の初期値に設定しようと思ったけど、int→byteへの変換で「精度が落ちる」というコンパイルエラーが出るので、出来ない。
けど最近Scalaを勉強しているんだから、Scalaで書いてみよう(Javaだと毎回コンパイルがいるし)…と思って書いたのがこれ。
(直接バイト配列に入れようとするとエラーになるのはJavaと同じだった)
def f(xs:Int*) = {
val b = new Array[Byte](xs.length)
var i = 0
for (x <- xs) { b(i) = x.toByte; i += 1 }
new String(b, "MS932")
}
f(0x82,0xA8,0x82,0xC8,0x82,0xA9,0x82,0xB7,0x82,0xA2,0x82,0xBD)
でもこれ、Scalaプログラムとしては明らかに駄目駄目orz
で、Arrayの代わりにListBufferを使ってみた。
def f(xs:Int*) = {
val b = new scala.collection.mutable.ListBuffer[Byte]
for (x <- xs) b += x.toByte
new String(b.toArray, "MS932")
}
もうちょっと何とかなりそうな気もするけど、どうすればいいか思い付かず、とりあえずTwitterに出してみた。
(ツイートする為に一行にしたら136文字。ツイートは140文字までだから、ぎりぎりw)
そうしたら、mapを使えば?というアドバイスをいただいた。
なるほど、Scalaの本とかを見ているとfilterやらmapというのが出てきていた気がする。で出来たのがこれ。
def f(xs:Int*) = new String(xs.map(_.toByte).toArray, "MS932")
おお、これは何となくScalaっぽい気がする!
→Togetter「文字コードのデータを文字列に変換するプログラム」
まだScalaを勉強中なので、やはりfilterやmapといった関数は自力では思い付けないんだなぁ。
そういえば、自分が新しい言語を勉強するときは、(1)知っている言語の機能(構文)と比較する、(2)ライブラリーをざっと眺める(どんな関数・クラス・メソッドがあるかを知る)、をするんだけど、Scalaではまだそれが途中だった。
今のところ、Scalaの構文はtry~catchをメモしようと思って、形式がmatchに似てるからそちらを先にまとめていた。
ライブラリーの方は、PredefとStringのメソッドをざっと見てみただけ。
コレクション(ListとかListBuffer)のメソッドを眺めてみれば、filterとかmapが出てくるはず。(もしかしたらStringにもあったかもしれないが、あったとすればCharの並びを処理するもののはずで、そういった使い方を自分がするとは思えなかったから、読み飛ばしたかも)
その前にコンストラクターや関数リテラルの定義方法とかもまとめたい。…色々先は長いなー^^;
ちなみに「マップ」と聞くと、まずはJavaのMap(HashMap)が思い浮かぶ。
最近ではHadoopのMapReduceのMap処理とこんがらがる事も…。
これにScalaのようなmap関数(マッピングする=対応付ける?)が加わると、余計ややこしくなりそう^^;
(さらに某業界ではマップと言えば地図のことで、マッピングと言えば地図を描くことだが、さすがにこれは区別がつくかw)