I would like to write a function copy(File f1, File f2)
f1 is always a file.
f2 is either a file or a directory.
If f2 is a directory I would like to copy f1 to this directory (the file name should stay the same).
If f2 is a file I would like to copy the contents of f1 to the end of the file f2.
So for example if F2 has the contents:
2222222222222
And F1 has the contents
1111111111111
And I do copy(f1,f2) then f2 should become
2222222222222
1111111111111
Thanks!
Apache Commons IO to the rescue!
Expanding on Allain's post:
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2, true); // appending output stream
try {
IOUtils.copy(in, out);
}
finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
Using Commons IO can simplify a lot of the stream grunt work.
Using the code from the answer by Allain Lolande and extending it, this should address both parts of your question:
File f1 = new File(srFile);
File f2 = new File(dtFile);
// Determine if a new file should be created in the target directory,
// or if this is an existing file that should be appended to.
boolean append;
if (f2.isDirectory()) {
f2 = new File(f2, f1.getName());
// Do not append to the file. Create it in the directory,
// or overwrite if it exists in that directory.
// Change this logic to suite your requirements.
append = false;
} else {
// The target is (likely) a file. Attempt to append to it.
append = true;
}
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(f1);
out = new FileOutputStream(f2, append);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} finally {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
}
FileOutputStream has a constructor that allows you to specify append as opposed to overwrite.
You can use this to copy the contents of f1 to the end of f2 as below:
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2, true);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
Check out the link below. it is a source file that copies a file to another using NIO.
http://www.java2s.com/Code/Java/File-Input-Output/CopyafileusingNIO.htm
Related
I have tried multiple examples... But non will work for me
Make tar file by Java
If I use above code, After reading the line TarOutputStream out = new TarOutputStream( new BufferedOutputStream( dest ) ); it just come out of the method(i.e.After reading that line... it won't executed the code which are after to that. The Sequence directly gone to the finally block where that method called).
For another example, I used apache common compress Jar. In that case it won't execute the java class itself it exit from the FormBean class.
The files are fetched from the database and it will be in a CSV format and all the files are placed in an Array List.
fileNames = "Security.smod."+SYSDATE;
strSavePath = D\:\\CMSREPORT\\reportZip\\
tarFunction(fileList, strSavePath, fileNames);
//Example function 1
private String tarFunction(ArrayList fileList, String strSavePath, String outFileName) {
int fileCountSize = fileList.size();
// Output file stream
FileOutputStream dest = new FileOutputStream( strSavePath );
// Create a TarOutputStream
TarOutputStream out = new TarOutputStream( new BufferedOutputStream( dest ) );
// Files to tar
File[] filesToTar=new File[3];
for(int i=0; i<fileCountSize; i++)
{
filesToTar[i]=new File((String) fileList.get(i);
}
for(File f:filesToTar){
out.putNextEntry(new TarEntry(f, f.getName()));
BufferedInputStream origin = new BufferedInputStream(new FileInputStream( f ));
int count;
byte data[] = new byte[2048];
while((count = origin.read(data)) != -1) {
out.write(data, 0, count);
}
out.flush();
origin.close();
}
}
For Example 2, I used apache.common.compress.1.2 as a jar.
In that case, It won't execute the java class, it exited from the FormBean class.
//Example function 2
private void tarFunc(){
try{
// Files to tar
File resource1 = new File((String) fileList.get(0));
File resource2 = new File((String) fileList.get(1));
File resource3 = new File((String) fileList.get(2));
// Output Stream - that will hold the physical TAR file
OutputStream tar_output = new FileOutputStream(new File(fileNames+".tar"));
// Create Archive Output Stream that attaches File Output Stream / and specifies TAR as type of compression
ArchiveOutputStream my_tar_ball = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.TAR, tar_output);
// Create Archieve entry - write header information
TarArchiveEntry tar_file = new TarArchiveEntry(resource1);
// length of the TAR file needs to be set using setSize method
tar_file.setSize(resource1.length());
my_tar_ball.putArchiveEntry(tar_file);
IOUtils.copy(new FileInputStream(resource1), my_tar_ball);
// Close Archieve entry, write trailer information
my_tar_ball.closeArchiveEntry();
// Repeat steps for the next file that needs to be added to the TAR
tar_file = new TarArchiveEntry(resource2);
tar_file.setSize(resource2.length());
my_tar_ball.putArchiveEntry(tar_file);
IOUtils.copy(new FileInputStream(resource2), my_tar_ball);
// Close Archieve entry, write trailer information
my_tar_ball.closeArchiveEntry();
tar_file = new TarArchiveEntry(resource3);
tar_file.setSize(resource3.length());
my_tar_ball.putArchiveEntry(tar_file);
IOUtils.copy(new FileInputStream(resource3), my_tar_ball);
// Close Archieve entry, write trailer information
my_tar_ball.closeArchiveEntry();
my_tar_ball.finish();
// Close output stream, our files are zipped
tar_output.close();
}catch(Exception e){
e.printStackTrace();
}
}
Anyone please help to solve this issue. Thank you:)
I have this little piece of code
public void doBuild() throws IOException {
ZipEntry sourceEntry=new ZipEntry(sourcePath);
ZipEntry assetEntry=new ZipEntry(assetPath);
ZipOutputStream out = new ZipOutputStream(new FileOutputStream("output/"+workOn.getName().replaceAll(".bld"," ")+buildNR+".zip"));
out.putNextEntry(sourceEntry);
out.putNextEntry(assetEntry);
out.close();
System.err.println("Build success!");
increaseBuild();
}
So, if I run it it runs trough it fine, creates the .zip and all, but the zip file is empty. sourceEntry and assetEntry are both directories. How could I get those directories to my .zip easily?
For those interested this is a MC mod build system and can be found at https://bitbucket.org/makerimages/makerbuild-system NOTE: the code above is not commited or pushed to there yet!!!!!!!!
Try something like this. The parameter useFullFileNames specifies
whether you want to preserve the full names of the paths to the
files which you're about to zip.
So if you have two files
/dir1/dir2/a.txt
and
/dir1/b.txt
the useFullFileNames specifies if you want to finally see in
the zip file those original paths to the two files or just
the two files with no paths like this
a.txt
and
b.txt
in the root of the zip file which you create.
Note that in my example, the files which are zipped
are actually read and then written to out.
I think you're missing that part.
public static boolean createZip(String fNameZip, boolean useFullFileNames, String... fNames) throws Exception {
try {
int cntBufferSize = 256 * 1024;
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(fNameZip);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte bBuffer[] = new byte[cntBufferSize];
File ftmp = null;
for (int i = 0; i < fNames.length; i++) {
if (fNames[i] != null) {
FileInputStream fi = new FileInputStream(fNames[i]);
origin = new BufferedInputStream(fi, cntBufferSize);
ftmp = new File(fNames[i]);
ZipEntry entry = new ZipEntry(useFullFileNames ? fNames[i] : ftmp.getName());
out.putNextEntry(entry);
int count;
while ((count = origin.read(bBuffer, 0, cntBufferSize)) != -1) {
out.write(bBuffer, 0, count);
}
origin.close();
}
}
out.close();
return true;
} catch (Exception e) {
return false;
}
}
I have the following situation:
I am able to zip my files with the following method:
public boolean generateZip(){
byte[] application = new byte[100000];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// These are the files to include in the ZIP file
String[] filenames = new String[]{"/subdirectory/index.html", "/subdirectory/webindex.html"};
// Create a buffer for reading the files
try {
// Create the ZIP file
ZipOutputStream out = new ZipOutputStream(baos);
// Compress the files
for (int i=0; i<filenames.length; i++) {
byte[] filedata = VirtualFile.fromRelativePath(filenames[i]).content();
ByteArrayInputStream in = new ByteArrayInputStream(filedata);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(filenames[i]));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(application)) > 0) {
out.write(application, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
out.close();
} catch (IOException e) {
System.out.println("There was an error generating ZIP.");
e.printStackTrace();
}
downloadzip(baos.toByteArray());
}
This works perfectly and I can download the xy.zip which contains the following directory and file structure:
subdirectory/
----index.html
----webindex.html
My aim is to completely leave out the subdirectory and the zip should only contain the two files. Is there any way to achieve this?
(I am using Java on Google App Engine).
Thanks in advance
If you are sure the files contained in the filenames array are unique if you leave out the directory, change your line for constructing ZipEntrys:
String zipEntryName = new File(filenames[i]).getName();
out.putNextEntry(new ZipEntry(zipEntryName));
This uses java.io.File#getName()
You can use Apache Commons io to list all your files, then read them to an InputStream
Replace the line below
String[] filenames = new String[]{"/subdirectory/index.html", "/subdirectory/webindex.html"}
with the following
Collection<File> files = FileUtils.listFiles(new File("/subdirectory"), new String[]{"html"}, true);
for (File file : files)
{
FileInputStream fileStream = new FileInputStream(file);
byte[] filedata = IOUtils.toByteArray(fileStream);
//From here you can proceed with your zipping.
}
Let me know if you have issues.
You could use the isDirectory() method on VirtualFile
I have chosen file using
File file = fileChooser.getSelectedFile();
Now I want to write this file chosen by user to another location when user clicks save button. How to achieve that using swing?
To select the file you need something like ,
JFileChooser open = new JFileChooser();
open.showOpenDialog(this);
selected = open.getSelectedFile().getAbsolutePath(); //selected is a String
...and to save a copy ,
JFileChooser save = new JFileChooser();
save.showSaveDialog(this);
save.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
tosave = fileChooser.getSelectedFile().getAbsolutePath(); //tosave is a String
new CopyFile(selected,tosave);
...the copyFile class will be something like,
public class CopyFile {
public CopyFile(String srFile, String dtFile) {
try {
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage() + " in the specified directory.");
System.exit(0);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Also have a look at this question : How to save file using JFileChooser? #MightBeHelpfull
Swing will just give you the location/File object. You are going to have to write the new file yourself.
To copy the file, I will point you to this question: Standard concise way to copy a file in Java?
If you are using JDK 1.7 you can use the java.nio.file.Files class which offers several copy methods to copy a file to a given destiny.
read the file into a InputStream and then write it out to an OutputStream.
For example, I want to zip a file stored in /Users/me/Desktop/image.jpg
I made this method:
public static Boolean generateZipFile(ArrayList<String> sourcesFilenames, String destinationDir, String zipFilename){
// Create a buffer for reading the files
byte[] buf = new byte[1024];
try {
// VER SI HAY QUE CREAR EL ROOT PATH
boolean result = (new File(destinationDir)).mkdirs();
String zipFullFilename = destinationDir + "/" + zipFilename ;
System.out.println(result);
// Create the ZIP file
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFullFilename));
// Compress the files
for (String filename: sourcesFilenames) {
FileInputStream in = new FileInputStream(filename);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(filename));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
} // Complete the ZIP file
out.close();
return true;
} catch (IOException e) {
return false;
}
}
But when I extract the file, the unzipped files have the full path.
I don't want the full path of each file in the zip i only want the filename.
How can I made this?
Here:
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(filename));
You're creating the entry for that file using the whole path. If you just use the name ( without the path ) you'll have what you need:
// Add ZIP entry to output stream.
File file = new File(filename); //"Users/you/image.jpg"
out.putNextEntry(new ZipEntry(file.getName())); //"image.jpg"
You're finding your source data using the relative path to the file, then setting the Entry to the same thing. Instead you should turn the source into a File object, and then use
putNextEntry(new ZipEntry(sourceFile.getName()))
that'll give you just the final part of the path (ie, the actual file name)
Do as Jason said, or if you want to keep your method signature, do it like this:
out.putNextEntry(new ZipEntry(new File(filename).getName()));
or, using FileNameUtils.getName from apache commons/io:
out.putNextEntry(new ZipEntry(FileNameUtils.getName(filename)));
You could probably get away with accessing source files via new FileInputStream(new File(sourceFilePath, sourceFileName)).
// easy way of zip a file
import java.io.*;
import java.util.zip.*;
public class ZipCreateExample{
public static void main(String[] args) throws Exception {
// input file
FileInputStream in = new FileInputStream("F:/ZipCreateExample.txt");;
// out put file
ZipOutputStream out =new ZipOutputStream(new FileOutputStrea("F:/tmp.zip"));
// name of file in zip folder
out.putNextEntry(new ZipEntry("zippedfile.txt"));
byte[] b = new byte[1024];
int count;
// writing files to new zippedtxt file
while ((count = in.read(b)) > 0) {
System.out.println();
out.write(b, 0, count);
}
out.close();
in.close();
}
}
try {
String zipFile = "/locations/data.zip";
String srcFolder = "/locations";
File folder = new File(srcFolder);
String[] sourceFiles = folder.list();
//create byte buffer
byte[] buffer = new byte[1024];
/*
* To create a zip file, use
*
* ZipOutputStream(OutputStream out) constructor of ZipOutputStream
* class.
*/
//create object of FileOutputStream
FileOutputStream fout = new FileOutputStream(zipFile);
//create object of ZipOutputStream from FileOutputStream
ZipOutputStream zout = new ZipOutputStream(fout);
for (int i = 0; i < sourceFiles.length; i++) {
if (sourceFiles[i].equalsIgnoreCase("file.jpg") || sourceFiles[i].equalsIgnoreCase("file1.jpg")) {
sourceFiles[i] = srcFolder + fs + sourceFiles[i];
System.out.println("Adding " + sourceFiles[i]);
//create object of FileInputStream for source file
FileInputStream fin = new FileInputStream(sourceFiles[i]);
/*
* To begin writing ZipEntry in the zip file, use
*
* void putNextEntry(ZipEntry entry) method of
* ZipOutputStream class.
*
* This method begins writing a new Zip entry to the zip
* file and positions the stream to the start of the entry
* data.
*/
zout.putNextEntry(new ZipEntry(sourceFiles[i].substring(sourceFiles[i].lastIndexOf("/") + 1)));
/*
* After creating entry in the zip file, actually write the
* file.
*/
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
/*
* After writing the file to ZipOutputStream, use
*
* void closeEntry() method of ZipOutputStream class to
* close the current entry and position the stream to write
* the next entry.
*/
zout.closeEntry();
//close the InputStream
fin.close();
}
}
//close the ZipOutputStream
zout.close();
System.out.println("Zip file has been created!");
} catch (IOException ioe) {
System.out.println("IOException :" + ioe);
}
If you zip two files of the same name but with different paths you will run into duplicate file entry errors, though.