ページ 11

javaのファイル内検索

Posted: 2012年11月12日(月) 16:48
by tomomi
java/javac/ibookG4/xterm

例えば、下記のようなファイルがあったとします。

   あ 3画 100 100 300
   い 2画 100 90
   さ 3画 80 70 50
   藤 18画 ・・・
   ‥

文字、画数、文字の長さ情報がそれぞれ書き込まれています。
流れとしては、画数を入力し、このファイルを読み込み、文字、画数、文字の長さ情報を出力するプログラムを作りたいです。
例えば、“3”と入力すると
   あ 3画 100 100 300
   さ 3画 80 70 50
というよな感じです。
初心者なので、ここまで複雑なファイル操作はやったこともありません。
先頭から2番目の配列の数字(1桁や二桁)を読み込むことはそもそも可能なのでしょうか。
indexOfメソッドが近いと思われますが、2次元の場合で、その列すべてを読み込むとなるとどうすればよいかわかりません。
お願いします。

Re: javaのファイル内検索

Posted: 2012年11月12日(月) 20:51
by かずま
tomomi さんが書きました:流れとしては、画数を入力し、このファイルを読み込み、文字、画数、文字の長さ情報を出力するプログラムを作りたいです。
例えば、“3”と入力すると
   あ 3画 100 100 300
   さ 3画 80 70 50
というよな感じです。
それだけでよいのなら、

コード:

$ cat Stroke.java
import java.io.*;

class Stroke {
    public static void main(String[] args) throws Exception {
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("> ");
            String s = br.readLine().trim();
            int stroke = Integer.parseInt(s);
            if (stroke <= 0) break;
            new Stroke(stroke, "data.txt");
        }
    }

    Stroke(int stroke, String fileName) throws IOException {
        String pattern = ".*[ \t ]" + stroke + "画.*";
        BufferedReader br =
            new BufferedReader(new FileReader(new File(fileName)));
        String s;
        while ((s = br.readLine()) != null)
            if (s.matches(pattern)) System.out.println(s);
    }
}

$ javac Stroke.java
$ cat data.txt
   あ 3画 100 100 300
   い 2画 100 90
   さ 3画 80 70 50
   藤 18画 ・・・
$ java Stroke
> 3
   あ 3画 100 100 300
   さ 3画 80 70 50
> 2
   い 2画 100 90
> 8
> 18
   藤 18画 ・・・
> 0
$ 
[ \t ] は、半角スペース、タブ、全角スペースです。
これがないと、8 が 18画とマッチしてしまいます。

Re: javaのファイル内検索

Posted: 2012年11月14日(水) 16:10
by tomomi
プログラムありがとうございます。
しかし、かずまさんのプログラムを実行すると、コンパイルはうまく通ったのですがエラーが出てしまいます。

$ javac Stoke.java
$ java Stoke
Exception in thread "main" java.lang.NoClassDefFoundError: Stoke



あと、やりたいことはもっと複雑で、TXTファイルに入っている、

   あ 3画 100 100 300
   い 2画 100 90
   さ 3画 80 70 50

などの、画数の後ろにある文字の長さ情報を取り出して、値の変換(ファイルには保存しない)をしたいと思っています。
最終的な形としては、入力するのは画数と文字の長さ情報で、入力された値と登録されているデータを変換していき、同じ画数の中で、値の一番近いものを選び出すという流れにしたいのです。
なので、私が想像していたのは、ファイルの中身を2次元配列にして、画数を調べ、文字の長さ情報を持ってくる、、、
というような感じでした。
そこで、かずまさんに相談したいのですが、私の考えている2次元配列を用いたやり方でもこのプログラムを作ることは可能でしょうか。


かずま さんが書きました: それだけでよいのなら、

コード:

$ cat Stroke.java
import java.io.*;

class Stroke {
    public static void main(String[] args) throws Exception {
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("> ");
            String s = br.readLine().trim();
            int stroke = Integer.parseInt(s);
            if (stroke <= 0) break;
            new Stroke(stroke, "data.txt");
        }
    }

    Stroke(int stroke, String fileName) throws IOException {
        String pattern = ".*[ \t ]" + stroke + "画.*";
        BufferedReader br =
            new BufferedReader(new FileReader(new File(fileName)));
        String s;
        while ((s = br.readLine()) != null)
            if (s.matches(pattern)) System.out.println(s);
    }
}

Re: javaのファイル内検索

Posted: 2012年11月14日(水) 16:46
by tomomi
たった今、エラーが消えました。すみません!

Re: javaのファイル内検索

Posted: 2012年11月15日(木) 05:23
by かずま
tomomi さんが書きました: $ java Stoke
Exception in thread "main" java.lang.NoClassDefFoundError: Stoke
エラーメッセージをちゃんと読みましょう。
「例外 スレッド "main" の中で、"Stoke" というクラス定義が見つからないエラー」

プログラムは class Stroke を定義しています。
$ java Stroke で Stroke.main を呼び出しましょう。
tomomi さんが書きました: なので、私が想像していたのは、ファイルの中身を2次元配列にして、画数を調べ、文字の長さ情報を持ってくる、、、
というような感じでした。
そこで、かずまさんに相談したいのですが、私の考えている2次元配列を用いたやり方でもこのプログラムを作ることは可能でしょうか。
単純な2次元配列ではなく、文字の長さの部分を配列とし、
行は、ArrayList という要素の追加可能な配列としました。

コード:

$ cat Stroke2.java
import java.io.*;
import java.util.*;
 
class Entry {
    char ch;
    int strokeCount;
    int[] lengthOfStroke;
};

class Stroke2 {
    ArrayList<Entry> entries = new ArrayList<Entry>();

    public static void main(String[] args) throws Exception {
        String fileName = "data.txt";
        if (args.length == 2) fileName = args[0];
        Stroke2 stroke = new Stroke2(fileName);
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("> ");
            String s = br.readLine().trim();
            int n = Integer.parseInt(s);
            if (n <= 0) break;
            stroke.find(n);
        }
    }
 
    Stroke2(String fileName) throws IOException {
        BufferedReader br =
            new BufferedReader(new FileReader(new File(fileName)));
        String s;
        while ((s = br.readLine()) != null) {
            System.out.println("# " + s);
            String[] fields = s.trim().split("[ \t]+");
            if (fields.length < 3) {
                System.err.println("invalid data: " + s);
                continue;
            }
            Entry entry = new Entry();
            entry.ch = fields[0].charAt(0);
            int n = fields[1].length();
            entry.strokeCount = Integer.parseInt(fields[1].substring(0, n-1));
            if (fields.length != entry.strokeCount + 2) {
                System.err.println("invalid data: " + s);
                continue;
            }
            entry.lengthOfStroke = new int[entry.strokeCount];
            for (int i = 0; i < entry.strokeCount; i++)
                entry.lengthOfStroke[i] = Integer.parseInt(fields[i+2]);
            entries.add(entry);
        }
    }

    void find(int n) {
        for (int i = 0; i < entries.size(); i++) {
            Entry entry = entries.get(i);
            if (entry.strokeCount == n) {
                System.out.print(entry.ch + " " + entry.strokeCount + "画 ");
                for (int j = 0; j < entry.strokeCount; j++)
                    System.out.print(" " + entry.lengthOfStroke[j]);
                System.out.println();
            }
        }
    }
}

$ javac Stroke2.java
$ cat data.txt
      あ  3画  100  100  300
      い  2画  100  90
      さ  3画  80  70  50
      藤  18画  ・・・
$ java Stroke2 data.txt
#       あ  3画  100  100  300
#       い  2画  100  90
#       さ  3画  80  70  50
#       藤  18画  ・・・
invalid data:       藤  18画  ・・・
> 3
あ 3画  100 100 300
さ 3画  80 70 50
> 2
い 2画  100 90
> 8
> 18
> 0
$ 

Re: javaのファイル内検索

Posted: 2012年11月15日(木) 05:29
by かずま
data.txt の中の項目の区切りは、半角スペースとタブのみとしました。
全角スペースは使えません。
String[] fields = s.trim().split("[ \t]+");

Re: javaのファイル内検索

Posted: 2012年11月15日(木) 06:12
by かずま

コード:

class Entry {
    char ch;
    int strokeCount;
    int[] lengthOfStroke;
};
最後のセミコロンは不要です。

また
  if (args.length == 2) fileName = args[0];
は、
  if (args.length == 1) fileName = args[0];
の間違いです。

Re: javaのファイル内検索

Posted: 2012年11月17日(土) 00:39
by tomomi
かずまさんに示していただいたプログラムを実行したのですが、エラーがでてしまいます。
修正箇所が間違えているのか、何なのかわからないのですが、初心者なのでエラーにどう対処していいのかわからないので教えてください。
もしかして、データに小数点があるからでしょうか。だとすれば、小数点1桁まであるものはどこをどうかえればよいでしょうか。

エラー
% java Stroke2 MOJILIST.txt
# あ 3画 1121.0 863.0 548.0
Exception in thread "main" java.lang.NumberFormatException: For input string: "1121.0"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:456)
at java.lang.Integer.parseInt(Integer.java:497)
at Stroke2.<init>(Stroke2.java:49)
at Stroke2.main(Stroke2.java:16)

コード:

import java.io.*;
import java.util.*;
 
class Entry {
    char ch;
    int strokeCount;
    int[] lengthOfStroke;
}
 
class Stroke2 {
    ArrayList<Entry> entries = new ArrayList<Entry>();
 
    public static void main(String[] args) throws Exception {
        String fileName = "data.txt";
        if (args.length == 1) fileName = args[0];
        Stroke2 stroke = new Stroke2(fileName);
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("> ");
            String s = br.readLine().trim();
            int n = Integer.parseInt(s);
            if (n <= 0) break;
            stroke.find(n);
        }
    }
 
    Stroke2(String fileName) throws IOException {
        BufferedReader br =
            new BufferedReader(new FileReader(new File(fileName)));
        String s;
        while ((s = br.readLine()) != null) {
            System.out.println("# " + s);
            String[] fields = s.trim().split("[ \t]+");
            if (fields.length < 3) {
                System.err.println("invalid data: " + s);
                continue;
            }
            Entry entry = new Entry();
            entry.ch = fields[0].charAt(0);
            int n = fields[1].length();
            entry.strokeCount = Integer.parseInt(fields[1].substring(0, n-1));
            if (fields.length != entry.strokeCount + 2) {
                System.err.println("invalid data: " + s);
                continue;
            }
            entry.lengthOfStroke = new int[entry.strokeCount];
            for (int i = 0; i < entry.strokeCount; i++)
                entry.lengthOfStroke[i] = Integer.parseInt(fields[i+2]);
            entries.add(entry);
        }
    }
 
    void find(int n) {
        for (int i = 0; i < entries.size(); i++) {
            Entry entry = entries.get(i);
            if (entry.strokeCount == n) {
                System.out.print(entry.ch + " " + entry.strokeCount + "画 ");
                for (int j = 0; j < entry.strokeCount; j++)
                    System.out.print(" " + entry.lengthOfStroke[j]);
                System.out.println();
            }
        }
    }
}

Re: javaのファイル内検索

Posted: 2012年11月17日(土) 02:15
by かずま
tomomi さんが書きました:修正箇所が間違えているのか、何なのかわからないのですが、初心者なのでエラーにどう対処していいのかわからないので教えてください。
もしかして、データに小数点があるからでしょうか。だとすれば、小数点1桁まであるものはどこをどうかえればよいでしょうか。
Javaにはプリミティブ型(基本的な型)として、boolean, char, byte, short,
int, long, float, double があることを知らないということでしょうか?
基本を学んでから、Integer.parseInt が何であるかを調べてみることを
お勧めします。

Re: javaのファイル内検索

Posted: 2012年11月20日(火) 22:39
by tomomi
かずまさん
返信遅くなってすみません。いろいろと自分で試行錯誤を繰り返したのですが、同様のエラーが出てしまいます。
Integer.parseIntが「文字列から数値へ変換」していることはわかりました。そして小数点の数値を用いる場合は「float」を用いるということも学びました。文字列からfloatにするにはFloat.parseFloatを使うということも学びました。
ですが、うまくいきません。ヒントでもいいので、教えてください。


コード:

import java.io.*;
import java.util.*;
 
class Entry {
    char ch;
    int strokeCount;
    float[] lengthOfStroke;
}
 
class Stroke2 {
    ArrayList<Entry> entries = new ArrayList<Entry>();
 
    public static void main(String[] args) throws Exception {
        String fileName = "data.txt";
        if (args.length == 1) fileName = args[0];
        Stroke2 stroke = new Stroke2(fileName);
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.print("> ");
            String s = br.readLine().trim();
            float n = Float.parseFloat(s);
            if (n <= 0) break;
            stroke.find(n);
        }
    }
 
    Stroke2(String fileName) throws IOException {
        BufferedReader br =
            new BufferedReader(new FileReader(new File(fileName)));
        String s;
        while ((s = br.readLine()) != null) {
            System.out.println("# " + s);
            String[] fields = s.trim().split("[ \t]+");
            if (fields.length < 3) {
                System.err.println("invalid data: " + s);
                continue;
            }
            Entry entry = new Entry();
            entry.ch = fields[0].charAt(0);
            int n = fields[1].length();
            entry.strokeCount = Integer.parseInt(fields[1].substring(0, n-1));
            if (fields.length != entry.strokeCount + 2) {
                System.err.println("invalid data: " + s);
                continue;
            }
            entry.lengthOfStroke = new float[entry.strokeCount];
            for (int i = 0; i < entry.strokeCount; i++)
                entry.lengthOfStroke[i] = Integer.parseInt(fields[i+2]);
            entries.add(entry);
        }
    }
 
    void find(float n) {
        for (int i = 0; i < entries.size(); i++) {
            Entry entry = entries.get(i);
            if (entry.strokeCount == n) {
                System.out.print(entry.ch + " " + entry.strokeCount + "画 ");
                for (int j = 0; j < entry.strokeCount; j++)
                    System.out.print(" " + entry.lengthOfStroke[j]);
                System.out.println();
            }
        }
    }
}

Re: javaのファイル内検索

Posted: 2012年11月20日(火) 22:42
by tomomi

コード:

entry.lengthOfStroke[i] = Float.parseFloat(fields[i+2]);
すみません。解決しました。

かずまさん、ありがとうございました。

またわからないことがあったら質問しますのでご協力お願いします。