I know there's a way to select a random file from a directory, but I don't know how it's coded in Java. I have pseudocode though. What I'm asking is if I could get a nudge in the right direction. My pseudocode is as follows:
dir = "directory";
String[] files = dir.listfiles();
String next = rand.nextInt(files.length);
Image img = next;
The reason I want to do it like this is because I have a long list of images that I would like to shuffle through.
Your pseudo code looks fine, you can get all the names recursively, store the names in an ArrayList, and randomly retrieve the names from the ArrayList as shown below:
static ArrayList<String> files = new ArrayList<String>();
public static void main(String[] args) {
File dir = new File(".");
getFileNames(dir);
Random rand = new Random();
String next = files.get(rand.nextInt(files.size()));
}
private static void getFileNames(File curDir) {
File[] filesList = curDir.listFiles();
for (File f : filesList) {
if (f.isDirectory())
getFileNames(f);
if (f.isFile()) {
files.add(f.getName());
}
}
}
You seem to be on the right track. Only thing is listFiles() returns a File[] not a String[]
Maybe try something like this
File file = new File(filename);
File[] files = new File[0]; // initialize
if (file.isDirectory()){
files = file.listFiles(); // populate
}
int fileIndex = new Random().nextInt(files.length); // get random index
Image img = new ImageIcon(files[fileIndex]).getImage(); // create image
Though the above may work, It's recommended using URL for embedded resources and not Files. Something like this
String[] filenames = file.list(); // list returns String
int fileIndex = new Random().nextInt(filenames.length);
Image img = null;
java.net.URL url = MyClass.class.getResource(filenames[fileIndex]);
if (url != null){
img = new ImageIcon(url).getImage();
} else {
img = null;
}
When using the class.gerResource(). The file will be searched for in the location of the class files. You can can also change the path a little bit, for example if you want a file structure like this
ProjectRoot
bin
MyClass.class
images
image1.png
image2.png
src
Then you can use this code
java.net.URL url = MyClass.class.getResource("images/" + filenames[fileIndex]);
Here is how I would implement your pseudo-code
private static final Random random = new Random(0x20131224 ^ // A seed value
System.currentTimeMillis()); // and more seed value(s).
public static File getRandomFile(String filePath) {
File f = new File(filePath); // Do we have a directory?
if (f == null || ! f.isDirectory()) {
return f;
}
File[] files = f.listFiles();
List<File> al = new ArrayList<File>();
for (File file : files) {
if (file != null && file.isFile() && file.canRead()) { // Make sure it's a file.
al.add(file);
}
}
return al.get(random.nextInt(al.size())); // Get a random file.
}
File filedir=new File("C:\\Users\\ramaraju\\Desktop\\japan02-12\\");
File[] files=filedir.listFiles();
Random generator = new Random();
int Low = 0;
int High = files.length;
int R = generator.nextInt(High-Low) + Low;
System.out.println(R);
for (int i = 0; i < files.length; i++) {
if(i==R)
{
System.out.println(files[i].getName());
}
}
Related
How to assign ArrayList of String to File[] in java. I have tried as shown below
ArrayList<String> fileList;
File[] file;
for (int i = 0; i < fileList.size(); i++) {
file = new File (fileList.get(i));
}
But I am getting file cannot be converted to File[]. Please correct me.
First, you need to initialize the array like
File[] file = new File[list.size()];
Now, you need to access the indexes of the array, like
for(int i = 0;i<fileList.size();i++) {
file[i] = new File(list.get(i));
}
I need help in renaming all files and folders in a directory and add a character in front of there original name.
This is a method to rename a single folder:
File from = new File(sdcard,".DCIM");
File to = new File(sdcard,"DCIM");
from.renameTo(to);
So, something like:
String path = Environment.getExternalStorageDirectory().toString()+"/MyDir";
Log.d("Files", "Path: " + path);
File f = new File(path);
File file[] = f.listFiles();
Log.d("Files", "Size: "+ file.length);
for (int i=0; i < file.length; i++)
{
file[i].renameTo(file[i].getName() + "x");
}
EDIT:
To change a file name, it might be more clear to add a temporary variable:
String name = file[i].getName();
name = name.substr(0, name.length() - 1);
file[i].renameTo(name);
Go to the root folder and iterate over it. Just check if the the folder you are accessing is a directory or not and you can write the same logic in between for every folder.
public static void renameFile(String path) throws IOException {
File root = new File(path);
File[] list = root.listFiles();
if (list == null)
return;
for (File f : list) {
if (f.isDirectory()) {
File from = new File(f,"."+f.getName());
File to = new File(f,f.getName());
from.renameTo(to);
renameFile(f.getCanonicalPath());
} else {
System.out.println("File:" + f.getAbsoluteFile());
}
}
}
public static void main(String[] args) throws IOException {
//Root path within which you want to change the folder names
renameFile("c:\rootPath");
}
Just check if this helps you.
I am using "Files.copy" to copy files from one directory to another. 1 file will work, but when transferring multiple files, the contents of the copied files are the same, but the names are different. Please ignore bad naming. I am just quickly testing.
private void btnOpenActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fc = new JFileChooser();
fc.setMultiSelectionEnabled(true);
fc.showOpenDialog(null);
PathFile = fc.getSelectedFile().getAbsolutePath();
files = fc.getSelectedFiles();
int i=files.length;
System.out.print(i);
filesPath = Arrays.toString(files);
txtPath.setText(PathFile);
}
private void btnMoveActionPerformed(java.awt.event.ActionEvent evt) {
InputStream inStream = null;
OutputStream outStream = null;
String text = txtPath.getText();
String[] list = filesPath.split(",");
//String extension = filename.substring(filename.lastIndexOf('.'), filename.length());
String destPath = txtDest.getText();
try {
for(int i = 0; i<list.length; i++){
String filenamePre = list[i]
.replace(",", "") //remove the commas
.replace("[", "") //remove the right bracket
.replace("]", "");
String filename = filenamePre.substring(filenamePre.lastIndexOf('\\'), filenamePre.length());
System.out.println(filename);
File afile = new File(text);
//File bfile = new File(destPath+"\\file1"+extension);
File bfile = new File(destPath + filename);
Path pa = afile.toPath();
Path pb = bfile.toPath();
//inStream = new FileInputStream(afile);
//outStream = new FileOutputStream(bfile);
//byte[] buffer = new byte[1024];
//int length;
//copy the file content in bytes
// while ((length = inStream.read(buffer)) > 0) {
// outStream.write(buffer, 0, length);
//}
//inStream.close();
//outStream.close();
Files.copy(pa, pb, REPLACE_EXISTING);
//delete the original file
//afile.delete();
}
System.out.println("File(s) copied successful!");
System.out.println();
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}
private void txtPathActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
private void btnOpenDestActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fc = new JFileChooser();
//guiMove frame = new guiMove();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.showOpenDialog(null);
PathDest = fc.getSelectedFile().getAbsolutePath();
txtDest.setText(PathDest);
}
shouldn't the getText method be in your loop when you retrieve the new file?
You are transferring only one file multiple times.
File afile = new File(text);
Source (text) is not changing in loop.
i am not sure what is your filePath content
String[] list = filesPath.split(",");
if you have two text box ( source directory and Destination directory) to get the source and destination .
Then you can get list of files from source like this.
File[] fList = new File(sDir).listFiles();
and loop through flist to get the files like this.
public void fileCopy(String sourceDir , String destDir) throws IOException{
File sDir = new File(sourceDir);
if (!sDir.isDirectory()){
// throw error
}
File dDir = new File(destDir);
if (!dDir.exists()){
dDir.mkdir();
}
File[] files = sDir.listFiles();
for (int i = 0; i < files.length; i++) {
File destFile = new File(dDir.getAbsolutePath()+File.separator+files[i].getName().replace(",", "") //remove the commas
.replace("[", "") //remove the right bracket
.replace("]", "")
.replace(" ", ""));
// destFile.createNewFile();
Files.copy(files[i], destFile);
}
}
I have around 100 files in a folder. And I am trying to read all those files one by one. Each file will have data like this and each line resembles an user id.
960904056
6624084
1096552020
750160020
1776024
211592064
1044872088
166720020
1098616092
551384052
113184096
136704072
So I need to read that file line by line and then store each user id in a LinkedHashSet. I am able to read all the files from a particular folder with the below code. But with the below java code that I wrote, I am not sure how to read those files line by line and then store each user id in a LinkedHashSet?
public static void main(String args[]) {
File folder = new File("C:\\userids-20130501");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
if (file.isFile() && file.getName().endsWith(".txt")) {
try {
String content = FileUtils.readFileToString(file);
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any help will be appreciated on this? And any better way to do the same process?
Since you are using FileUtils. The class has the method readLines() which returns a list of String.
You can then add this List of String to LinkedHashSet by using the addAll() method.
Try this -
public static void main(String args[]) {
File folder = new File("C:\\userids-20130501");
File[] listOfFiles = folder.listFiles();
Set<String> userIdSet = new LinkedHashSet<String>();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
if (file.isFile() && file.getName().endsWith(".txt")) {
try {
List<String> content = FileUtils.readLines(file, Charset.forName("UTF-8"));
userIdSet.addAll(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can use the readLine() method of BufferedReader to read a file line by line as below:
public static void main(String args[]) {
File folder = new File("C:\\userids-20130501");
File[] listOfFiles = folder.listFiles();
Set<String> userIdSet = new LinkedHashSet<String>();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
if (file.isFile() && file.getName().endsWith(".txt")) {
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while((line = br.readLine()) != null) {
userIdSet.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
If I understood you correctly then you can do something like below.
// Change generic if you want Integer
Set<String> userIdSet = new LinkedHashSet<String>();
// Your code
String content = FileUtils.readFileToString(file);
// Creating array by splitting for every new line content
String[] stn = content.split("\\n");
for(String xx : stn){
// parse it as Integer if you changed the generic
// Adding the file content to Set
userIdSet.add(xx);
}
Here are a the things I would do different.
Using an iterator for the files
The new try statement allows opening up a “resource” in a try block and automatically closing the resource when the block is done. Ref
Excluding invalid files with a continue statement. This removes one level of nesting. See this post.
All of these changes are highly opinionated of course.
public static void main(String[] args) {
Set<Integer> users = new LinkedHashSet<Integer>();
File dir = new File("C:\\userids-20130501");
for (File child : dir.listFiles()) {
if (!child.isFile() || !child.getName().endsWith(".txt")) {
continue;
}
try (BufferedReader in = new BufferedReader(
new FileReader(child.getPath()))) {
String id = null;
while ((id = in.readLine()) != null) {
users.add(Integer.parseInt(id));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
This is how I set the path:
dPath = dPath.replace("\\", "/");
String iLen;
String FileName;
File iFolder = new File(dPath);
File[] listOfFiles = iFolder.listFiles();
When searching:
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
FileName = listOfFiles[i].getName();
for(String s : iEndsWith)
{
if(FileName.toLowerCase().endsWith(s))
{
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy h:mm aaa");
iLen = ReadableBytes(listOfFiles[i].length());
Object rowData[] = { FileName, listOfFiles[i].getAbsoluteFile(), sdf.format(listOfFiles[i].lastModified()), iLen };
iTableModel.addRow(rowData);
iTotalFiles ++;
}
}
}
}
That will only look for files in the given directory path, but not it's sub directories. How can I change that?
If you're on Java 7, you can use FileVisitor: http://docs.oracle.com/javase/tutorial/essential/io/walk.html
If not, just use a simple recursive version of your function.
Pass folder as Initial File which is to be searched
File foldr = new File("c:/javaFolder");
public void addFilesToList(File folder) {
File[] listofFiles = folder.listFiles();
if (listofFiles != null) {
for (File file : listofFiles) {
if (file.isFile()) {
} else
addFilesToList(file);
}
}
}
You can use DirectoryWalker from Apache Commons to walk through a directory hierarchy.