🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1240閲覧

指定されたファイルのクラス名の取得方法を知りたいです

Jhon_McClane

総合スコア48

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2019/11/15 13:14

編集2019/11/15 14:56
コードimport java.io.File; import java.io.IOException; import java.io.BufferedWriter; import java.io.PrintWriter; import java.io.FileWriter; import java.io.FileReader; import java.io.BufferedReader; import java.util.Scanner; import java.io.FileNotFoundException; public class Show{ public void act(File[] findList){ //インスタンスメソッド try{ FileWriter fw = inPutName(); // FileWriter fw = new FileWriter(fileOut, true);//true追記 false前のを消して上書き PrintWriter pw = new PrintWriter(new BufferedWriter(fw)); for(int i=0;i<findList.length;i++){ //ファイルの絶対パスの取得 pw.println("絶対パス:" + findList[i].getAbsolutePath()); //ファイル名の取得 pw.println("ファイル名:" + findList[i].getName()); //ファイルの行数の取得 BufferedReader br = new BufferedReader(new FileReader(findList[i])); int nLine =0; while(br.ready()){ String line = br.readLine(); nLine++; } pw.println("行数:"+nLine); // ファイルに含まれるクラス名 String getClassName = findList[i].getClass().getSimpleName(); // pw.println(getClassName); //ファイルに含まれるパッケージ宣言を取得 // pw.println(クラス名.class.getPackageName()); //ファイルに含まれる import クラス名 } pw.close(); }catch(FileNotFoundException e){ System.out.println(e); }catch(IOException e){ System.out.println(e); } } public static FileWriter inPutName(){ //クラスメソッド try{ System.out.print("出力ファイル名を入力:"); Scanner input = new Scanner(System.in); String output = input.nextLine(); File fileOut= new File(output+".txt"); if(fileOut.exists()){ System.out.println(output+".txtはすでに存在しています.以下から操作を選んでください"); System.out.println("1:追記する 2:名前を変える 3:前のデータを消去して上書きする"); int judge = new Scanner(System.in).nextInt(); switch (judge) { case 1: return new FileWriter(fileOut, true);//true追記 false前のを消して上書き case 2: inPutName(); //break; case 3: return new FileWriter(fileOut, false);//true追記 false前のを消して上書き } }else{ System.out.println("ファイルが存在しないので新しく作成しました."); fileOut.createNewFile(); return new FileWriter(fileOut, true);//true追記 false前のを消して上書き } }catch(IOException e){ System.out.println(e); } } } import java.io.File; import java.util.Scanner; class FileSearch{ public static void main(String[] args){ System.out.println("一覧を生成するディレクトリ名:"); Scanner scan = new Scanner(System.in); String str = scan.next(); //探すディレクトリ File file = new File("/home"); if(!file.exists()){ System.out.println("ディレクトリが存在しません."); System.exit(1); } SearchAlgorithm sa = new SearchAlgorithm(); sa.Search(file,str); } } import java.util.LinkedList; import java.io.File; import java.io.FilenameFilter; public class SearchAlgorithm{ public void Search(File file,String str){ LinkedList<File> que = new LinkedList<File>(); que.offer(file); while(que.size() != 0){//Queのサイズが0出ない(空っぽでない)ならープ File dir = que.poll(); File[] dirList = dir.listFiles(); for(int i=0;i<dirList.length;i++){ if(dirList[i].isDirectory()){//ディレクトリか String dirName = dirList[i].getName(); if(!dirName.equals(str)){//名前が一致しない que.offer(dirList[i]); }else{ //名前が一致 //取り出すディレクトリの処理 que.clear();//Que を空っぽにする que.offerFirst(dirList[i]);//見つけたディレクトリをQueに入れる File finding = que.poll();//Queから取り出し,sizeが0になる(空っぽになる)->while文を抜けられる File[] findList = finding.listFiles(new FileFilter()); Show s = new Show(); s.act(findList); } } } } } } import java.io.File; import java.io.FilenameFilter; class FileFilter implements FilenameFilter{ public boolean accept(File dir, String name) { if(name.endsWith("java")){ return true; }else{ return false; } } } ```指定したディレクトリに存在するjavaファイルをlistFiles(new Filefilter())で抜き出し,引っかかった全てのファイルのクラス名を取得したいです。調べてみると実行中のクラス名の取得方法は分かったのですが実行中でないファイルのクラス名の取得方法がわかりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/11/15 14:24

で、そこまでやったソースはどこですか?
Jhon_McClane

2019/11/15 15:00

コードが長いのでとりあえずという形で4つに分けました. 指定したディレクトリを幅探索で探していき一致したら そのディレクトリ内にあるjavaファイルの情報を一覧にして取り出します またshowクラスをコンパイルするとreturn 文が指定されていません。と出力されます どこが条件を網羅していないのかがわかりません
退会済みユーザー

退会済みユーザー

2019/11/15 15:08

特別どうしても分からないところがないのであれば、バグ取りは自分でしましょう。 上のURLはクラスファイルを解析するライブラリなので、上のようなコードで足りる要件には必要ないです。 私はこの辺で失礼します。
dodox86

2019/11/15 18:02

質問者さんが指定されたテキストの*.javaファイルを読んで、そのファイルのクラス名は何かと考えるとき、どこを見ますか?それをそのままプログラムに書けば良いです。
xebme

2019/11/16 10:03

↑そのとおり。<クラス>.javaなので、クラス名は<クラス>です(パッケージ名は抜き)。 ただし、publicでないクラス、インナークラス、ローカルクラスなどが含まれるかもしれない。要件は? 実行中のクラス名のところは、classファイルがクラスパスに含まれていてロードできるからだけど、... 変でしょ。
guest

回答2

0

ベストアンサー

javaファイル

これが、ソースファイルを指すのか、コンパイル後の拡張子が .class のファイルを指すのかによって、方法は大きく変わります。

ソースファイルを意味しているのであれば、ソースファイル中をJavaの文法に従って構文解析するロジックを書くことになります。その上でクラス定義している箇所から名前を取り出すようにしなければなりません。
その理由はコメント内や定数定義された中の文字列を除外する必要があるからです。様々なソースファイルの書き方を考慮すると単純な文字列検索では、不適切な場所の文字列も検索結果に含まれるからです。また、コメントを除外するのも、コーディングの書き方によって、単純なロジックで処理するのは正確には行えないでしょう。コメントの記述の書式、例えば // の右側をコメントにしようとした時に、その // が文字列定数の中の場合、その右側全部をコメントとしてしまうのは誤った結果につながります。

次に .class ファイルからクラス名を得る方法ですが、大きく二つあります。
一つはインターフェースもクラスとみなせる場合の方法で、単純にファイル名から .class を取り除き、内部クラスなどが、$付きのファイル名になっているのでその辺を考慮して名前として扱えば良いです。

インターフェースはクラスと見做さない場合には、そのファイルを byte stream として読み込んで、クラスファイルの構造定義に従って内容を解析する必要があります。その構造の中の this_class という項目に入っているインデックス値で、constant_pool というテーブル構造の中のインデックス位置にある COSTANT_Class_info 構造に記された name_index の値がまた constant_pool 構造内のインデックス値であり、それが指す、CONSTANT_Utf8_info 構造が保持する byte配列をutf-8エンコーディングされているものとして文字列変換することでクラス名が得られます。
これだけだとインターフェースも含んでしまうため、インターフェースではないことを特定するために access_flags 構造を参照して、その構造の ACC_INTERFACE を表すビットがオフであることを確かめます。もっとも、この情報はクラスファイルの構造上、this_classの直前にあるので、先に判定すればクラス名を得るための処理は必要な時だけ行えるでしょう。

端折って書くなら、constant_pool 構造の解析中に、COSTANT_Class_infoが登場したら控えておいて、のちに access_flags の状態でクラス名を特定してしまうこともできるでしょう。
ただ、この中で骨が折れるのは constant_pool が配列のように定義されて見えるものの、各要素の構造は一定ではなく、先頭の決まった位置にある長さ情報を見ながら、その先の構造を探し出す必要があることです。

内部クラスや無名クラスなど、一つのソースファイル内に複数のクラスが定義されているときは、クラスファイル名は、ソースファイルのクラス名に$記号に続いて内部クラスの名前や、無名クラスの場合は数字がついています。ソースファイル単位にまとめたい場合は、その辺考慮して処理しなくてはなりません。

まずは、これらをヒントに、ご自身でロジックを書いて、個別のわからない箇所、実行時に発生するとりきれないエラー、期待する結果が得られない状況を、個別具体的に質問できる段階になってから再度ご質問ください。
なぜなら、上に説明した内容の全てをロジックで例示するのは、質的にも量的にも回答者自ら行うのは無理だからです。
ご理解ください。

投稿2019/11/17 01:15

編集2019/11/17 01:32
ironya

総合スコア456

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

java ファイルの中を検索して "class" の次の文字列を取り出すというような処理を行うのではないでしょうか.

投稿2019/11/16 10:22

jimbe

総合スコア13204

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問