There's something going on here that I don't understand. This code deletes all the files in the "stuff"directory:
public static void main(String[] args) throws Exception {
File dire = new File("C:\\Users\\spacitron\\Desktop\\Stuff");
for (File doc : dire.listFiles()) {
doc.delete();
}
}
However it won't work if I try to do something useful with it, such as only deleting duplicate files:
public static void main(String[] args) throws Exception {
File dire = new File("C:\\Users\\spacitron\\Desktop\\Stuff");
ArrayList<String> hashes = new ArrayList<>();
for (File doc : dire.listFiles()) {
String docHash = getHash(doc);
if (hashes.contains(docHash)) {
doc.delete();
} else {
hashes.add(docHash);
}
}
}
public static String getHash(File d) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA1");
FileInputStream inStream = new FileInputStream(d);
DigestInputStream dis = new DigestInputStream(inStream, md);
BufferedInputStream bis = new BufferedInputStream(dis);
while (true) {
int b = bis.read();
if (b == -1)
break;
}
} catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
BigInteger bi = new BigInteger(md.digest());
return bi.toString(16);
}
What gives?
You need to close your input streams in a finally block would be best, These will be accessing you files still preventing them from being deleted as they are in use
FileInputStream inStream = null;
DigestInputStream dis = null;
BufferedInputStream bis = null;
try {
md = MessageDigest.getInstance("SHA1");
inStream = new FileInputStream(d);
dis = new DigestInputStream(inStream, md);
bis = new BufferedInputStream(dis);
while (true) {
int b = bis.read();
if (b == -1)
break;
}
} catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
} finally {
try{
if(inStream!= null)
inStream.close();
if(dis != null)
dis.close();
if(bis != null)
bis.close()
} catch (Exception ex){
ex.printStackTrace()
}
}
Windows does not permit deleting files that are open, unless they are opened with a special flag that is unavailable when programming in Java. While this code would work on a Unix system, on Windows it won't.
Closing open files is a good idea in general because operating systems impose a limit on the number of files that an application can have open at any given time.
Related
public class JavaApplication {
public static void main(String[] args) throws IOException{
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
byte[]bytes= u.openStream().readAllBytes();
ObjectOutputStream output= new ObjectOutputStream(
new FileOutputStream("binary.dat"));
output.write(bytes);
output.close();
//Scanning the URL works just not the try and catch block
try{
ObjectInputStream input = new ObjectInputStream(new FileInputStream
("binary.dat"));
byte[]byte1= (byte[])input.readObject();
String any;
for(int i=0; i<byte1.length; i++){
any=String.valueOf(byte1[i]);
System.out.println(any);
}
input.close();
}
catch(Exception e){
System.out.println(e);}
}
}
I used a new byte array to read the object from file, use String.valueOf() to obtain the String value of the byte, then a for-loop to iterate the String. What am I doing wrong?
As the first commenter said, your main problem was not using writeObject. The only other problem is the way you turn the bytes into text. Your code will result in the 'ascii' code of the character being printed instead of the character itself. In fact you can simplify the output code as follows:
import java.io.*;
import java.net.*;
public class JavaApplication {
public static void main(String[] args) throws IOException {
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
byte[] bytes = u.openStream().readAllBytes();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("binary.dat"));
output.writeObject(bytes);
output.close();
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream("binary.dat"));
byte[] byte1 = (byte[]) input.readObject();
System.out.println(new String(byte1));
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
To solve your problem, I prefer you :
Add implementation of URLConnection for avoidance from Http Status 403 / Forbidden. Reference
use ByteArrayOutputStream to write the byte and save it into file using ObjectOutputStream
if you read with readObject() you must write with writeObject()
public class JavaApplication {
public static void main(String[] args) throws IOException, ClassNotFoundException {
URL u = new URL("https://www.javatpoint.com/java-string-valueof");
URLConnection uc = u.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = uc.getInputStream();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ((n = is.read(byteChunk)) > 0) {
baos.write(byteChunk, 0, n);
}
} catch (IOException e) {
System.err.printf("Failed while reading bytes from %s: %s", u.toExternalForm(), e.getMessage());
} finally {
if (is != null) {
is.close();
}
}
byte[] bytes = baos.toByteArray();
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("binary.dat"));
output.writeObject(bytes);
output.close();
//Scanning the URL works just not the try and catch block
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream("binary.dat"));
byte[] byte1 = (byte[]) input.readObject();
String any;
for (int i = 0; i < byte1.length; i++) {
any = String.valueOf(byte1[i]);
System.out.println(any);
}
input.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
I JCIFS using the API to perform the reading of a text file that is in my local network, the code below I can open the file;
Code:
String sharedFolder ="tratermik";
String path="smb://192.168.43.80/"+sharedFolder+"balanca.txt";
SmbFile smbFile = new SmbFile(path);
How do I copy this file to my internal memory ?
The code below solved my problem.
I hope I can help somebody else
private static final byte[] buffer = new byte[60416];
public void copiar(String serverPath, String localPath)
throws Exception {
SmbFile serverFile = new SmbFile("smb://192.168.43.80/tratermik/balanca.txt");
File localFile = new File("sdcard/sistemas/tratermic/balanca.txt);
InputStream in = new SmbFileInputStream(serverFile);
OutputStream out = new FileOutputStream(localFile);
try {
while (true) {
synchronized (buffer) {
int amountRead = in.read(buffer);
if (amountRead == -1) {
break;
}
out.write(buffer, 0, amountRead);
}
}
} catch (Exception e) {
throw e;
} finally {
if (in != null) { in.close();}
if (out != null) {out.close();}
}
}
}
I want to write simple rest api for file download.
I cant find docs about it as I understood I need to set mimetype='application/zip' for response, but not clear how to return stream.
http://sparkjava.com/
update:
resolved here example code:
public static void main(String[] args) {
//setPort(8080);
get("/hello", (request, responce) -> getFile(request,responce));
}
private static Object getFile(Request request, Response responce) {
File file = new File("MYFILE");
responce.raw().setContentType("application/octet-stream");
responce.raw().setHeader("Content-Disposition","attachment; filename="+file.getName()+".zip");
try {
try(ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(responce.raw().getOutputStream()));
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file)))
{
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer,0,len);
}
}
} catch (Exception e) {
halt(405,"server error");
}
return null;
What you need is similar to this thread. You only need to close the OutputStream and return the raw HTTPServletResponse:
try {
...
zipOutputStream.flush();
zipOutputStream.close();
} catch (Exception e) {
halt(405,"server error");
}
return responce.raw();
I am trying to write a class that can compress data. The below code fails (no exception is thrown, but the target .gz file is empty.)
Besides: I don't want to generate the .gz file directly like it is done in all examples. I only want to get the compressed
data, so that I can e.g. encrypt it before writting the data to a file.
If I write directly to a file everything works fine:
import java.io.*;
import java.util.zip.*;
import java.nio.charset.*;
public class Zipper
{
public static void main(String[] args)
{
byte[] dataToCompress = "This is the test data."
.getBytes(StandardCharsets.ISO_8859_1);
GZIPOutputStream zipStream = null;
FileOutputStream fileStream = null;
try
{
fileStream = new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz");
zipStream = new GZIPOutputStream(fileStream);
zipStream.write(dataToCompress);
fileStream.write(compressedData);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{ zipStream.close(); }
catch(Exception e){ }
try{ fileStream.close(); }
catch(Exception e){ }
}
}
}
But, if I want to 'bypass' it to the byte array stream it does not produce a single byte - compressedData is always empty.
import java.io.*;
import java.util.zip.*;
import java.nio.charset.*;
public class Zipper
{
public static void main(String[] args)
{
byte[] dataToCompress = "This is the test data."
.getBytes(StandardCharsets.ISO_8859_1);
byte[] compressedData = null;
GZIPOutputStream zipStream = null;
ByteArrayOutputStream byteStream = null;
FileOutputStream fileStream = null;
try
{
byteStream = new ByteArrayOutputStream(dataToCompress.length);
zipStream = new GZIPOutputStream(byteStream);
zipStream.write(dataToCompress);
compressedData = byteStream.toByteArray();
fileStream = new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz");
fileStream.write(compressedData);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{ zipStream.close(); }
catch(Exception e){ }
try{ byteStream.close(); }
catch(Exception e){ }
try{ fileStream.close(); }
catch(Exception e){ }
}
}
}
The problem is that you are not closing the GZIPOutputStream. Until you close it the output will be incomplete.
You just need to close it before reading the byte array. You need to reorder the finally blocks to achieve this.
import java.io.*;
import java.util.zip.*;
import java.nio.charset.*;
public class Zipper
{
public static void main(String[] args)
{
byte[] dataToCompress = "This is the test data."
.getBytes(StandardCharsets.ISO_8859_1);
try
{
ByteArrayOutputStream byteStream =
new ByteArrayOutputStream(dataToCompress.length);
try
{
GZIPOutputStream zipStream =
new GZIPOutputStream(byteStream);
try
{
zipStream.write(dataToCompress);
}
finally
{
zipStream.close();
}
}
finally
{
byteStream.close();
}
byte[] compressedData = byteStream.toByteArray();
FileOutputStream fileStream =
new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz");
try
{
fileStream.write(compressedData);
}
finally
{
try{ fileStream.close(); }
catch(Exception e){ /* We should probably delete the file now? */ }
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
I do not recommend inititalizing the stream variables to null, because it means your finally block can also throw a NullPointerException.
Also note that you can declare main to throw IOException (then you would not need the outermost try statement.)
There is little point in swallowing exceptions from zipStream.close();, because if it throws an exception you will not have a valid .gz file (so you should not proceed to write it.)
Also I would not swallow exceptions from byteStream.close(); but for a different reason - they should never be thrown (i.e. there is a bug in your JRE and you would want to know about that.)
I've improved JITHINRAJ's code - used try-with-resources:
private static byte[] gzipCompress(byte[] uncompressedData) {
byte[] result = new byte[]{};
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(uncompressedData.length);
GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) {
gzipOS.write(uncompressedData);
// You need to close it before using bos
gzipOS.close();
result = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
private static byte[] gzipUncompress(byte[] compressedData) {
byte[] result = new byte[]{};
try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedData);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPInputStream gzipIS = new GZIPInputStream(bis)) {
byte[] buffer = new byte[1024];
int len;
while ((len = gzipIS.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
result = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
If you are still looking an answer you can use the below code to get the compressed byte[] using deflater and decompress it using inflater.
public static void main(String[] args) {
//Some string for testing
String sr = new String("fsdfesfsfdddddddsfdsfssdfdsfdsfdsfdsfdsdfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghghghghggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfsdfesfsfdddddddsfdsfssdfdsfdsfdsfdsfdsdfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghghghghggggggggggggggggggggggggggggggggggggggggg");
byte[] data = sr.getBytes();
System.out.println("src size "+data.length);
try {
compress(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static byte[] compress(byte[] data) throws IOException {
Deflater deflater = new Deflater();
deflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
deflater.finish();
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
System.out.println("Original: " + data.length );
System.out.println("Compressed: " + output.length );
return output;
}
To compress
private static byte[] compress(byte[] uncompressedData) {
ByteArrayOutputStream bos = null;
GZIPOutputStream gzipOS = null;
try {
bos = new ByteArrayOutputStream(uncompressedData.length);
gzipOS = new GZIPOutputStream(bos);
gzipOS.write(uncompressedData);
gzipOS.close();
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
assert gzipOS != null;
gzipOS.close();
bos.close();
}
catch (Exception ignored) {
}
}
return new byte[]{};
}
To uncompress
private byte[] uncompress(byte[] compressedData) {
ByteArrayInputStream bis = null;
ByteArrayOutputStream bos = null;
GZIPInputStream gzipIS = null;
try {
bis = new ByteArrayInputStream(compressedData);
bos = new ByteArrayOutputStream();
gzipIS = new GZIPInputStream(bis);
byte[] buffer = new byte[1024];
int len;
while((len = gzipIS.read(buffer)) != -1){
bos.write(buffer, 0, len);
}
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
assert gzipIS != null;
gzipIS.close();
bos.close();
bis.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
return new byte[]{};
}
You can use the below function, it is tested and working fine.
In general, your code has serious problem of ignoring the exceptions! returning null or simply not printing anything in the catch block will make it very difficult to debug
You do not have to write the zip output to a file if you want to process it further (e.g. encrypt it), you can easily modify the code to write the output to in-memory stream
public static String zip(File inFile, File zipFile) throws IOException {
FileInputStream fis = new FileInputStream(inFile);
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fos);
try {
zout.putNextEntry(new ZipEntry(inFile.getName()));
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = fis.read(buffer)) > 0) {
zout.write(buffer, 0, len);
}
zout.closeEntry();
} catch (Exception ex) {
ex.printStackTrace();
return null;
} finally {
try{zout.close();}catch(Exception ex){ex.printStackTrace();}
try{fis.close();}catch(Exception ex){ex.printStackTrace();}
}
return zipFile.getAbsolutePath();
}
Most of the examples have wrong exception handling.
public static byte[] gzipBytes(byte[] payload) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(baos)) {
gzip.write(payload);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
// note: toByteArray should be called after try-with-resources, not inside
return baos.toByteArray();
}
public static byte[] gunzipBytes(byte[] gzPayload) {
ByteArrayInputStream bais = new ByteArrayInputStream(gzPayload);
try (GZIPInputStream gzip = new GZIPInputStream(bais)) {
// java 9+ required for this method
return gzip.readAllBytes();
} catch (IOException e) {
throw new UncheckedIOException("Error while unpacking gzip content", e);
}
}
Try with this code..
try {
String inputFileName = "test.txt"; //may use your file_Path
String zipFileName = "compressed.zip";
//Create input and output streams
FileInputStream inStream = new FileInputStream(inputFileName);
ZipOutputStream outStream = new ZipOutputStream(new FileOutputStream(zipFileName));
// Add a zip entry to the output stream
outStream.putNextEntry(new ZipEntry(inputFileName));
byte[] buffer = new byte[1024];
int bytesRead;
//Each chunk of data read from the input stream
//is written to the output stream
while ((bytesRead = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, bytesRead);
}
//Close zip entry and file streams
outStream.closeEntry();
outStream.close();
inStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
Also may be helpful this one..
http://www.java-samples.com/java/zip_files_in_a_folder_using_java.htm
I'd like to send a file contained in a ZIP archive unzipped to an external program for further decoding and to read the result back into Java.
ZipInputStream zis = new ZipInputStream(new FileInputStream(ZIPPATH));
Process decoder = new ProcessBuilder(DECODER).start();
???
BufferedReader br = new BufferedReader(new InputStreamReader(
decoder.getInputStream(),"us-ascii"));
for (String line = br.readLine(); line!=null; line = br.readLine()) {
...
}
What do I need to put into ??? to pipe the zis content to the decoder.getOutputStream()? I guess a dedicated thread is needed, as the decoder process might block when its output is not consumed.
Yes a thread is needed (or you wait/block until the copy is finished) for copying the InputStream to the OutputStream. Check the org.apache.commons.net.io.Util class for several helper methods to copy the data.
Ok, I got as far as following:
public class CopyStream extends Thread {
static final int BUFFERSIZE = 10 * 1024;
InputStream input; OutputStream output;
boolean closeInputOnExit, closeOutputOnExit, flushOutputOnWrite;
public IOException ex;
public CopyStream (InputStream input, boolean closeInputOnExit, OutputStream output, boolean closeOutputOnExit,
boolean flushOutputOnWrite) {
super("CopyStream");
this.input = input; this.closeInputOnExit = closeInputOnExit;
this.output = output; this.closeOutputOnExit = closeOutputOnExit;
this.flushOutputOnWrite = flushOutputOnWrite;
start();
}
public void run () {
try {
byte[] buffer = new byte[BUFFERSIZE];
for (int bytes = input.read(buffer); bytes>=0; bytes = input.read(buffer)) {
output.write(buffer,0,bytes);
if (flushOutputOnWrite) output.flush();
}
} catch (IOException ex) {
this.ex = ex;
} finally {
if (closeInputOnExit) {
try {
input.close();
} catch (IOException ex) {
if (this.ex==null) this.ex = ex;
}
}
if (closeOutputOnExit) {
try {
output.close();
} catch (IOException ex) {
if (this.ex==null) this.ex = ex;
}
}
}
}
}
Then the code would look as following:
ZipInputStream zis = new ZipInputStream(new FileInputStream(ZIPPATH));
for (ZipEntry ze = zis.getNextEntry(); ze!=null; ze = zis.getNextEntry()) {
Process decoder = new ProcessBuilder(EXTERNALPROCESSOR).start();
CopyStream cs1 = new CopyStream(is,false,decoder.getOutputStream(),true,true);
CopyStream cs2 = new CopyStream(decoder.getErrorStream(),true,System.err,false,true);
BufferedReader br = new BufferedReader(new InputStreamReader(decoder.getInputStream(),"us-ascii"));
ArrayList<String> lines = new ArrayList<String>();
for (String line = br.readLine(); line!=null; line = br.readLine()) {
lines.add(line);
}
if (decoder.exitValue()!=0) throw new IOException("Decoder exits with "+decoder.exitValue());
try {
cs1.join(100);
} catch (InterruptedException ex) {
throw new IOException(ex);
}
if (cs1.isAlive()) throw new IOException("cs1 not terminated");
if (cs1.ex!=null) throw cs1.ex;
try {
cs2.join(100);
} catch (InterruptedException ex) {
throw new IOException(ex);
}
if (cs2.isAlive()) throw new IOException("cs2 not terminated");
if (cs2.ex!=null) throw cs2.ex;
for (String line: lines) {
processline(line);
}
}
However, I find this a bit fragile. Isn't this a pattern for which some more robust implementation is around?