I have a .xlsx file (or any file) which I would like to gzip. I am able to gzip the file but now I have the problem of trying to do this in place. Meaning to replace the original file with the gzipped version of the file.
Here is my code:
public static void main(String[] args) throws IOException {
File file = new File("test.xlsx");
File gfile = new File(file.getAbsolutePath()+".gz");
if(!file.exists()) {
System.err.println("Input tax file did not exist!");
}
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(gfile);
GZIPOutputStream gos = new GZIPOutputStream(fos);
gzipReplace(fis, gos);
}
private static void gzipReplace(InputStream is, OutputStream os) {
int oneByte;
try {
while( (oneByte = is.read()) != -1 ) {
os.write(oneByte);
}
os.close();
is.close();
} catch (Exception e){
System.err.println(e.getStackTrace());
}
}
How can I do an in-place replacement of an uncompressed file with a gzipped one?
Just use File.delete() on the original file after successful compression and writing of the gzip file.
You must be very careful to not delete the original file until you are certain that the new compressed file was successfully written and closed. Otherwise you are setting yourself up to lose data.
Related
I am currently working a project and we have divided it in modules, in one of them, we have a file ( .exe ) extension. I decided to open it in binary format and read the contents of it, modify them. But, I am not to modify the changes and save it in the same file. When I am trying to do so, it says 0KB. It's working perfectly fine when using two files.
Here is the source code :
public static void main(String[] args) {
String strSourceFile="E:/e.exe";
String strDestinationFile="E:/f.exe";
try
{
FileInputStream fin = new FileInputStream(strSourceFile);
FileOutputStream fout = new FileOutputStream(strDestinationFile);
byte[] b = new byte[1];
int noOfBytes = 0;
System.out.println("Copying file using streams");
while( (noOfBytes = fin.read(b)) != -1 )
{
fout.write(b, 0, noOfBytes);
}
System.out.println("File copied!");
//close the streams
fin.close();
fout.close();
Use RandomAccessFile or You can also create a new file with your changes save it and delete the original one. Once original file is deleted then rename this new file to the original one.
You are trying to read and write the same file with the input and the output stream so the file is not getting copied while you try to do it with the same file. Instead, use a middle file as the buffer, as in the below code I have used the f.exe as the middle buffer, next I have copied the data from the buffer file again to the original file jar.exe, at last you need to delete the buffer file.
Here is the below code :
String strSourceFile = "C:/jar.exe";
String strDestinationFile = "C:/f.exe";
FileInputStream fin = new FileInputStream(strSourceFile);
FileOutputStream fout = new FileOutputStream(strDestinationFile);
byte[] b = new byte[1];
int noOfBytes = 0;
System.out.println("Copying file using streams");
while ((noOfBytes = fin.read(b)) != -1) {
fout.write(b, 0, noOfBytes);
}
fin.close();
fout.close();
String strDestinationFile1 = "C:/jar.exe";
FileInputStream fin1 = new FileInputStream(strDestinationFile);
FileOutputStream fout1 = new FileOutputStream(strDestinationFile1);
while ((noOfBytes = fin1.read(b)) != -1) {
fout1.write(b, 0, noOfBytes);
}
System.out.println("File copied!");
//close the streams
fin1.close();
fout1.close();
File file = new File("C:/f.exe");
file.delete();
I am trying to copy the content of one file to another using Java I/O Stream.
I have written below code for this, but it is copying only the last letter of the source file.
package io.file;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopyTester {
public void copyFile() {
FileInputStream fis = null;
try{
fis = new FileInputStream("resources/Source.txt");
System.out.println("Started copying");
int data = fis.read();
while (data != -1){
try (FileOutputStream fos = new FileOutputStream("resources/Destination.docx")){
fos.write(data);
fos.close();
}
catch (IOException io) {
System.err.println("Error o/p:"+io.getMessage());
}
System.out.print((char)data+" ");
data = fis.read();
}
fis.close();
System.out.println("End Copying");
}
catch(IOException ioe){
System.err.println("ERROR: "+ioe.getMessage());
}
}
public static void main(String[] args) {
new FileCopyTester().copyFile();
}
}
In Source file I have data something like
22
/
7
3.142857
So in destination I am getting only
7
Kindly help If I am missing something in this, like something that should not overwrite the data in destination file.
You overwrite your file each time with one byte.
Solution: open the output stream outside your while loop, and close it afterwards.
Opening the stream at every turn of the loop is pointless - the new data is overwriting the old content of the file. However - opening the stream with the "append mode" will make your code work:
FileOutputStream fos = new FileOutputStream("resources/Destination.docx", true);
The second, nicer solution is to open the stream before loop:
FileInputStream fis = new FileInputStream("resources/Source.txt");
FileOutputStream fos = new FileOutputStream("resources/Destination.docx");
int data = fis.read();
while (data != -1){
fos.write(data);
data = fis.read();
}
fos.close();
I am using the DeferredFileOutputStream to write files to disk. I have specified the size threshold to 10K, sometimes if the file size is less than the threshold, then files are not getting into physical location. I think its holding in-memory.
In this scenario do i need to explicitly write to disk?
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream(new File(
"atest.zip"));
DeferredFileOutputStream differedFileOutputStream = new DeferredFileOutputStream(1, new File(
"atest.zip"));
ZipOutputStream zos = new ZipOutputStream(differedFileOutputStream);
String file5Name = "folder/android.pdf";
String file1Name = "file1.txt";
String file2Name = "file2.txt";
String file3Name = "folder/file3.txt";
String file4Name = "folder/file4.txt";
addToZipFile(file1Name, zos);
addToZipFile(file2Name, zos);
addToZipFile(file3Name, zos);
addToZipFile(file4Name, zos);
zos.close();
differedFileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void addToZipFile(String fileName, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
From the documentation:
An output stream which will retain data in memory until a specified threshold is reached, and only then commit it to disk. If the stream is closed before the threshold is reached, the data will not be written to disk at all.
And then it explains the use case for this class:
This class originated in FileUpload processing. In this use case, you do not know in advance the size of the file being uploaded. If the file is small you want to store it in memory (for speed), but if the file is large you want to store it to file (to avoid memory issues).
So the answer is no, the file doesn't get written. It sounds that you shouldn't be using this at all if you are trying to write to disk in every case. You should just use FileOutputStream directly.
Thats right. The solution i found was, After i right all the files, check if the Threshold reached, if No, then write the file to OutputStream explicitly.
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream(new File(
"atest.zip"));
DeferredFileOutputStream differedFileOutputStream = new DeferredFileOutputStream(1, new File(
"atest.zip"));
ZipOutputStream zos = new ZipOutputStream(differedFileOutputStream);
String file5Name = "folder/android.pdf";
String file1Name = "file1.txt";
String file2Name = "file2.txt";
String file3Name = "folder/file3.txt";
String file4Name = "folder/file4.txt";
addToZipFile(file1Name, zos);
addToZipFile(file2Name, zos);
addToZipFile(file3Name, zos);
addToZipFile(file4Name, zos);
FileOutputStream fos = new FileOutputStream(new File(
"atest.zip"));
if(differedFileOutputStream.isInMemory()) {
differedFileOutputStream.writeTo(fos);
}
zos.close();
differedFileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm writing a java server and always read requests form the browser. For example, I have in browser http://localhost:8080/C:\Users\1\Desktop\tur.txt and read this request. Then saves a file path. Then I want to print the contents of the file to browser. For example, some text which is in tur.txt.
I'm doing it with a method in another class.
Here is a code of this class:
public class FileReader {
BufferedReader in;
File DataFile;
public void Reader(String directory, PrintStream out) throws IOException {
try {
File stockInputFile = new File(directory);
File StockOutputFile = new File(directory);
FileInputStream fis = new FileInputStream(stockInputFile);
FileOutputStream fos = new FileOutputStream(StockOutputFile);
int count;
if (new File(directory).isDirectory()) {
directory=directory.replace('\\', '/');
out.print("HTTP/1.0 301 Moved Permanently\r\n"+
"Location: /"+directory+"/\r\n\r\n");
out.close();
return;
}
// Open the file (may throw FileNotFoundException)
InputStream f=new FileInputStream(directory);
// Determine the MIME type and print HTTP header
String mimeType="text/plain";
if (directory.endsWith(".html") || directory.endsWith(".htm"))
mimeType="text/html";
else if (directory.endsWith(".jpg") || directory.endsWith(".jpeg"))
mimeType="image/jpeg";
else if (directory.endsWith(".gif"))
mimeType="image/gif";
else if (directory.endsWith(".txt"))
mimeType="text/txt";
else if (directory.endsWith(".class"))
mimeType="application/octet-stream";
out.print("HTTP/1.0 200 OK\r\n"+
"Content-type: "+mimeType+"\r\n\r\n");
System.out.println(mimeType);
// Send file contents to client, then close the connection
byte[] a=new byte[4096];
int n;
while ((n=f.read(a))>0)
out.write(a, 0, n);
// out.flush();
out.close();
}
catch (FileNotFoundException x) {
out.println("HTTP/1.0 404 Not Found\r\n"+
"Content-type: text/html\r\n\r\n"+
"<html><head></head><body>"+directory+" not found</body></html>\n");
out.close();
}
}
}
It takes a directory to find a file a file on disk and PrintStream (PrintStream out = new PrintStream(new BufferedOutputStream(serSock.getOutputStream()));) to print the content to browser. But, the problem is that when I read this file. The content of this file removes. That means all that text that I had in tur.txt deletes. And the file becomes emtpty intead of beeng printed to the browser.
Can anyone explain why? Thank you.
The problem was here:
FileInputStream fis = new FileInputStream(stockInputFile);
FileOutputStream fos = new FileOutputStream(StockOutputFile);
In FileOutputSteam. So when I deleted these 2 lines the program started to work correctly. I forgot that FileOutputStream clears all the data stored in the file.
I would like to thank #lamsomeone for his help.
I'm currently writing a function what would create a zip file, which will be used in other functionality. Below it is my function's code:
public void createZip(){
try{
String outfile = this.filename + ".zip";
//input file
FileInputStream input = new FileInputStream(this.filename);
//output file
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(outfile));
//name the file inside the zip file
System.out.println(this.filename);
zip.putNextEntry(new ZipEntry(this.filename));
byte[] buffer = new byte[this.BUFFER];
int len;
//copy the file to the zip
while((len= input.read(buffer)) > 0){
System.out.println(len);
zip.write(buffer, 0, len);
}
zip.closeEntry();
zip.flush();
input.close();
zip.close();
this.filename += ".zip";
}
catch(IOException e){
e.printStackTrace();
}
}
I have tried to debug, but I couldn't find the source of this problem. The function runs without any further problems, but the zip file produced it is an empty one.
You must close the entry using ZipOutputStream#closeEntry() prior to closing the output stream, or the entry is never confirmed to have been written entirely.
Also, the name of the ZipEntry cannot be the entire path; i.e, it should be dog.png instead of C:\Users\Admin\Documents\dog.png. This issue will pass by without an exception, and will cause the data from the file to be compressed directly into the zip, rather than into the zip as a compressed file.
final static byte[] EmptyZip={80,75,05,06,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00};
public static void createEmptyZip(String path){
try{
FileOutputStream fos=new FileOutputStream(new File(path));
fos.write(EmptyZip, 0, 22);
fos.flush();
fos.close();
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
well, just wondering why you pass a filename as a parameter if you dont use it within the code..
Since you are always using the this.filename. That makes me think that you are trying to name a zip file with a name you set into the objects state and since you are also using that same name in the ZipEntry its trying to add that same zipper file inside it.. since the ZipEntry must point to an existing file, thats why it comes up empty.
Hope it helps.
Try to flush the buffer by using zip.flush() before closing, although close should flush the buffer.
Also verify this.filename. You have a local variable with the same name. The local variable filename is never used. It's possible the zip file is being written to a different location than what you expect.
#phillipe try this please
public void createZip(String filename) {
try {
//input file
FileInputStream input = new FileInputStream(filename);
//output file
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(filename + ".zip"));
//name the file inside the zip file
zip.putNextEntry(new ZipEntry(filename));
byte[] buffer = new byte[1024];
int len;
//copy the file to the zip
while((len = input.read(buffer)) > 0) {
System.out.println();
zip.write(buffer, 0 , len);
}
zip.closeEntry();
zip.flush();
zip.close();
input.close();
filename += ".zip";
} catch(IOException e) {
e.printStackTrace();
}
}
those code create a zip file and that's work and for me too. :)
Simple solution. Make one manual directory in ZipEntry without File Separator.
zip.putNextEntry(new ZipEntry("LOG" + fileName));
instead of
zip.putNextEntry(new ZipEntry(fileName));
Here fileName = file.getAbsoluteFile();
This will first create LOG dir in zip file followed by fileNames with directory path. This avoids creating initial empty directory in zip file.