Having a variable from another class as the file name (GUI) - java

One class of my GUI has a variable for the file name. I want to pass this to another class so that I can process a file without having to hard code the file's name every time. The program compiles fine but I can't seem to run it correctly.
public void run() {
WordsCounter2 fileName = new WordsCounter2();
essayName = fileName.getFileList();
File f = new File(essayName);
//other code
WordsCounter2 is the class that houses the variable fileName, I'm calling it from this class and assigning it as the file's name, but this doesn't work. Could someone help?
if (rVal == JFileChooser.APPROVE_OPTION) {
File[] selectedFile = fileChooser.getSelectedFiles();
fileList = "nothing";
if (selectedFile.length > 0)
fileList = selectedFile[0].getName();
for (int i = 1; i < selectedFile.length; i++) {
fileList += ", " + selectedFile[i].getName();
}
statusBar.setText("You chose " + fileList);
}
else {
statusBar.setText("You didn't choose a file.");
}
fileList isn't empty because I have a label on the GUI that lists whatever file I chose.
Here's my new edit: now the exception occurs at the last line with the scanner and throws a NPE. Can you help?
public void run() {
WordsCounter2 pathNamesList = new WordsCounter2();
essayName = pathNamesList.getPathNamesList();
essayTitle = new String[essayName.size()];
essayTitle = essayName.toArray(essayTitle);
for (int i = 0; i < essayTitle.length; i++) {
f = new File(essayTitle[i]);
}
try {
Scanner scanner = new Scanner(f);

Your code is failing because File will not accept comma separated file names, in fact, it needs a single file path to create the file in the mentioned path. See here: https://docs.oracle.com/javase/7/docs/api/java/io/File.html
You'll have to get complete paths in an array and put the file creation statement as follows:
File f;
for (int i=0; i<fileList.length; i++)
f = new File(fileList[i]);
where fileList is a String array holding the list of pathnames.
In case you're trying to write some content to these files as well, this should be helpful: Trying to Write Multiple Files at Once - Java

Related

Copying Multiple files using SWT filedialog

I'm working a transfer file program and my program is working but I'm having a problem because when I select multiple files and put it on a textbox the source directory can't read what is on the textbox
this is my code
Opening file/files
btnSearchFile.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
FileDialog fd = new FileDialog(shell, SWT.MULTI);
Collection files = new ArrayList();
String firstFile = fd.open();
if (firstFile != null) {
String[] selectedFiles = fd.getFileNames();
File file = new File(firstFile);
for (int ii = 0; ii < selectedFiles.length; ii++ )
{
if (file.isFile())
{
displayFiles(new String[] { file.toString()});
}
else
displayFiles(file.list());
}
}
}
});
Displaying Files on textbox
public void displayFiles(String[] files) {
for (int i = 0; files != null && i < files.length; i++) {
txtSource.append(files[i]);
txtSource.setEditable(false);
}
}
Copy Files
public static void copyFile(File src, File dest) throws IOException
{
InputStream oInStream = new FileInputStream(src);
OutputStream oOutStream = new FileOutputStream(dest);
// Transfer bytes from in to out
byte[] oBytes = new byte[1024];
int nLength;
BufferedInputStream oBuffInputStream = new BufferedInputStream( oInStream );
while ((nLength = oBuffInputStream.read(oBytes)) > 0)
{
oOutStream.write(oBytes, 0, nLength);
}
oInStream.close();
oOutStream.close();
}
PS: One file is okay but if multiple files are selected and put on the textbox the source directory can't be found
In order to be completely helpful, we could really use some more detail (specific exceptions, a complete MCVE, which SWT widgets are used, etc.).
That said, I think you've provided enough to see that there are some issues with your code:
For starters, when you have multiple files selected, you're displaying the same file name (the name of the first one) over and over. Perhaps this is intentional, but worth mentioning:
String[] selectedFiles = fd.getFileNames();
File file = new File(firstFile);
for (int ii = 0; ii < selectedFiles.length; ii++ )
{
// You've used a FileDialog, so this should always be true
if (file.isFile())
{
// Will always be the first file
displayFiles(new String[] { file.toString()});
}
else
displayFiles(file.list());
}
Based on the context, I'm assuming txtSource is a Text widget. With that in mind, if we look at your displayFiles() method, you have the following:
txtSource.append(files[i]);
When you call displayFiles() repeatedly, you will be tacking on a file name after all the others, effectively building one long String which is the combination of all file names. When you go to copy the files listed, splitting that String back into valid file paths will be tricky.
My guess is that when you say:
"the source directory can't be found"
...you're just grabbing the content of txtSource. Something like this:
new File(txtSource.getText());
"...One file is okay..."
That will certainly work if there's only one file name in the Text object, but if there are multiple names it will result in a non-existent File.
For example, if you've selected two files:
C:\Users\me\FileA
C:\Users\me\FileB
Your txtSource would display C:\Users\me\FileAC:\Users\me\FileB. And the path C:\Users\me\FileAC:\Users\me\FileB most likely does not exist.
In that case, new File(txtSource.getText()).exists() would return false, and using that File in the constructor for FileInputStream (inside copyFile()) would result in a FileNotFoundException.
In short, just make sure that when you make your call to copyFile() and create the source File object that you're giving the path that you think you are, and not the concatenation of all files selected.

Remove certain characters from a directory's name in Java

So I wrote a little program to use on a Unix machine that has to get all the names of the files and folders in a directory where it is stored and then remove all the characters from them. These characters (or a character) will be defined by a user. Use case: I put the program in the directory containing various useless files and directories named, for example, "NaCl2!!!!!!!!!", "H2O!", "O2" and "Lithium!!!!!" and I "ask" it to get rid of all the bangs in all the directores' names so it will result in this:
ls
NaCl2 H2O O2 Lithium Unreal3.zip
Ok I guess you get it. So here's the code and it doesn't compile (
DirRename.java:18: error: method renameTo in class File cannot be applied to given types;
tempDir.renameTo(name);
). I guess this error is caused with a substantial problem in my code. Is there a way to get it working, can you tell me, please?
import java.io.*; import java.util.Scanner;
class DirRename {
public static void main(String[] s) {
//DECLARING
String name, curDir, annoyngChar;
Scanner scan = new Scanner(System.in);
//WORKING
curDir = System.getProperty("user.dir");
File dir = new File(curDir);
File[] listOfFiles = dir.listFiles();
System.out.print("Type a character (or a line of them) that you want to remove from directories' names:");
annoyngChar = scan.nextLine();
System.out.println("\nAll directories will get rid of " + annoyngChar + " in their names.");
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isDirectory() ) {
File tempDir = listOfFiles[i];
name = tempDir.getName().replaceAll(annoyngChar, "");
tempDir.renameTo(name);
}
}
}
}
Need to say, the program is unfinished, I am sorry for that.
File.renameTo(File dest) takes a File parameter, not a String. So, you need to create a File instance with the correct path (using the new name), and pass that instance to renameTo.
Try this (not tested):
import java.io.*; import java.util.Scanner;
class DirRename {
public static void main(String[] s) {
//DECLARING
String name, curDir, annoyngChar;
Scanner scan = new Scanner(System.in);
//WORKING
curDir = System.getProperty("user.dir");
File dir = new File(curDir);
File[] listOfFiles = dir.listFiles();
System.out.print("Type a character (or a line of them) that you want to remove from directories' names:");
annoyngChar = scan.nextLine();
System.out.println("\nAll directories will get rid of " + annoyngChar + " in their names.");
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isDirectory() ) {
File f = listOfFiles[i];
String oldName = f.getName();
name = oldName.replaceAll(annoyngChar, "");
if (!oldName.equals(name)) {
File newF = new File(dir, name);
f.renameTo(newF);
}
}
}
}
}
Alternatively, you can use Files.move to rename the file. The documentation has an example of how to rename a file while keeping it in the same directory.

Iterating through array using for loop - keeps failing?

(Hello world level tester here)
I've got a java application to delete a bunch of files post tests to keep everything clean, however the issue is I can't seem to get it to work, this is my first time touching on an array and it's a slightly more complex one than the ones they show in the tutorials, any assistance would be greatly appreciated.
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
File filePath = new File(home+fileArray);
System.out.println(filePath);
for (String count: fileArray) {
if (filePath.exists()) {
filePath.delete();
System.out.println("Deleted");
}
else
{
System.out.println("failed");
Assert.fail();
}
System.out.println(count);
}
You should concat new file path for every element in an array, so need to put work with a file in for body. So in every iteration, you get in variable filePath next element of an array and then you need to concat this variable to base path home + filePath. Now you are looking at needed file, you can create file object and work with it.
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
for (String filePath: fileArray) {
File file = new File(home + filePath);
System.out.println(filePath);
if (file.exists()) {
file.delete();
System.out.println("Deleted");
} else {
System.out.println("failed");
Assert.fail();
}
}
Seem like you expect that in variable count you will see a number of iterated files. In this case, it does not work like this. Such form of for acting like this: for (String arrayElement : arrayToWorkWith) - mean that on every iteration in variable arrayElement will be put next element from array arrayToWorkWith. If you need to count number of element during iterations you can introduce separate variable and increment it or use another form of for cycle - for (int i = 0; i < fileArray.length; i++).
try it this way
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
//File filePath = new File(home+fileArray); thats wrong here and will give you a invalid file anyway as you concatenating a string with an object
for (String file: fileArray) {
File filePath = new File(home+file); //here you need to define the file
if (filePath.exists()) {
filePath.delete();
System.out.println("Deleted");
}
else
{
System.out.println("failed");
Assert.fail();
}
System.out.println(file);
}

Extract zip and re-zip with password in java

I am trying to extract list of zip files from folder and then re-zipping them with password. The problem is while re-zipping, the iteration/loop is not stopping. Also, re-zipped files should be a separate zip file each rather than merging all contents to one zip.
Here's what I have tried:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
public class AddFilesWithAESEncryption2 {
public AddFilesWithAESEncryption2() {
try {
//Extract Zip files as folders
try {
String ZipSourcePath = "E:/EZipTest/";
String ExtractTo = "D:/DZipTest/";
String files1;
File folder1 = new File(ZipSourcePath);
File[] listOfFiles1 = folder1.listFiles();
for (int i = 0; i < listOfFiles1.length; i++) {
if (listOfFiles1[i].isFile()) {
files1 = listOfFiles1[i].getName();
String ZipFiles = "E:/EZipTest/" + files1;
try {
ZipFile zipFile = new ZipFile(ZipFiles);
List fileHeaderList = zipFile.getFileHeaders();
zipFile.extractAll(ExtractTo);
} catch (ZipException e) {
e.printStackTrace();
}
}
}
//Get list of folders
String DirectoryNames;
String ExtractedDirectories1 = "D:/DZipTest/";
File folder2 = new File(ExtractedDirectories1);
File[] listOfFiles2 = folder2.listFiles();
for (int i = 0; i < listOfFiles2.length; i++) {
if (listOfFiles2[i].isDirectory()) {
DirectoryNames = listOfFiles2[i].getName();
String ListOfDirectories = "D:/DZipTest/" + DirectoryNames;
//Get list of files
String ExtractedDirectories = ListOfDirectories;
File folder3 = new File(ExtractedDirectories);
File[] listOfFiles3 = folder3.listFiles();
for (int j = 0; j < listOfFiles3.length; j++) {
File file = listOfFiles3[j];
if (file.isFile()) {
String FileNames = file.getName();
System.out.println(ListOfDirectories + FileNames);
//Compress and zip the files
ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
ArrayList filesToAdd = new ArrayList();
filesToAdd.add(new File(ListOfDirectories + FileNames));
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
parameters.setPassword("test");
zipFile.addFiles(filesToAdd, parameters);
}
}
}
}
} catch (ZipException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new AddFilesWithAESEncryption2();
}
}
Refactoring
Refactoring your code will help you understand what it does. It will reveal the problem and immediately identify a fix. Here's how it goes. Note that this is not a complete tutorial, but I hope you get the point.
First, extract a nice method that does the unzipping. Mark everything inside the first for loop, then right click and choose Refactor / Extract Method.... Name it unzipFile. Note that you now have a nice small, potentially reusable and potentially testable (JUnit) method.
Next, mark everything from ZipParameters parameters to parameters.setPassword("test"); Right click, Refactor / Extract Method.... Name it getEncryptionParameters. Note how 7 lines of code have been removed from the long method and readability is improved.
Right click on parameters and choose Refactor / Inline .... Note how the temporary variable disappears.
See the bug
If you have followed closely, there is a piece of code like this:
//Compress and zip the files
ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
ArrayList filesToAdd = new ArrayList();
filesToAdd.add(new File(ListOfDirectories + FileNames));
zipFile.addFiles(filesToAdd, getEncryptionParameters());
See what it does? It creates a new ZIP file, adds only one file to filesToAdd and that's it. But why? It says FileNames. How can that be one file only?
Looking at
String FileNames = file.getName();
that's really just one file, so the variable name is wrong.
Right click FileNames and choose Refactor/Rename.... Enter fileName. Note how the variable name in your program matches to what it really is. It heavily improves readability of the code.
Simplify
Now that you know you're adding only one file, use addFile() instead of addFiles(). You're getting rid of the ArrayList:
//Compress and zip the files
ZipFile zipFile = new ZipFile("D:/" + listOfFiles2[i].getName() + ".zip");
File fileToAdd = new File(ListOfDirectories + fileName);
zipFile.addFile(fileToAdd, getEncryptionParameters());
Fix the bug
As spotted before, a new ZipFile(...) is created inside the loop and only one file is added to it. Move that line out of the loop pressing Alt+Up.
Continue refactoring
A part of the problem is already fixed (I haven't tried, actually), but your code is still not error-free. Let's go on:
Mark everything from File[] listOfFiles3 to the end of the for loop that follows. Right click, Refactor/Extract Method..., name it rezip. Your big method becomes smaller again.
Right click on ExtractedDirectories, Refactor / Inline .... You just got rid of a unnecessary temporary variable.
See something? Your code should look like this:
//Get list of files
File folder3 = new File(ListOfDirectories);
rezip(listOfFiles2, i, ListOfDirectories, folder3);
Note how folder3 and ListOfDirectories is essentially the same. Let's get rid of it. Move the line File folder3 = new File(ListOfDirectories); into the method, just behind private void rezip(...){ and remove the parameter File folder3 from both, the method call and the method declaration of rezip().
The loop using rezip() now looks like this:
for (int i = 0; i < listOfFiles2.length; i++) {
if (listOfFiles2[i].isDirectory()) {
DirectoryNames = listOfFiles2[i].getName();
String ListOfDirectories = "D:/DZipTest/" + DirectoryNames;
rezip(listOfFiles2, i, ListOfDirectories);
}
}
You might spot that DirectoryNames is actually just one, not many. Right click, Refactor/Rename.... Enter subDirectory.
Right click subDirectory, Refactor / Inline .... Read the error message. Right click References / Workspace. Check the results and find out that this variable is only used within the for loop. Delete the declaration outside and declare it at its first use. Now do the Refactor / Inline ... operation.
Your code looks like this:
for (int i = 0; i < listOfFiles2.length; i++) {
if (listOfFiles2[i].isDirectory()) {
String ListOfDirectories = "D:/DZipTest/" + listOfFiles2[i].getName();
rezip(listOfFiles2, i, ListOfDirectories);
}
}
Again, there's a variable name indicating a list or an Array, but that's not true. Refactor / Rename..., name it directoryToZip.
Inline the following variables in this order: ExtractedDirectories1, folder2, ZipSourcePath, folder1.
Rename in this order listOfFiles1 to zipFiles and listOfFiles2 to extractedDirectories.
Remove files1 since it is never used.
The final bug
The method is now short and readable enough to understand it completely. Does the following make sense?
String ExtractTo = "D:/DZipTest/";
File[] zipFiles = new File("E:/EZipTest/").listFiles();
for (int i = 0; i < zipFiles.length; i++) {
unzipFile(ExtractTo, zipFiles, i);
}
File[] extractedDirectories = new File("D:/DZipTest/").listFiles();
for (int i = 0; i < extractedDirectories.length; i++) {
if (extractedDirectories[i].isDirectory()) {
String directoryToZip = "D:/DZipTest/" + extractedDirectories[i].getName();
rezip(extractedDirectories, i, directoryToZip);
}
}
No it doesn't.
You don't want to extract all archives first but one by one
You don't want to zip subdirectories, you want to zip everything in the ExtractTo directory
Fixing the final bug
The signature of unzipFile() does not look right. If it unzips one file only as the name suggests, why does it get access to all files then?
Replace unzipFile(ExtractTo, zipFiles, i); by unzipFile(ExtractTo, zipFiles[i]);. This breaks the code. Eclipse will mark it red. Fix it by changing the parameters from
private void unzipFile(String ExtractTo, File[] listOfFiles1, int i)
to
private void unzipFile(String ExtractTo, File listOfFiles1)
Inside unzip, replace listOfFiles1[i] by listOfFiles1. Then Refactor/Rename... it to sourceZipFile.
Similar for the rezip method: it should get the directory to zip and the target file name only. Therefore change
rezip(extractedDirectories, i, directoryToZip);
to
rezip(extractedDirectories[i], directoryToZip);
Then adapt the method itself from
private void rezip(File[] listOfFiles2, int i, String ListOfDirectories) throws ZipException
to
private void rezip(File listOfFiles2, String ListOfDirectories) throws ZipException
then change listOfFiles2[i] to listOfFiles2. Rename it to targetFile.
Now you have a nice unzipFile() method and a rezip() method. Let's combine it in a cool way:
String ExtractTo = "D:/DZipTest/";
File[] zipFiles = new File("E:/EZipTest/").listFiles();
for (int i = 0; i < zipFiles.length; i++) {
unzipFile(ExtractTo, zipFiles[i]);
rezip(zipFiles[i], ExtractTo);
// TODO: delete extracted files here
}
Awesome, ain't it?
Notes
Maybe you've seen how much effort it is to understand your code and provide a fix. Actually, too much effort for Stack Overflow. Next time you ask a question, please try to provide code that is at minumum as readable as your code now.
The code is still not as clean as it should be. Spend some more time on it. When you think it's superb, post it on https://codereview.stackexchange.com/ to get even more instructions.

Display the names of all .txt documents within the current (or specified) directory

So I have the following code (which has been shamelessly copied from a tutorial so I can get the basics sorted), in which it asks the player to load their game (text-based adventure game)
but I need a way to display all the saved games in the directory. I can get the current directory no worries. Here is my code:
public void load(Player p){
Sleep s = new Sleep();
long l = 3000;
Scanner i = new Scanner(System.in);
System.out.println("Enter the name of the file you wish to load: ");
String username = i.next();
File f = new File(username +".txt");
if(f.exists()) {
System.out.println("File found! Loading game....");
try {
//information to be read and stored
String name;
String pet;
boolean haspet;
//Read information that's in text file
BufferedReader reader = new BufferedReader(new FileReader(f));
name = reader.readLine();
pet = reader.readLine();
haspet = Boolean.parseBoolean(reader.readLine());
reader.close();
//Set info
Player.setUsername(name);
Player.setPetName(pet);
Player.setHasPet(haspet);
//Read the info to player
System.out.println("Username: "+ p.getUsername());
s.Delay(l);
System.out.println("Pet name: "+ p.getPetName());
s.Delay(l);
System.out.println("Has a pet: "+ p.isHasPet());
} catch(Exception e){
e.printStackTrace();
}
}
}
File currentDirectory = new File(currentDirectoryPath);
File[] saveFiles = currentDirectory.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".txt");
}
});
You can first get a File object for the directory:
File ourDir = new File("/foo/bar/baz/qux/");
Then by checking ourDir.isDirectory() you can make sure you don't accidentally try to work on a file. You can handle this by falling back to another name, or throwing an exception.
Then, you can get an array of File objects:
File[] dirList = ourDir.listFiles();
Now, you may iterate through them using getName() for each and do whatever you need.
For example:
ArrayList<String> fileNames=new ArrayList<>();
for (int i = 0; i < dirList.length; i++) {
String curName=dirList[i].getName();
if(curName.endsWith(".txt"){
fileNames.add(curName);
}
}
This should work:
File folder = new File("path/to/txt/folder");
File[] files = folder.listFiles();
File[] txtFiles = new File[files.length];
int count = 0;
for(File file : files) {
if(file.getAbsolutePath().endsWith(".txt")) {
txtFiles[count] = file;
count++;
}
}
It should be pretty self explanatory, you just need to know folder.listFiles().
To trim down the txtFiles[] array use Array.copyOf.
File[] finalFiles = Array.copyOf(txtFiles, count);
From the docs:
Copies the specified array, truncating or padding with false (if necessary) so the copy has the specified length.

Categories