So here is my problem:
I have here a program that gets all files and folders in a certian directory:
import java.io.File;
import java.util.ArrayList;
public class getFilesAndFolders {
private String[] filesAndFolders = {};
private ArrayList<String> filesAndFolders2 = new ArrayList<String>(filesAndFolders.length +1);
public String[] get(String location){
File files = new File(location);
File[] fList = files.listFiles();
for(File fileLoop : fList){
if(files.isDirectory()){
String placeHolder = fileLoop.getPath();
filesAndFolders2.add(placeHolder);
initialise();
}else if(files.isFile()){
String placeHolder = fileLoop.getPath();
filesAndFolders2.add(placeHolder);
initialise();
}
}
return filesAndFolders;
}
private void initialise() {
filesAndFolders = filesAndFolders2.toArray(new String[filesAndFolders2.size()]);
filesAndFolders2 = new ArrayList<String>(filesAndFolders.length +1);
}
}
I call it with this:
sample.get("sample//samples");
And it returns a nullPointerException at line 16. (The for loop)
Whereas when I type this:
private static Image n1 = new Image("sample//sample2//sample3.png");
The file would be found and the application would load fine. How can I make it so that this program returns something?
Ps: I got to to work before: But it was with a file outside the Jar file
Edit: I want to return the file list back as a String[]. Also, I don't want the computer to know beforehand what files exist there. (EG: If a files name is changed, the computer will still find it)
If I'm reading your question properly, you want a list of entries in a jar file, without knowing in advance what's in the jar file.
To get the the list of entries in a jar file, you can use the java.util.jar.JarFile and java.util.jar.JarEntry classes:
String jarFileName = ...
JarFile jar = new JarFile( jarFileName );
Enumeration<JarEntry> entries = jar.entries();
while ( entries.hasMoreElements() )
{
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
// do something with the entryName String
...
// get an InputStream for the entry
InputStream is = jar.getInputStream( entry );
...
}
Related
I am trying to create a runnable jar file. My project includes models.txt file. My project works perfectly in eclipse with no error but when exported to a runnable jar file, It doesn't work. I hereby attach the error and the piece of code where the file is been called.
public static HashMap<String, RenderModel> getModelList(String file) throws IOException {
List<String> data;
HashMap<String, RenderModel> namesToModels = new HashMap<String, RenderModel>();
if (file != null) {
data = Files.readAllLines(Paths.get(file), StandardCharsets.UTF_8);
} else {
String path = "models/models.txt";
data = Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8);
}
Iterator<String> dataIterator = data.iterator();
while (dataIterator.hasNext()) {
String dataLine = dataIterator.next();
System.out.println(dataLine);
String[] line = dataLine.split("; ");
String key = line[0];
String valueObj = line[1];
String valueMtl = line[2];
float scale = Float.parseFloat((String) line[3]);
RenderModel v = new RenderModel(valueObj, valueMtl, scale);
namesToModels.put(key, v);
}
RenderModel v = new RenderModel("custom", "custom", 1.0f);
namesToModels.put("Choose Model from file", v);
return namesToModels;
}
Error Image:
If the files are in the Jar and you cannot read them, try accessing the files by doing:
getClass().getClassLoader().getResource(fileName);
Use this instead for static methods:
ClassName.class.getClassLoader().getResource(fileName);
Where fileName is the name of the file and ClassName the name of the class from which the statement is called.
In your code the path of the model.txt is 'src/models/model.txt'. When your project is packaged the src folder is not included usually. Then you must change the file location; could be better put the file outside the jar, but inside the java classpath.
It does not work because you do not have any file on the path src/models/models.txt when you run your jar else where, this path is only present in your IDE (ofcourse you can place your jar in a location from where it can reach that path, but this is not how it is supposed to be), when you package your project into a jar file it is packed in the package models and you can if you want to have it as default file read it via classpath.
I'm creating a java program which takes parent path and deletes all the files and folders in the given path. I'm able to delete files and folder's files inside another folder in the parent folder but not able to delete folders at 3rd level.
Here's my code:
package com.sid.trial;
import java.util.List;
import java.io.File;
import java.util.ArrayList;
public class DeleteFilesOfDirectoryWithFilters {
public static void main(String[] args) {
String parentPath = "D:\\tester";
List<String> folderPaths = deleteFiles(parentPath);
deleteFolders(folderPaths);
}
public static void deleteFolders(List<String> folderPaths) {
for(String path : folderPaths){
File folder = new File(path);
if(folder.delete())
System.out.println("Folder "+folder.getName()+" Successfully Deleted.");
}
}
public static List<String> deleteFiles(String path){
File folder = new File(path);
File[] files = folder.listFiles();
List<String> folderPaths = new ArrayList<String>();
String folderPath = path;
if(files.length == 0){
System.out.println("Directory is Empty or No FIles Available to Delete.");
}
for (File file : files) {
if (file.isFile() && file.exists()) {
file.delete();
System.out.println("File "+file.getName()+" Successfully Deleted.");
} else {
if(file.isDirectory()){
folderPath = file.getAbsolutePath();
char lastCharacter = path.charAt(path.length()-1);
if(!(lastCharacter == '/' || lastCharacter == '\\')){
folderPath = folderPath.concat("\\");
}
/*folderPath = folderPath.concat(file.getName());*/
System.out.println(folderPath);
folderPaths.add(folderPath);
}
}
}
for(String directoryPath : folderPaths){
List<String> processedFiles = new ArrayList<String>();
processedFiles = deleteFiles(directoryPath);
folderPaths.addAll(processedFiles);
}
return folderPaths;
}
}
You can use the ""new"" Java File API with Stream API:
Path dirPath = Paths.get( "./yourDirectory" );
Files.walk( dirPath )
.map( Path::toFile )
.sorted( Comparator.comparing( File::isDirectory ) )
.forEach( File::delete );
Note that the call to sorted() method is here to delete all files before directories.
About one statement, and without any third party library ;)
You should consider using Apache Commons-IO. It has a FileUtils class with a method deleteDirectory that will recursively delete.
Note: Apache Commons-IO (as for version 2.5) provides utilities only for legacy java.io API (File and friends), not for Java 7+ java.nio API (Path and friends).
You can recursively traverse through the folder and delete each file one by one. After deleting all the files in one folder, delete the folder. Something similar to following code should work:
public void delete(File path){
File[] l = path.listFiles();
for (File f : l){
if (f.isDirectory())
delete(f);
else
f.delete();
}
path.delete();
}
You can do the following, your recursion is longer than needed.
public static void deleteFiles (File file){
if(file.isDirectory()){
File[] files = file.listFiles(); //All files and sub folders
for(int x=0; files != null && x<files.length; x++)
deleteFiles(files[x]);
}
else
file.delete();
}
Explanation:
When invoke deleteFiles() on a file, the else statement gets triggered, the single file will be deleted with no recursion.
When invoke deleteFiles() on a folder, the if-statement gets triggered.
Get all the entries (files of folders residing in the folder) as an array
If there exist sub-entries, for each entry, recursively delete the sub-entry (the same process (1 and 2) repeats).
Be careful when implementing deletion of file and folders. You may want to print out all the files and folders name first instead of deleting them. Once confirmed it is working correctly, then use file.delete().
So, this question has been asked a million times i believed and I've been reading them for a couple of hours and trying several options given by some people but none of them work for me.
I want to list all the files inside a directory inside the application's JAR, so in IDE this works:
File f = new File(this.getClass().getResource("/resources/").getPath());
for(String s : f.list){
System.out.println(s);
}
That gives me all the files inside the directory.
Now, i've tried this also:
InputStream in = this.getClass().getClassLoader().getResourceAsStream("resources/");
InputStreamReader inReader = new InputStreamReader(in);
Scanner scan = new Scanner(inReader);
while (scan.hasNext()) {
String s = scan.next();
System.out.println("read: " + s);
}
System.out.println("END OF LINE");
And from IDE it prints ALL the files in the directory. Outside IDE prints: "END OF LINE".
Now, I can find an entry inside a Jar with this too:
String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
JarFile jar = new JarFile(s);
JarEntry entry = jar.getJarEntry("resources");
if (entry != null){
System.out.println("EXISTS");
System.out.println(entry.getSize());
}
That's some horrible coding i had to do to that String.
Anyway... I can't get the list of resources inside the "resources" directory within the Jar... How can I do this???
There's no way to simply get a filtered list of internal resources without first enumerating over the contents of the Jar file.
Luckily, that's actually not that hard (and luckily for me you've done most of the hardwork).
Basically, once you have a reference to the JarFile, you simple need to ask for its' entries and iterate over that list.
By checking the JarEntry name for the required match (ie resources), you can filter the elements you want...
For example...
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReadMyResources {
public static void main(String[] args) {
new ReadMyResources();
}
public ReadMyResources() {
JarFile jf = null;
try {
String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
jf = new JarFile(s);
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
if (je.getName().startsWith("resources")) {
System.out.println(je.getName());
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
jf.close();
} catch (Exception e) {
}
}
}
}
Caveat
This type of question actually gets ask a bit. Rather then trying to read the contents of the Jar at runtime, it would be better to produce some kind of text file which contained a list of the available resources.
This could be produced by your build process dynamically before the Jar file is created. It would be a much simpler solution to then read this file in (via getClass().getResource(), for example) and then look up each resource list in the text file...IMHO
For Spring Framework users, have a look at PathMatchingResourcePatternResolver to do something like the following:
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:path/to/resource/*.*");
for (Resource resource : resources) {
InputStream inStream = resource.getInputStream();
// Do something with the input stream
}
My case was to read a directory inside resources:
As my requirement was to transform resource directory to io.File, finally it looked like this:
public static File getResourceDirectory(String resource) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL res = classLoader.getResource(resource);
File fileDirectory;
if ("jar".equals(res.getProtocol())) {
InputStream input = classLoader.getResourceAsStream(resource);
fileDirectory = Files.createTempDir();
List<String> fileNames = IOUtils.readLines(input, StandardCharsets.UTF_8);
fileNames.forEach(name -> {
String fileResourceName = resource + File.separator + name;
File tempFile = new File(fileDirectory.getPath() + File.pathSeparator + name);
InputStream fileInput = classLoader.getResourceAsStream(resourceFileName);
FileUtils.copyInputStreamToFile(fileInput, tempFile);
});
fileDirectory.deleteOnExit();
} else {
fileDirectory = new File(res.getFile());
}
return fileDirectory;
}
If resources are in jar, we copy it to temp directory that will be deleted on application end.
Then calling getResourceDirectory("migrations") returned me io.File directory for further use.
I am trying to create a simple function which copies or merge two or more folder files into one single folder.
I started with below. I thought to post here to get a better quality code.
public void copyDifferentFolderFilesIntoOne(String mergedFolderStr,String ... foldersStr)
{
File mergedFolder= new File(mergedFolderStr);
for(String folder: foldersStr)
{
//copy folder's files into mergedFolder
}
}
When there is a conflict in file copying (i.e. file with same name exists on two or more folder) I want the file with latest timestamp get copied in mergedFolder.
Do you know the best way to merge two or more folders files into one?
Let me know if question is not clear.
You can create a Map<String, File> of the files you want to copy by traversing the merged dirs and keeping the newest files. Then you can copy the files you have in a map.
A sample code (haven't tried it) might look like this:
public void copyDifferentFolderFilesIntoOne(String mergedFolderStr,
String... foldersStr) {
final File mergedFolder = new File(mergedFolderStr);
final Map<String, File> filesMap = new HashMap<String, File> ();
for (String folder : foldersStr) {
updateFilesMap(new File (folder), filesMap, null);
}
for (final Map.Entry<String, File> fileEntry : filesMap.entrySet()) {
final String relativeName = fileEntry.getKey();
final File srcFile = fileEntry.getValue();
FileUtils.copyFile (srcFile, new File (mergedFolder, relativeName));
}
}
private void updateFilesMap(final File baseFolder, final Map<String, File> filesMap,
final String relativeName) {
for (final File file : baseFolder.listFiles()) {
final String fileRelativeName = getFileRelativeName (relativeName, file.getName());
if (file.isDirectory()) {
updateFilesMap(file, filesMap, fileRelativeName);
}
else {
final File existingFile = filesMap.get (fileRelativeName);
if (existingFile == null || file.lastModified() > existingFile.lastModified() ) {
filesMap.put (fileRelativeName, file);
}
}
}
}
private String getFileRelativeName(final String baseName, final String fileName) {
return baseName == null ? fileName : baseName + "/" + fileName;
}
To copy file, look at Standard concise way to copy a file in Java?
To get timestamp, see File.lastModified()
I need to create a temp file, so I tried this:
String[] TempFiles = {"c1234c10","c1234c11","c1234c12","c1234c13"};
for (int i = 0; i <= 3; i++) {
try {
String tempFile = TempFiles[i];
File temp = File.createTempFile(tempFile, ".xls");
System.out.println("Temp file : " + temp.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
The output is something like this:
Temp file : C:\Users\MD1000\AppData\Local\Temp\c1234c108415816200650069233.xls
Temp file : C:\Users\MD1000\AppData\Local\Temp\c1234c113748833645638701089.xls
Temp file : C:\Users\MD1000\AppData\Local\Temp\c1234c126104766829220422260.xls
Temp file : C:\Users\MD1000\AppData\Local\Temp\c1234c137493179265536640669.xls
Now, I don't want the extra numbers (long int) which is getting added to the file name. How can I achieve that? Thanks
First, use the following snippet to get the system's temp directory:
String tDir = System.getProperty("java.io.tmpdir");
Then use the tDir variable in conjunction with your tempFiles[] array to create each file individually.
Using Guava:
import com.google.common.io.Files;
...
File myTempFile = new File(Files.createTempDir(), "MySpecificName.png");
You can't if you use File.createTempFile to generate a temporary file name. I looked at the java source for generating a temp file (for java 1.7, you didn't state your version so I just used mine):
private static class TempDirectory {
private TempDirectory() { }
// temporary directory location
private static final File tmpdir = new File(fs.normalize(AccessController
.doPrivileged(new GetPropertyAction("java.io.tmpdir"))));
static File location() {
return tmpdir;
}
// file name generation
private static final SecureRandom random = new SecureRandom();
static File generateFile(String prefix, String suffix, File dir) {
long n = random.nextLong();
if (n == Long.MIN_VALUE) {
n = 0; // corner case
} else {
n = Math.abs(n);
}
return new File(dir, prefix + Long.toString(n) + suffix);
}
}
This is the code in the java JDK that generates the temp file name. You can see that it generates a random number and inserts it into your file name between your prefix and suffix. This is in "File.java" (in java.io). I did not see any way to change that.
If you want files with specific names created in the system-wide temporary directory, then expand the %temp% environment variable and create the file manually, nothing wrong with that.
Edit: Actually, use System.getProperty("java.io.tmpdir")); for that.
Just putting up the option here:
If someone anyhow need to use createTempFile method, you can do create a temp file and rename it using Files.move option:
final Path path = Files.createTempFile(fileName, ".xls");
Files.move(path, path.resolveSibling(fileName));
You can create a temp directory then store new files in it. This way all of the new files you add won't have a random extension to it. When you're done all you have to do is delete the temp directory you added.
public static File createTempFile(String prefix, String suffix) {
File parent = new File(System.getProperty("java.io.tmpdir"));
File temp = new File(parent, prefix + suffix);
if (temp.exists()) {
temp.delete();
}
try {
temp.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
return temp;
}
public static File createTempDirectory(String fileName) {
File parent = new File(System.getProperty("java.io.tmpdir"));
File temp = new File(parent, fileName);
if (temp.exists()) {
temp.delete();
}
temp.mkdir();
return temp;
}
Custom names can be saved as follows
File temp=new File(tempFile, ".xls");
if (!temp.exists()) {
temp.createNewFile();
}
public static File createTempDirectory(String dirName) {
File baseDir = new File(System.getProperty("java.io.tmpdir"));
File tempDir = new File(baseDir, dirName);
if (tempDir.mkdir()) {
return tempDir;
}
return null;
}