Get Class Name from File

Get class name from file

There are multiple possible solutions to this problem, each with their advantages and disadvantages. Here they are, it's up to know to decide which one you want.

Tokenizer

This method uses the tokenizer and reads parts of the file until it finds a class definition.

Advantages

  • Do not have to parse the file entirely
  • Fast (reads the beginning of the file only)
  • Little to no chance of false positives

Disadvantages

  • Longest solution

Code

$fp = fopen($file, 'r');
$class = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;

$buffer .= fread($fp, 512);
$tokens = token_get_all($buffer);

if (strpos($buffer, '{') === false) continue;

for (;$i<count($tokens);$i++) {
if ($tokens[$i][0] === T_CLASS) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$class = $tokens[$i+2][1];
}
}
}
}
}

Regular expressions

Use regular expressions to parse the beginning of the file, until a class definition is found.

Advantages

  • Do not have to parse the file entirely
  • Fast (reads the beginning of the file only)

Disadvantages

  • High chances of false positives (e.g.: echo "class Foo {";)

Code

$fp = fopen($file, 'r');
$class = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;

$buffer .= fread($fp, 512);
if (preg_match('/class\s+(\w+)(.*)?\{/', $buffer, $matches)) {
$class = $matches[1];
break;
}
}

Note: The regex can probably be improved, but no regex alone can do this perfectly.

Get list of declared classes

This method uses get_declared_classes() and look for the first class defined after an include.

Advantages

  • Shortest solution
  • No chance of false positive

Disadvantages

  • Have to load the entire file
  • Have to load the entire list of classes in memory twice
  • Have to load the class definition in memory

Code

$classes = get_declared_classes();
include 'test2.php';
$diff = array_diff(get_declared_classes(), $classes);
$class = reset($diff);

Note: You cannot simply do end() as others suggested. If the class includes another class, you will get a wrong result.


This is the Tokenizer solution, modified to include a $namespace variable containing the class namespace, if applicable:

$fp = fopen($file, 'r');
$class = $namespace = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;

$buffer .= fread($fp, 512);
$tokens = token_get_all($buffer);

if (strpos($buffer, '{') === false) continue;

for (;$i<count($tokens);$i++) {
if ($tokens[$i][0] === T_NAMESPACE) {
for ($j=$i+1;$j<count($tokens); $j++) {
if ($tokens[$j][0] === T_STRING) {
$namespace .= '\\'.$tokens[$j][1];
} else if ($tokens[$j] === '{' || $tokens[$j] === ';') {
break;
}
}
}

if ($tokens[$i][0] === T_CLASS) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$class = $tokens[$i+2][1];
}
}
}
}
}

Say you have this class:

namespace foo\bar {
class hello { }
}

...or the alternative syntax:

namespace foo\bar;
class hello { }

You should have the following result:

var_dump($namespace); // \foo\bar
var_dump($class); // hello

You could also use the above to detect the namespace a file declares, regardless of it containing a class or not.

How to get class name of any java file

Well .java files need to have the same name as the class or enum within, so we could just use the file name:

public String getClass(File file){
return removeExtension(file.getName());
}

removeExtension has many different ways of achieving, here is just one:

public static String removeExtension(String file){
return file.replaceFirst("[.][^.]+$", "");
}

More here: How to get the filename without the extension in Java?

...the reason behind me wanting to do is is so that I can count the methods within the class.

OK, well this is not the way to do it, you should look into reflection: What is reflection and why is it useful?

How to find the list of all the class name in a file in python?

An alternative that will also find nested classes and doesn't require importing of the file:

source = """
class test:
class inner_class:
pass
pass

class test2:
pass
"""

import ast
p = ast.parse(source)
classes = [node.name for node in ast.walk(p) if isinstance(node, ast.ClassDef)]
# ['test', 'test2', 'inner_class']

How to get names of classes inside a jar file?

Unfortunately, Java doesn't provide an easy way to list classes in the "native" JRE. That leaves you with a couple of options: (a) for any given JAR file, you can list the entries inside that JAR file, find the .class files, and then determine which Java class each .class file represents; or (b) you can use a library that does this for you.

Option (a): Scanning JAR files manually

In this option, we'll fill classNames with the list of all Java classes contained inside a jar file at /path/to/jar/file.jar.

List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
// This ZipEntry represents a class. Now, what class does it represent?
String className = entry.getName().replace('/', '.'); // including ".class"
classNames.add(className.substring(0, className.length() - ".class".length()));
}
}

Option (b): Using specialized reflections libraries

Guava

Guava has had ClassPath since at least 14.0, which I have used and liked. One nice thing about ClassPath is that it doesn't load the classes it finds, which is important when you're scanning for a large number of classes.

ClassPath cp=ClassPath.from(Thread.currentThread().getContextClassLoader());
for(ClassPath.ClassInfo info : cp.getTopLevelClassesRecurusive("my.package.name")) {
// Do stuff with classes here...
}

Reflections

I haven't personally used the Reflections library, but it seems well-liked. Some great examples are provided on the website like this quick way to load all the classes in a package provided by any JAR file, which may also be useful for your application.

Reflections reflections = new Reflections("my.project.prefix");

Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

Class Name and File Name

There's a file. Period. Whatever is contained in it is of no interest for imports, and the file name or location doesn't have any effect on the contained code (generally - it is accessible during execution, so some metaprogramming makes use of it but should be agnostic w.r.t. the actual value).

The contents of a file are not restricted to a single class, and few people impose such a restriction onto themselves. Python isn't exclusively an OO language, you can and should have free functions whenever it's sensible, and modules are seen one level above classes in code organizations - if several classes are closely related, they should propably go in one module.

Your example code/problem is unrelated to this, it's a matter of scoping inside a given file. Classes do have their own scope, but you can't and shouldn't be using the class variables of the containing class in methods like this (directly) - it would make the code oblivious to a new value set in a subclass. Instead, you either use class methods (by the way, you should propably read http://dirtsimple.org/2004/12/python-is-not-java.html) or make use of the fact that instances inherit all members of the class and just prefix it with self..

Fetching all the Module name, class name and method names from directory in python

To filter the files in a directory you can use('.' refers to the current directory):

from os import listdir,chdir

default_path = r'c:\dev\python'
modules = [ fl for fl in listdir(default_path) if fl.endswith('.py') ]

To get the classes and methods I know you can use inspect though you can't use it without importing the module:

e.g.

from inspect import getmembers, isfunction, ismethod, isclass
your_module = __import__(modules[0].split('.')[0])

class_funcs = {}
funcs = [ obj for obj in getmembers(your_module) if isfunction(obj[1]) ]
classes = [ obj for obj in getmembers(your_module) if isclass(obj[1]) ]

for cls in classes:
class_funcs[cls[0]] = [ obj for obj in getmembers(cls[1]) if ismethod(obj[1]) ]

print funcs

[('function1', <function your_module.function1>),
('function2', <function your_module.function2>)]

print class_funcs

{'ClassName': [('__init__', <unbound method ClassName.__init__>),
('Method_name', <unbound method ClassName.Method_name>)]}

That will give you all the functions, classes, classes methods in your module.

If you don't want to import the module I'm not familiar with a way to get the methods(except for reading the file and using regex and etc.).



Related Topics



Leave a reply



Submit