Copying Multiple files using SWT filedialog - java

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.

Related

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

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

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.

How to list only non hidden and non system file in jtree

File f=new File("C:/");
File fList[] = f.listFiles();
When i use this it list all system file as well as hidden files.
and this cause null pointer exception when i use it to show in jTree like this:
public void getList(DefaultMutableTreeNode node, File f) {
if(f.isDirectory()) {
DefaultMutableTreeNode child = new DefaultMutableTreeNode(f);
node.add(child);
File fList[] = f.listFiles();
for(int i = 0; i < fList.length; i++)
getList(child, fList[i]);
}
}
What should i do so that it do not give NullPointerException and show only non hidden and non system files in jTree?
Do this for hidden files:
File root = new File(yourDirectory);
File[] files = root.listFiles(new FileFilter() {
#Override
public boolean accept(File file) {
return !file.isHidden();
}
});
This will not return hidden files.
As for system files, I believe that is a Windows concept and therefore might not be supported by File interface that tries to be system independent. You can use Command line commands though, if those exist.
Or use what #Reimeus had in his answer.
Possibly like
File root = new File("C:\\");
File[] files = root.listFiles(new FileFilter() {
#Override
public boolean accept(File file) {
Path path = Paths.get(file.getAbsolutePath());
DosFileAttributes dfa;
try {
dfa = Files.readAttributes(path, DosFileAttributes.class);
} catch (IOException e) {
// bad practice
return false;
}
return (!dfa.isHidden() && !dfa.isSystem());
}
});
DosFileAttributes was introduced in Java 7.
If running under Windows, Java 7 introduced DosFileAttributes which enables system and hidden files to be filtered. This can be used in conjunction with a FileFilter
Path srcFile = Paths.get("myDirectory");
DosFileAttributes dfa = Files.readAttributes(srcFile, DosFileAttributes.class);
System.out.println("System File? " + dfa.isSystem());
System.out.println("Hidden File? " + dfa.isHidden());
If you are trying to list all files in C:/ please keep in mind that there are other files also which are neither hidden nor system files, but that still won't open because they require special privileges/permissions. So:
String[] files = file.list();
if (files!=null) {
for (String f : files) open(f);
}
So just compare if the array is null or not and design your recursion in such a way that it just skips those files whose array for the list() function is null.
private void nodes(DefaultMutableTreeNode top, File f) throws IOException {
if (f.isDirectory()) {
File[] listFiles = f.listFiles();
if (listFiles != null) {
DefaultMutableTreeNode b1[] = new DefaultMutableTreeNode[listFiles.length];
for (int i = 0; i < b1.length; i++) {
b1[i] = new DefaultMutableTreeNode(listFiles[i].toString());
top.add(b1[i]);
File g = new File(b1[i].toString());
nodes(b1[i], g);
}
}
}
Here is the code I used to create a window file explorer using jtree.

How do you make a function that will create a .jar file in Java?

I've made some code in Java that will change some files in another .jar file, and I know that the unpacking/changing works, but the repacking doesn't. It does succeed, but when I compare the new one and the original (I removed the code that changed the files), they differed. What's interesting is that when I extracted them both into different directories, and I runned diff -rqy on them both, it didn't show any difference.
Here is the current function:
public static void add(File source, JarOutputStream target, String removeme)
throws IOException
{
BufferedInputStream in = null;
try
{
File source2 = new File(source.getPath().replaceAll("^" + removeme,
""));
// File source2 = source;
if (source.isDirectory())
{
String name = source2.getPath().replace("\\", "/");
if (!name.isEmpty())
{
if (!name.endsWith("/"))
name += "/";
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile : source.listFiles())
add(nestedFile, target, removeme);
return;
}
JarEntry entry = new JarEntry(source2.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[2048];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally
{
if (in != null)
in.close();
}
}
I call it like this:
JarOutputStream zip = new JarOutputStream(
new FileOutputStream(JARFILE));
for (File nestedFile : new File(DIRECTORY).listFiles())
{
Utils.add(nestedFile, zip,
new File(DIRECTORY).getAbsolutePath());
}
zip.close();
Can anyone direct me on what to change in the function, or what other function I should use? The directory has subdirectories, so I need a function that will scan them.
Thanks in advance!
Edit: I don't want something using the jar command, because I don't want the user to need to install the JDK. I want something using pure Java (libraries are OK, as long as I can include them in the program).
Edit 2: I'm making a Minecraft modder (like MCPatcher and ModLoader), but when I run java -jar minecraft.jar, it gives me this: Invalid or corrupt jarfile. The correct .jar doesn't give this (just a main class error, which is supposed to happen).
I think you maybe interested in java.util.jar. This link maybe useful for you..
http://www.theserverside.com/discussions/thread.tss?thread_id=32600

How to upload multiple files using Swings Applications?

I m trying to upload multiple files in swings applications.I have declared an array to hold the values of selected files but when i click on upload button only 1 file is getting uploaded. How can i upload all selected files into database?
The code to Open and Upload File is ....
public void openFile()
{
JFileChooser jfc = new JFileChooser();
jfc.setMultiSelectionEnabled(true);// added line
int result = jfc.showOpenDialog(this);
if(result == JFileChooser.CANCEL_OPTION) return;
try {
ArrayList<String> FileData = new ArrayList<String>();
File[] file = jfc.getSelectedFiles();
String s=""; int c=0;
for(int i=0;i<file.length;i++) //added
{
jep.setText(file[i].toString()); // added
}
return FileData;
}
catch (Exception e)
{
JOptionPane.showMessageDialog(this,e.getMessage(),
"File error",JOptionPane.ERROR_MESSAGE);
}
}
You haven't clearly defined what you actually mean by "upload multiple files". I'm presuming that you wish to load the contents of multiple text files one after the other into a single JEditorPane. If that is the case, Romain's answer shows you an example of loading a single file.
What your code is actually doing though is looping through the array of File objects and setting their path (that is what toString returns on File) as the text within your editor pane. Each one is overriding the last, so that is why you end up with a single file path.
I might also suggest when you pop up your JFileChooser you limit the files a user can select to specific file types (e.g. txt, html).
// get list of selected files
File[] file = jfc.getSelectedFiles();
String s=""; int c=0;
for(int i=0;i<file.length;i++) //added
{
// The toString will just return you back the path of the file object times the number of bytes in the file.
jep.setText(file[i].toString()); // added
}
return FileData;
This code will not work. If you want a method to read a file given a file name into an array of Strings then you will need:
/**
* Read entire contents of a text file.
*
* #param fileName Text file name
* #return ArrayList of String (line) elements
* #throws FileNotFoundException
* #throws IOException
*/
public static ArrayList readTextFile( String fileName )
throws FileNotFoundException, IOException
{
ArrayList lines = new ArrayList();
BufferedReader in = null;
try
{
in = new BufferedReader( new FileReader( fileName ));
String line;
while ( ( line = in.readLine()) != null )
{
lines.add( line );
}
}
finally
{
if ( in != null )
{
try
{
in.close();
}
catch ( IOException ex )
{
}
}
}
return lines;
}
Since you want to read in the contents of several file, just do this in a loop and do each one individually. If you load it all in memory you might run into problems.

Categories