I wish to create a zip program in Java, which zip files and folders let say structure like this -
folder-one/
folder-one/one.txt
folder-one/two.mp3
folder-one/three.jpg
folder-two/
folder-two/four.doc
folder-two/five.rtf
folder-two/folder-three/
folder-two/folder-three/six.txt
I used zip4j open source, I have collected all the files (with absolute path) in one list then given it to zip but it is zipping files only as in my.zip -
one.txt
two.mp3
three.jpg
four.doc
five.rtf
six.txt
How can I preserve same structure on zipping and unzipping as it was on local earlier. Please suggest if any other open source can help me to zip/unzip in same structure files and folders like other windows zip programs.
Code is below --
public class CreateZipWithOutputStreams {
ArrayList filesToAdd = new ArrayList();
public void CreateZipWithOutputStreams(String sAbsolutePath) {
ZipOutputStream outputStream = null;
InputStream inputStream = null;
try {
ArrayList arrLocal = exploredFolder(sAbsolutePath);
outputStream = new ZipOutputStream(new FileOutputStream(new File("c:\\ZipTest\\CreateZipFileWithOutputStreams.zip")));
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
parameters.setPassword("neelam");
for (int i = 0; i < arrLocal.size(); i++) {
File file = (File) arrLocal.get(i);
outputStream.putNextEntry(file, parameters);
if (file.isDirectory()) {
outputStream.closeEntry();
continue;
}
inputStream = new FileInputStream(file);
byte[] readBuff = new byte[4096];
int readLen = -1;
while ((readLen = inputStream.read(readBuff)) != -1) {
outputStream.write(readBuff, 0, readLen);
}
outputStream.closeEntry();
inputStream.close();
}
outputStream.finish();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public ArrayList exploredFolder(String sAbsolutePath) {
File[] sfiles;
File fsSelectedPath = new File(sAbsolutePath);
sfiles = fsSelectedPath.listFiles();
if (sfiles == null) {
return null;
}
for (int j = 0; j < sfiles.length; j++) {
File f = sfiles[j];
if (f.isDirectory() == true) {
exploredFolder(f.getAbsolutePath());
} else {
filesToAdd.add(f);
}
}
return filesToAdd;
}
public static void main(String[] args) {
new CreateZipWithOutputStreams().CreateZipWithOutputStreams("c:\\ZipTest");
}
}
Thanks!
Okay so first the code that is attached is supposed to work the way it is because the exploredFolder(String absolutePath) method is returning the "files to add" which in turn is being used by the CreateZipWithOutputStreams() method to create a single layered(flat) zip file.
What needs to be done is looping over the individual folders and keep adding them to the ZipOutputStream.
Please go through the link below and you will find the code snippet and detailed explaination.
Let me know if that helps!
http://www.java-forums.org/blogs/java-io/973-how-work-zip-files-java.html
Related
So I have this java program which generates a jar file when we give the path to the content. But the problem is it generate more directories inside the jar file. For an example assume the relevant content is in the directory /home/user/Desktop/sample/bin/tmp. And when I create the jar file it has all those directories inside it, which means inside home directory there is user directory and inside it, there is Desktop directory and so on until the content inside the tmp folder is added. But what I want is, add the content inside this tmp folder directly to the jar without adding those extra directories. Here is the code which I used and I want to modify this or completely rewrite this. Any idea to do it...?
private static void createJar(File source, JarOutputStream target) throws IOException
{
BufferedInputStream in = null;
try
{
if (source.isDirectory())
{
String name = source.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())
createJar(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally
{
if (in != null)
in.close();
}
}
Note that source is the directory and the target is the jar file that I'm going to create.
I've found the answer. Hope someone would need it as I did.
private static void createJar(File source, JarOutputStream target) {
createJar(source, source, target);
}
private static void createJar(File source, File baseDir, JarOutputStream target) {
BufferedInputStream in = null;
try {
if (!source.exists()){
throw new IOException("Source directory is empty");
}
if (source.isDirectory()) {
// For Jar entries, all path separates should be '/'(OS independent)
String name = source.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()) {
createJar(nestedFile, baseDir, target);
}
return;
}
String entryName = baseDir.toPath().relativize(source.toPath()).toFile().getPath().replace("\\", "/");
JarEntry entry = new JarEntry(entryName);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true) {
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
} catch (Exception ignored) {
} finally {
if (in != null) {
try {
in.close();
} catch (Exception ignored) {
throw new RuntimeException(ignored);
}
}
}
}
I am developing an Android application that produces results and I am saving this results in a CSV file. After that I want to close the app, open it again, get other results and write them at the end of the same existing CSV file. Right now every time it ovverrides the previous results.
This is my class to save the results in a CSV file:
public class SaveCSV {
private File file;
private RandomAccessFile randomAccessFile;
public SaveCSV(){
this.file = getPath("RisultatiTest.csv");
try {
this.randomAccessFile = new RandomAccessFile(file, "rwd");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public void salvaRisultati (int[] array) {
try {
file.createNewFile();
String s = "";
for (int i = 0; i < array.length; i++) {
s = s + array[i] + ",";
}
randomAccessFile.writeBytes(s);
randomAccessFile.writeBytes("\n");
} catch (IOException e) {
throw new RuntimeException("Unable to create File " + e);
}
}
public static File getPath(String fileName){
return new File(Environment.getExternalStorageDirectory(), fileName);
}
}
In reality its just making a copy of a text.txt file. I know how to use file chooser to choose the file but that is as far as my knowledge really goes.
I can do this:
public BasicFile()
{
JFileChooser choose = new JFileChooser(".");
int status = choose.showOpenDialog(null);
try
{
if (status != JFileChooser.APPROVE_OPTION) throw new IOException();
f = choose.getSelectedFile();
if (!f.exists()) throw new FileNotFoundException();
}
catch(FileNotFoundException e)
{
display(1, e.toString(), "File not found ....");
}
catch(IOException e)
{
display(1, e.toString(), "Approve option was not selected");
}
}
Path object is perfect for copying files,
Try this code to copy a file,
Path source = Paths.get("c:\\blabla.txt");
Path target = Paths.get("c:\\blabla2.txt");
try {
Files.copy(source, target);
} catch (IOException e1) {
e1.printStackTrace();
}
If you have to backup a whole folder, you can use this code
public class BackUpFolder {
public void copy(File sourceLocation, File targetLocation) throws IOException {
if (sourceLocation.isDirectory()) {
copyDirectory(sourceLocation, targetLocation);
} else {
copyFile(sourceLocation, targetLocation);
}
}
private void copyDirectory(File source, File target) throws IOException {
if (!target.exists()) {
target.mkdir();
}
for (String f : source.list()) {
copy(new File(source, f), new File(target, f));
}
}
private void copyFile(File source, File target) throws IOException {
try (
InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(target)) {
byte[] buf = new byte[1024];
int length;
while ((length = in.read(buf)) > 0) {
out.write(buf, 0, length);
}
}
}
public static void main(String[] args) {
try {
BackUpFolder backUpFolder = new BackUpFolder();
String location = "./src/edu/abc/locationFiles/daofile"; //File path you are getting from file chooser
String target = "./src"; //target place you want to patse
File locFile = new File(location);
File tarFile = new File(target);
backUpFolder.copyDirectory(locFile, tarFile);
} catch (IOException ex) {
Logger.getLogger(BackUpFolder.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Start by taking a look at Basic I/O, which explains the basics of Input/OutputStreams and Readers and Writers, which are used to read/write bytes of data from a source to a destination.
If you're using Java 7 or over, you should also take a look at Copying a File or Directory which is part of newer Files and Paths API, which you can find more information about at File I/O (Featuring NIO.2)
The code I have works for copying all direcotries and files but not sure on how to exclude a
particular directory under music and exclude a list of files
1) For example, I have Music folder and lots of subdirectories. Want to exclude spanish
subdirectory and copy everything under Music folder to destination
The second condition which I wanted to check is
2) Under Music folder I wanted to exclude all text files and copy
` private void copyFiles(File src, File tgt) throws IOException
{
if(src.isDirectory())
{
try{
if(!tgt.exists()) tgt.mkdirs();
String[] filePaths = src.list();
for(String filePath : filePaths)
{
File srcFile = new File(src, filePath);
File destFile = new File(tgt, filePath);
copyFiles(srcFile, destFile);
}
}
catch(Exception ie)
{
ie.printStackTrace();
}
}
else
{
try
{
bis = new BufferedInputStream(new FileInputStream(src));
bos = new BufferedOutputStream(new FileOutputStream(tgt));
long fileBytes = src.length();
long soFar = 0;
int Byte;
while((Byte = bis.read()) != -1)
{
bos.write(Byte);
}
bis.close();
bos.close();
}
catch(Exception excep)
{
excep.printStackTrace();
bos.flush();
bis.close();
bos.close();
}`
File#listFiles takes a FileFilter which can be used to determine if certain files should be included or not in the listing returne by File#listFiles...
This is okay if you know in advance what you to to include/exclude. If you want to make the process more dynamic, you could pass a list of FileFilters to the copy method and then use a special FileFilter to iterate over them...
private void copyFiles(File src, File tgt, FileFilter... filters) {
/*...*/
File[] filePaths = src.listFiles(new GroupedFileFiler(filters));
/*...*/
}
public class GroupedFileFilter implements FileFilter {
private FileFilter[] filters;
public GroupedFileFilter(FileFilter... filters) {
this.filters = filters;
}
#Override
public boolean accept(File pathname) {
boolean include = true;
if (filters != null && filters.length > 0) {
for (FileFilter filter : filters) {
include = filter.accept(pathname);
if (!include) {
break;
}
}
}
return include;
}
}
I want to copy a file from one location to another location in Java. What is the best way to do this?
Here is what I have so far:
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
public class TestArrayList {
public static void main(String[] args) {
File f = new File(
"D:\\CBSE_Demo\\Demo_original\\fscommand\\contentplayer\\config");
List<String>temp=new ArrayList<String>();
temp.add(0, "N33");
temp.add(1, "N1417");
temp.add(2, "N331");
File[] matchingFiles = null;
for(final String temp1: temp){
matchingFiles = f.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(temp1);
}
});
System.out.println("size>>--"+matchingFiles.length);
}
}
}
This does not copy the file, what is the best way to do this?
You can use this (or any variant):
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
Also, I'd recommend using File.separator or / instead of \\ to make it compliant across multiple OS, question/answer on this available here.
Since you're not sure how to temporarily store files, take a look at ArrayList:
List<File> files = new ArrayList();
files.add(foundFile);
To move a List of files into a single directory:
List<File> files = ...;
String path = "C:/destination/";
for(File file : files) {
Files.copy(file.toPath(),
(new File(path + file.getName())).toPath(),
StandardCopyOption.REPLACE_EXISTING);
}
Update:
see also
https://stackoverflow.com/a/67179064/1847899
Using Stream
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
Using Channel
private static void copyFileUsingChannel(File source, File dest) throws IOException {
FileChannel sourceChannel = null;
FileChannel destChannel = null;
try {
sourceChannel = new FileInputStream(source).getChannel();
destChannel = new FileOutputStream(dest).getChannel();
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}finally{
sourceChannel.close();
destChannel.close();
}
}
Using Apache Commons IO lib:
private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
Using Java SE 7 Files class:
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
Or try Googles Guava :
https://github.com/google/guava
docs:
https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/io/Files.html
Use the New Java File classes in Java >=7.
Create the below method and import the necessary libs.
public static void copyFile( File from, File to ) throws IOException {
Files.copy( from.toPath(), to.toPath() );
}
Use the created method as below within main:
File dirFrom = new File(fileFrom);
File dirTo = new File(fileTo);
try {
copyFile(dirFrom, dirTo);
} catch (IOException ex) {
Logger.getLogger(TestJava8.class.getName()).log(Level.SEVERE, null, ex);
}
NB:- fileFrom is the file that you want to copy to a new file fileTo in a different folder.
Credits - #Scott: Standard concise way to copy a file in Java?
public static void copyFile(File oldLocation, File newLocation) throws IOException {
if ( oldLocation.exists( )) {
BufferedInputStream reader = new BufferedInputStream( new FileInputStream(oldLocation) );
BufferedOutputStream writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
try {
byte[] buff = new byte[8192];
int numChars;
while ( (numChars = reader.read( buff, 0, buff.length ) ) != -1) {
writer.write( buff, 0, numChars );
}
} catch( IOException ex ) {
throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
} finally {
try {
if ( reader != null ){
writer.close();
reader.close();
}
} catch( IOException ex ){
Log.e(TAG, "Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
}
}
} else {
throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
}
}
Copy a file from one location to another location means,need to copy the whole content to another location.Files.copy(Path source, Path target, CopyOption... options) throws IOException this method expects source location which is original file location and target location which is a new folder location with destination same type file(as original).
Either Target location needs to exist in our system otherwise we need to create a folder location and then in that folder location we need to create a file with the same name as original filename.Then using copy function we can easily copy a file from one location to other.
public static void main(String[] args) throws IOException {
String destFolderPath = "D:/TestFile/abc";
String fileName = "pqr.xlsx";
String sourceFilePath= "D:/TestFile/xyz.xlsx";
File f = new File(destFolderPath);
if(f.mkdir()){
System.out.println("Directory created!!!!");
}
else {
System.out.println("Directory Exists!!!!");
}
f= new File(destFolderPath,fileName);
if(f.createNewFile()) {
System.out.println("File Created!!!!");
} else {
System.out.println("File exists!!!!");
}
Files.copy(Paths.get(sourceFilePath), Paths.get(destFolderPath, fileName),REPLACE_EXISTING);
System.out.println("Copy done!!!!!!!!!!!!!!");
}
You can do it with the Java 8 Streaming API, PrintWriter and the Files API
try (PrintWriter pw = new PrintWriter(new File("destination-path"), StandardCharsets.UTF_8)) {
Files.readAllLines(Path.of("src/test/resources/source-file.something"), StandardCharsets.UTF_8)
.forEach(pw::println);
}
If you want to modify the content on-the-fly while copying, check out this link for the extended example https://overflowed.dev/blog/copy-file-and-modify-with-java-streams/
I modified one of the answers to make it a bit more efficient.
public void copy(){
InputStream in = null;
try {
in = new FileInputStream(Files);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
OutputStream out = new FileOutputStream();
try {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
while (true) {
int len = 0;
try {
if (!((len = in.read(buf)) > 0)) break;
} catch (IOException e) {
e.printStackTrace();
}
try {
out.write(buf, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
}
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void moveFile() {
copy();
File dir = getFilesDir();
File file = new File(dir, "my_filename");
boolean deleted = file.delete();
}
Files.exists()
Files.createDirectory()
Files.copy()
Overwriting Existing Files:
Files.move()
Files.delete()
Files.walkFileTree()
enter link description here
You can use
FileUtils.copy(sourceFile, destinationFile);
https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html