なたで日記

いろいろな思ったこと書きますヽ(^▽^ゞ) by natade

Posts Tagged ‘文字列処理

プログラミングのアイデア1

leave a comment »


適当に思いついたプログラミングアイデアのメモ。

・オートフォーカス
オートフォーカスとはカメラのピントを自動で合わせるもの。
ピントがあっているということは、画像がクッキリしているということ。
クッキリしているということは、高域の周波数成分が大きいということ。
ということで、ピントを段々いろいろと試していって、
もっとも高域の周波数成分が大きくなるところを探す。
そこがピントが合っている部分と考えられる。

・文章をスキャナで取り込んだ画像の傾きの自動補正
画像を大津の判別分析法とかで2値化する。
2値化した画像に対して、毎行(x軸方向)ごとの黒色の値をカウントする。
このx軸方向にカウントした値の列をベクトルとみなす。
ここで、画像が傾いている場合は、このベクトルの各値が滑らかなにつながっていると予想される。
従って、あらゆる傾きに対して、上記のベクトルを調べる。
このベクトルの中で、もっとも高周波数成分が含まれる傾きが、
画像が水平になっていると思われる。

・文字列のあいまい検索
検索したい文字列を X
Xを用いて検索する文章を Y
まずXに含まれるワードを保存しておく。
(漢字とか、カタカナとかでワード判定。あるいは辞書を使う。)
Yに対して、文章を句読点で区切りを分ける。
各文章ごとに、上記のワードを調べる。
全てのワードが含まれていれば、その文章に検索したい情報が含まれると考えられる。
あるいは、Y全体に対して上記のワードがどこに含まれるか調べる。
ワードが集中している箇所が、Xのことが書いてあると考えられる。

Written by なたで

2012年1月28日 at 16:58

Java の Sound API を使用すると文字化けする問題について

with 3 comments


Windows環境で、javax.sound.sampledを使用した以下のコード。

Mixer.Info[] mixerinfo = AudioSystem.getMixerInfo();
for(int i=0;i<mixerinfo.length;i++) {
	System.out.println("****\t"+i+"\t***");
	System.out.println(mixerinfo[i].getName());
}

上記のコードを利用すると、
ヘルプによれば

getName

public final String getName()
ミキサーの名前を取得します。
戻り値:
ミキサーの名前を表す文字列

と、名前を取得できるはずです。
しかし、日本語環境の場合、ミキサーの名前に全角文字があると、文字化けした名前を取得してしまいます。


「Port スピーカー」 → 「Port ?X?s?[?J?[」
「Port ライン入力」 → 「Port ???C??????」
「Port マイク」 → 「Port ?}?C?N」
「Port SPDIF出力」 → 「Port SPDIF????」
「Port SPDIF入力」 → 「Port SPDIF?o??」
「Port 再生リダイレクト」 → 「Port ??¶???_?C???N?g」

ネットでこの問題を探してみると、
Java の Sound API を使用した際に文字化けが起こってしまう問題に関しての質問です。
のように困っている人もいたりします。

なぜこういう自体が起こっているかというと、
多分内部で文字コードの変換が適切に行われていないためだと考えられます。
海外では話題が見つからなかったことから、誰か教えにいかないと多分治らないです。

解決策として、例えば。
「Port ???C??????」
これに関して、

for(int i=0;i<x.length();i++) {
	System.out.println((int)x.charAt(i));
}

を実行すると

「 80 111 114 116 32 131 137 131 67 131 147 147 252 151 205」

となることから、?の部分でも、しっかりコードが取得できていることが分かるので、

一度byte[]に変換した後に、
ByteArrayInputStream で、このバイト列を入力ストリームとして、

ByteArrayInputStream is = new ByteArrayInputStream(binary);
String charsetName = "JISAutoDetect";
InputStreamReader inputreader = new InputStreamReader(is, charsetName);
BufferedReader br = new BufferedReader(inputreader);

みたいな形で文字を読みこめば、文字化けを治すことができます。
ByteBufferと、CharsetDecoderでも出来るかも。

ただ一つだけ問題があって分からないことがありました。
再生リダイレクト」が「??¶???_?C???N?g」のように文字化けをしていて、
実際の文字コードは、

「141 196 144 182 131 138 131  95 131  67 131 140 131  78 131 103」

となるはずが、charAtで取得すると

「141 272 182 131 138 131  95 131  67 131 140 131  78 131 103」

となってしまうのです。

「再生」が「141 196 144 182」のはずなのに「141 272 182」

196 0b11000100 0xC4
144 0b10010000 0x90

がなぜ

272 0b0000000100010000 0x0110

となってしまうのか。
誰か分かった方いたら教えてください。

Written by なたで

2011年7月24日 at 19:08

カテゴリー: program

Tagged with , , ,

Stringとint[]の相互変換

leave a comment »


charAt1文字を1変数(コードポイントで)に割り当てたい。
そんな要望からStringint[]との相互変換を行ってみます。
使い方はお察し下さい。

文字列から数値配列へ

    static public int[] toInteger(String text) {
        int textlength = text.length();
        for (int i = 0, j = text.length(); i < j; i++) {
            if (Character.isHighSurrogate(text.charAt(i))) {
                textlength––;
                i++;
            }
        }
        int[] out = new int[textlength];
        for (int i = 0, j = text.length(), p = 0; i < j; i++, p++) {
            int c = text.charAt(i);
            if (!Character.isHighSurrogate(text.charAt(i))) {
                out[p] = c;
            } else {
                out[p] = toCodePoint(c, text.charAt(i + 1));
                i++;
            }
        }
        return (out);
    }

数値配列から文字列へ

    static public String toString(int[] text) {
        StringBuilder out = new StringBuilder();
        for (int i = 0, j = text.length; i < j; i++) {
            out.append(Character.toChars(text[i]));
        }
        return (out.toString());
    }

サロゲートペアとか

    static public int getHighSurrogate(int x) {
        x -= 0×10000;
        x >>= 10;
        x += 0xD800;
        return (x);
    }
    static public int getLowSurrogate(int x) {
        x -= 0×10000;
        x &= 0x3FF;
        x += 0xDC00;
        return (x);
    }
    static public int toCodePoint(int high, int low) {
        high -= 0xD800;
        high <<= 10;
        low -= 0xDC00;
        low |= high;
        low += 0×10000;
        return (low);
    }

※ 「Character.toCodePoint」とかぶってた。

数値配列の検索とか

    static public int indexOf(int[] in, int[] target, int offset) {
        final int ilength = in.length – target.length + 1;
        final int tlength = target.length;
        // 高速化のために頭の文字だけ配列からだしておく
        final int sento = target[0];
        if (offset >= ilength) {
            return (-1);
        }
        // 検索対象が1文字の場合
        int i;
        if (tlength == 0) {
            for (i = offset; i < ilength; i++) {
                if (in[i] == sento) {
                    return (i);
                }
            }
            return (-1);
        }
        // 検索対象が複数の場合
        int j;
        for (i = offset; i < ilength; i++) {
            if (in[i] == sento) {
                i++;
                for (j = 1; j < tlength; j++, i++) {
                    if (in[i] != target[j]) {
                        break;
                    }
                }
                if (j == tlength) {
                    return (i – tlength);
                } else {
                    i -= j;
                }
            }
        }
        return (-1);
    }

数値配列の置換とか

    static public int[] getReplace(int[] in, int[] target, int[] replacement) {
        if ((target.length == replacement.length) && (target.length == 1)) {
            int tgt = target[0];
            int rep = replacement[0];
            int[] out = new int[in.length];
            System.arraycopy(in, 0, out, 0, in.length);
            for (int i = in.length – 1; i >= 0; i–) {
                if (out[i] == tgt) {
                    out[i] = rep;
                }
            }
            return (out);
        } else if (target.length < replacement.length) {
            return (toInteger(toString(in).replace(toString(target),
                    toString(replacement))));
        }
        int[] out = new int[in.length];
        int ilength = in.length;
        int tlength = target.length;
        int rlength = replacement.length;
        int inpoint = 0, outpoint = 0, index;
        while (true) {
            index = indexOf(in, target, inpoint);
            if (index == -1) {
                System.arraycopy(in, inpoint, out, outpoint, ilength – inpoint);
                outpoint += ilength – inpoint;
                break;
            }
            System.arraycopy(in, inpoint, out, outpoint, index – inpoint);
            outpoint += index – inpoint;
            inpoint += index – inpoint;
            System.arraycopy(replacement, 0, out, outpoint, rlength);
            inpoint += tlength;
            outpoint += rlength;
        }
        if (outpoint != ilength) {
            int[] out2 = new int[outpoint];
            System.arraycopy(out, 0, out2, 0, outpoint);
            return (out2);
        }
        return (out);
    }

Written by なたで

2010年5月9日 at 16:31

カテゴリー: program

Tagged with , ,