Wczytywanie pliku z kodem źródłowym Javy

0

Mam takie zadanie:
Napisać program, który wczytuje plik o nazwie "Test.java" z kodem źródłowym Javy i wyszukuje w nim instrukcje if oraz napisy "wariant". Wyniki dzialania programu w postaci:
Liczba instrukcji if: n
Liczba napisów: m
należy wypisać na konsoli

Plik Test.java: http://wklej.org/id/1299051/

Na razie mam coś takiego:

 import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Test {

	public static void main(String[] args) throws IOException{
 		FileReader fileReader = new FileReader("Test.java");
 		BufferedReader bufferedReader = new BufferedReader(fileReader);
  
  String text = bufferedReader.readLine();


bufferedReader.close();
   }
}

Użyłam FileReader, ponieważ polecono go na tym forum do podobnego typu zadania.
Ale nawet jeśli odczytanie z pliku zadziała to nie wiem co dalej zrobić.
Po przeszukaniu parunastu stron na ten temat, znalazłam jeszcze coś takiego jak: Matcher i Pattern.
Zastanawiam się czy mogłabym do kodu wyżej dodać coś takiego:

   String patternString1 = "wariant";
  
  Pattern pattern = Pattern.compile(patternString1);
  Matcher matcher = pattern.matcher(text);

Czy raczej coś takiego nie jest możliwe? I czy w taki sposób wyszukałoby mi słowa 'wariant' skoro one zamieszczone są w komentarzach? I jak wyszukać instrukcje if, a nie samo słowo if, które w pliku źródłowym podane jest wiele razy w różnych miejscach?

Z góry dziękuję za pomoc i wskazówki co mogłabym zrobić dalej.

0

Dobrze kombinujesz z tym pattern/matcher:

String code = "xxxxx wariant yyyy"; // tutaj wstaw swój kawałek pliku
Pattern p = Pattern.compile("wariant");
Matcher m = p.matcher(code);
int count = 0;
while (m.find()) {
    count +=1;
}

Oczywiscie dla instrukcji warunkowej if wyrażenie regularne będzie bardziej skomplikowane niż "if", bo nie chcesz żeby złapało ci na przykład "if" w środku wyrazu np. "diff".
Poczytaj o regular expressions. No i oczywiście jak chcesz przeiterować cały plik, metodę readLine() musisz wykonywać w pętli.

0
kszychu napisał(a):

Dobrze kombinujesz z tym pattern/matcher:

String code = "xxxxx wariant yyyy"; // tutaj wstaw swój kawałek pliku
Pattern p = Pattern.compile("wariant");
Matcher m = p.matcher(code);
int count = 0;
while (m.find()) {
    count +=1;
}

Da się w taki sposób zrobić, by nie wstawiać kawałka pliku ale cały?

kszychu napisał(a):

Oczywiscie dla instrukcji warunkowej if wyrażenie regularne będzie bardziej skomplikowane niż "if", bo nie chcesz żeby złapało ci na przykład "if" w środku wyrazu np. "diff".
Poczytaj o regular expressions. No i oczywiście jak chcesz przeiterować cały plik, metodę readLine() musisz wykonywać w pętli.

String text = bufferedReader.readLine();
 bufferedReader.close(); 

Chodzi, żeby ten fragment dać w pętli?

1

Nie, tylko ten fragment

String text = bufferedReader.readLine();

dać w pętli.

0
String text;
while((text = bufferedReader.readLine()) != null){
   

}
bufferedReader.close();  

Coś takiego?
i w środku pętli dać pattern i matcher?

1

Pattern na zewnatrz, Matcher wewnatrz petli (osobny dla kazdej linii pliku)

0

Bardzo dziękuję za pomoc, już działa. To znaczy jeszcze muszę popróbować z tymi wyrażeniami regularnymi.

0

Chyba nie są konieczne, wystarczy usuwać spacje (białe znaki) i szukać "if(".

0
String allTogether = "";
while(sc.hasNextLine())
{
      allTogether+=sc.nextLine().replaceAll("[ \t]",""); //wystarczy replaceAll(" ","")
}
int pos = -1;
while((pos=allTogether.indexOf("if(",pos+1))>=0)
{
      counter++;
}

Mam trochę inną pętlę, bo korzystałem z klasy Scanner, a nie BufferedReader.

0

Ze spacją własnie udało mi się zrobić do wariant, próbowałam i inne sposoby, ale chyba ze spacją na początku jest najprościej.
Z ifem jest gorzej właśnie przez to, że jedne mają spacje, inne nie + ten ostatni w nawiasem w innej linii.
Skorzystałam z tego temu w linku wyżej i teraz program pokazuje 9 ifów.

"if.(.*)"

więc niby liczy dobrze, bo jest 9 instrukcji if, zastanawiam się tylko czy to przypadkowo się udało, bo może w innym pliku wskazywałoby źle.

0

Na dowolnym nie zadziała. Policzy takie ify:

System.out.println("if(1>3)");
private int nif()
{
    return 3;
}
0

Czyli nie ma możliwości użycia wyrażeń regularnych w tym przypadku, by to zadziałało? Trzeba pozmieniać pętle?
Miałam nawet pomysł by ifa szukać podwójnie, raz, że jest po nim spacja, raz że jest od razu nawias, ale to i tak nie uwzględni tego ostatniego, gdzie nie ma po nim nic i dopiero w kolejnej linii są nawiasy.

0

Mam takie zadanie:
Napisać program, który wczytuje plik o nazwie "Test.java" z kodem źródłowym Javy

Dlaczego chcesz napisać program, który analizuje wszystkie[wszystkie składniowo poprawne] pliki źródłowe w Javie?

0

Zrozumiałam to zadanie tak, że mam odczytać ten plik i poznajdywać w nim dany napis i funkcje, a że pojawiają się w różnych kombinacjach to mam znaleźć sposób by je wyszukać.

0

Ja tez tak zrozumiałem, ale wcześniej napisałaś

zastanawiam się tylko czy to przypadkowo się udało, bo może w innym pliku wskazywałoby źle.

0

Chodziło mi o to, że czasem napiszę jakiś kod i pokaże co prawda to co mówi zadanie, ale gdyby cokolwiek zmienić w danych (np. dodać gdzieś jakąś spacje czy dodatkową instrukcje) i tak dalej to się wszystko rozsypie.
Nie jestem też pewna czy dobra ilość ifów to faktycznie ify z instrukcji czy może policzyło jakoś inaczej (ciągle niepokoi mnie ten if gdzie nawias na w nowej linii).

0

@Shiori tak jak pisałem w temacie wyżej: jeśli chcesz napisać uniwersalny program który wykrywa wszystkie ify w dowolnym źródle javy to nie zrobisz tego regexpami bo to nie jest język regularny. Takie coś trzeba parsować jakimś LL, LR albo LALR.

0

Mam takie pytanie. Czy BufferedReaderem da się czytać cały tekst na raz? Znaczy wszystkie linie? Nie linia po linii. A jeśli nie to czy jest inny sposób na to? Po wypróbowaniu wielu kombinacji wyrażeń regularnych ostatni if nie jest liczony, pewnie nie uda się tego zrobić póki kod będzie czytać liniami.

0

http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#readAllLines(java.nio.file.Path, java.nio.charset.Charset)
a potem to scal w jednego stringa jak chcesz

0

Przecież napisałem wcześniej kod scalający

String allTogether = "";
while(sc.hasNextLine())
{
      allTogether+=sc.nextLine().replaceAll("[ \t]",""); //wystarczy replaceAll(" ",""), to co jest w kodzie usuwa również tabulacje
}

Nie chciałem wtedy komplikować, ale teraz napisze porządnie (operator konkatenacji Stringów jest bardzo wolny):

StringBuilder allTogether = new StringBuilder("");
while(sc.hasNextLine())
{
      allTogether.append(sc.nextLine().replaceAll("[ \t]",""));
}
String result = allTogether().toString()l

1 użytkowników online, w tym zalogowanych: 0, gości: 1