I usually find a workaround for problems, but this time I cannot seem to find one.
I am making a compiler for a self-designed language using JavaCC. Before I simply used System.in to read files, so this way I know my compiler can use any text-based file of any extension.
This project must ONLY open files with a custom extension (.bait). From my research, there are plenty of ways in Java to get a file's extension, but they all require a full path. My compiler is supposed to run from any place in the user's disk through a terminal (CMD), so I do not think Java's options are useful.
The question: How can I filter the file extension of a given file that the compiler rejects the source if it's not .bait?
The original code I use is pretty simple:
hook analizador = new hook (System.in);
analizador.RunLexer();
'hook' being the class and RunLexer() is a method for lexical analysis. The code allows any text-based code to be analyzed. For the extention rule I thought of using *.bait regular expresion as in:
hook analizador = new hook (new FileInputStream("*.bait"));
analizador.codigo();
and
InputStream input = new FileInputStream("*.bait");
hook analizador = new hook (input);
with no luck, so far. Can anybody guide me with this? An explanation of the answer will be gladly appreciated.
EDIT: Thanks to sepp2k and MeetTitan.
System.in was not an option, so instead the filename (used as argument) can be used for all the verifications needed:
String arc = args[0];
if(arc.endsWith(".bait")){ //checks file extention
File src = new File(arc); //created just to use exists()
if(src.exists()){
FileReader fr = new FileReader(arc); //used instead of System.in
hook analizador = new hook(fr);
} else System.out.println("File not found");
} else System.out.println("Invalid filetype");
As for the way to use the program, using terminal (CMD)
java hook file.bait
This code doesn't let the user run .bait files out of the hook directory as intended, so it's safe even if there are several copies of the file in different locations.
Hope it can be of any use to someone, and thank you again, sepp2k and MeetTitan!
Why can't you do something like this?
//this method takes a String and returns a substring containing the characters between the last occurrence of '.' and the end of the String
//For example, getExtension("test/your.file.bait"); will return "bait".
public static String getExtension(String fileNameOrPath) {
return fileNameOrPath.substring(fileNameOrPath.lastIndexOf('.')+1);
}
//this method compares equality of "bait" and the returned extension from our other method
public static boolean isBait(String fileNameOrPath) {
return "bait".equals(getExtension(fileNameOrPath));
}
You can use isBait(String) on any path, relative or absolute, or a filename.
You could also simply leverage String.endsWith(String).
Like so:
public static boolean isBait(String str) {
return str.endsWith(".bait");
}
EDIT
To get a listing of all files in a folder with a specific extension, you'd use a FilenameFilter with File.listFiles()
Like so:
File dir = new File("path/to/folder");
File[] baitFiles = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".bait");
}
});
EDIT to recurse over EVERY subfolder and only get certain files:
public static List<File> recurseGetBait(File dir) { //need method for recursion
List<File> baitFilesList = new ArrayList<>(); //make a new ArrayList that we will populate and return
File[] baitFiles = dir.listFiles(new FilenameFilter() { //get all bait files with previously shown snippet
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".bait");
}
});
for(File baitFile : baitFiles) {
baitFilesList.add(baitFile); //add every file from baitFiles to baitFilesList
}
String[] dirs = file.list(new FilenameFilter() { //get all subfolders of current folder
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
for(File dir : dirs) { //iterate over all subfolders
List<File> returned = recursiveGetBait(dir); //run this same method on this subfolder (which will recurse until there are no sub folders)
baitFilesList.addAll(returned); // add all of the previously returned bait files to baitFilesList so we populate and return
}
return baitFilesList; //either returns our list to the previous recurse or returns the fully built list to our original caller
}
Related
File dir = new File(dirName);
ArrayList<File> files = new ArrayList<File>();
dir.listFiles(new FileFilter()
{
#Override
public boolean accept(File file)
{
if (!file.isFile()){
return false;
}
String name = file.getName();
if (!StringUtils.startsWith(name, startsWith)){
return false;
}
if (!StringUtils.endsWith(name, ensWith)){
return false;
}
files.add(file);
s_logs.log(Level.INFO, "File that startswith " + startsWith + " found ");
return true;
}
});
This code is used for getting all file starting with character but i want to wait till file is created.
Could you please suggest a way?
You can use something called as a WatchService that is available in the new java.nio.file package in Java.
You can observe a directory for any file creation using this. You can also check the directory recursively if needed. Oracle also has put up a code sample that you can use to get started.
https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java
You will need to modify the processEvents() method in the above sample and check if the child object begins with the character that you are trying to look for.
Hope this helps you get started!
I'm working on a program. However, the program is that I'm on a Linux based operating system and it wants perfect case-match names for all of the files, and considering the artist has some named with Caps, some not, some have ".png" some are ".Png" and some are ".PNG", etc; this is becoming a very difficult task. There's a little over a thousand Sprites, or renaming them wouldn’t be a problem. This is for a 2D RPG Hobby project that I'm doing for learning, purposes that I've been working on for awhile now.
Anyhow, my question is if we can make the 'Compiler'(I think is the right way to word this) ignore the file ending character-casing? If I want to load the following items
1.jpg
2.Jpg
3.JPg
4.JPG
5.jpG
I would like to be able to do it in a single line.
You cannot make the compiler ignore case; this is a filesystem characteristic. Note that NTFS is case-insensitive but it is case-preserving nonetheless.
Using Java 7 you can use a DirectoryStream.Filter<Path> to collect the relevant paths; then rename if appropriate:
final DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>()
{
#Override
public boolean accept(final Path entry)
{
return Files.isRegularFile(entry)
&& entry.getFileName().toString().toLowerCase().endsWith(".jpg");
}
};
final List<Path> collected = new ArrayList<Path>();
try (
final DirectoryStream<Path> entries = Files.newDirectoryStream(dir, filter);
) {
for (final Path entry: entries)
collected.add(entry);
}
Path dst;
String targetName;
for (final Path src: collected) {
targetName = src.getFileName().toString().toLowerCase();
dst = src.resolveSibling(targetName);
if (!Files.isSameFile(src, dst))
Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE);
}
With Java 8 you would probably use Files.walk() and lambdas instead.
If you know the exact directory for the file, you could use File.list() to get an String[] of all files in this directory. By iterating over those and using toLowerCase() on the filenames you can find your desired file.
String filename = "1.jpg";
String targetFilename = null;
File directory = new File("/some/path");
for(String maybeTargetName : directory.list()) {
if(filename.equals(maybeTargetName.toLowerCase()) {
targetFilename = maybeTargetName;
break;
}
}
if(targetFilename != null) {
File targetFile = new File(directory, targetFilename);
}
Just for my own learning, i am trying to find all mp3 files in my music collection and finding all the tracks which do not have id3v2 tags. My code gives me information about the directory i specify, but it doesn't look for the mp3 files in subdirectories. Although i can see that it recognises the directories as i can print them out. Please see my code below. I am very sorry if the formatting of the code is not correct. I am blind and using a screen reader and the formatter on this site is not very accessible to me.
public static int numberOfUntaggedTracks(String directory) throws UnsupportedTagException, InvalidDataException, IOException {
int untaggedTracks = 0;
File f = new File(directory);
File l[] = f.listFiles();
for (File x: l) {
if (x.isHidden() || !x.canRead())
continue;
if (x.isDirectory()) {
System.out.println("testing" + x.getPath());
numberOfUntaggedTracks(x.getPath());
} else if (x.getName().endsWith(".mp3")) {
Mp3File song = new Mp3File(x.getPath());
if (song.hasId3v1Tag() == false) {
untaggedTracks++;
}
//end of else if checking for .mp3 extension
}
//end of for loop
}
return untaggedTracks;
}
FileUtils from apatche commons-io has a listFiles method that should do what you need.
The method takes two IOFileFilter instances that you can use to filter files (mp3 files in your case) and to filter sub directories (so you can control which directories to include in your search).
To make your code work just change numberOfUntaggedTracks(x.getPath()); to untaggedTracks += numberOfUntaggedTracks(x.getPath());
I need to get the paths of files and their parent directories in java from a given directory but not including it.
So for example, If my method was given the path: /home/user/test as a path it would return the paths of all files in that directory and under it.
So if /home/user/test had the sub folders: /subdir1 and /subdir2 each containing file1.txt and file2.txt then the result of the method would be 2 strings containing /subdir1/file1.txt and /subdir2/file2.txt
And if subdir1 had a directory inside it called subsubdir and inside that file3.txt, then the string created for that file would be /subdir1/subsubdir/file3.txt, and if there are further sub directories that would continue.
The idea is I just want the directory paths above the file but not the absolute path so only the directories AFTER the initial given path.
I know its a little confusing but I'm sure someone can make sense of it. Right now all I have is a recursive function that prints out file names and their absolute paths.
Any assistance on this?
What would have been nice if you had tried something and asked questions about that...
However...
public class TestFileSearch {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new TestFileSearch();
}
public TestFileSearch() {
File parentPath = new File("C:/Users/shane/Documents");
List<String> files = list(parentPath);
for (String file : files) {
System.out.println(file);
}
}
protected List<String> list(File parent) {
return listFiles(parent, parent);
}
protected List<String> listFiles(File parent, File folder) {
List<String> lstFiles = new ArrayList<String>(25);
if (folder.isDirectory()) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
lstFiles.addAll(listFiles(parent, file));
} else {
String path = file.getPath();
String offset = parent.getPath();
path = path.substring(offset.length());
lstFiles.add(path);
}
}
}
}
return lstFiles;
}
}
You could simply do a normal folder recursion, returning a list of files and THEN strip of the prefix, but that's up to you
What about using the absolute path you currently have but removing the prefix from it using String.replace
You said you had the full, absolute path, say in full
then just do
String relative = full.replace(prefix, "");
If you have the input "/home/user/text", all absolute paths to files will start with /home/user/text/. If you're already able to print a list of all files under text/, then all you need to do is take the suitable substring.
The following function should visit all files under pathToDir. In the printFileName function, you can remove the /home/user/text part and print the file names
public static void gotoAllFiles(File pathToDir) {
if (pathToDir.isDirectory()) {
String[] subdirs = pathToDir.list();
for (int i=0; i<subdirs.length; i++) {
gotoAllFiles(new File(pathToDir, subdirs[i]));
}
} else {
printFileName(pathToDir);
}
}
For each file found, print the file.getAbsolutePath().substring(rootPath.length());
I want to figure it out whether a csv file present in a particular directory or not
Something along the lines of
public boolean containsCSVFiles( File aDirectory ){
return !aDirectory.listFiles( new FilenameFilter(){
public boolean accept(File dir, String name){
return name.endsWith( ".csv" );
}
}).isEmpty();
}
should do it (not tested in my IDE, so I hope I did not make to much typos).
Simply parse the directory to look for .csv files....
File f = new File("D:/Shashank/");
if(f.isDirectory())
{
File[] file= f.listFiles();
for(File f1 :file)
{
if(f1.getName().endsWith(".csv"))
{
System.out.println("File Found"+f1.getName());
}
}
}
You can make it recursive too, to look into the sub directories.
You don't really explain what you want to do, but between the listFiles() and exists() methods of the java.io.File class, you should be able to get it done.