0

入力ファイルからのバイトデータで動作するハフマンコーディングをJavaで実装しました。ただし、ASCIIを圧縮する場合にのみ機能します。1 バイトを超える文字を処理できるように拡張したいのですが、これを正確に行う方法がわかりません。

private static final int CHARS = 256;     
private int [] getByteFrequency(File f) throws FileNotFoundException {
    try {
        FileInputStream fis = new FileInputStream(f);
        byte [] bb = new byte[(int) f.length()];
        int [] aa = new int[CHARS];
            if(fis.read(bb) == bb.length) {
                System.out.print("Uncompressed data: ");
                for(int i = 0; i < bb.length; i++) {
                        System.out.print((char) bb[i]);
                        aa[bb[i]]++;
                }
                System.out.println();
            }
        return aa;
    } catch (FileNotFoundException e) { throw new FileNotFoundException(); 
    } catch (IOException e) { e.printStackTrace(); }
    return null;
}

たとえば、これはファイル内の文字の頻度を取得するために使用しているものであり、明らかに単一バイトでのみ機能します。Unicode ファイルを指定すると、 で ArrayIndexOutOfBoundsException が発生しaa[bb[i]]++;ます。通常、i は負の数です。これは、 が 1 バイトしか見ておらず、Unicode 文字が複数になるためであることはわかってaa[bb[i]]++;いますが、どのように変更できるかわかりません。

誰か私にいくつかの指針を教えてもらえますか?

4

1 に答える 1

0

次のことを試してください。

private static final int CHARS = 256;     
private int [] getByteFrequency(File f) throws FileNotFoundException {
    try {
        FileInputStream fis = new FileInputStream(f);
        byte [] bb = new byte[(int) f.length()];
        int [] aa = new int[CHARS];
            if(fis.read(bb) == bb.length) {
                System.out.print("Uncompressed data: ");
                for(int i = 0; i < bb.length; i++) {
                        System.out.print((char) bb[i]);
                        aa[((int)bb[i])&0xff]++;
                }
                System.out.println();
            }
        return aa;
    } catch (FileNotFoundException e) { throw new FileNotFoundException(); 
    } catch (IOException e) { e.printStackTrace(); }
    return null;
}

私が正しければ(テストしていません)、あなたの問題は、バイトがJavaのSIGNED値であることです。整数へのキャスト + 0xff へのマスキングは、正しく処理する必要があります。

于 2012-11-01T09:42:05.317 に答える