How to download a file from the internet using Java - java

Hi I am trying to write some code in my program so I can grab a file from the internet but it seems that is not working. Can someone give me some advice please ? Here is my code. In this case I try to download an mp3 file from the last.fm website, my code runs perfectly fine but when I open my downloads directory the file is not there. Any idea ?
public class download {
public static void main(String[] args) throws IOException {
String fileName = "Death Grips - Get Got.mp3";
URL link = new URL("http://www.last.fm/music/+free-music-downloads");
InputStream in = new BufferedInputStream(link.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1!=(n=in.read(buf)))
{
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(response);
fos.close();
System.out.println("Finished");
}
}

Every executing program has a current working directory. Often times, it is the directory where the executable lives (if it was launched in a "normal" way).
Since you didn't specify a path (in fileName), the file will be saved with that name in the current working directory.
If you want the file to be saved in your downloads directory, specify the full path. E.g.
String fileName = "C:\\Users\\YOUR_USERNAME\\Downloads\\Death Grips - Get Got.mp3";
Note how I've escaped the backslashes. Also note that there are methods for joining paths in Java. There is a way to get the current working directory in Java.

Related

How to write a Zip File with the "DFLT-X" Method

I am working on a Software which bundles and exports XML files as a zip. The compression method is "Deflate" (Code snipped included below).
These zip files are needed in another (older) Software, which is build up on "QT" (Code snipped also below).
The Problem is, that the zip files are not accepted in the second Software. If these zip files get rezipped manually, they work suddendly.
To find any differences in the generated zip and the Manual one, i plugged both into "powerArchiver" and saw they are exactly the same except for the "Method", which is "DFLT-X" on the workign zip and "DFLT-N" on the not working one (Note: working refers to the second Software import, both zip files can be extracted without Problems manually).
Any ideas how i can get the "DFLT-X" Method with Java utils libs?
I tried all settings and variants (.setLevel(), setMethod()) for "ZipOutputStream", "Deflater" and "DeflaterOutputStream" but i only got the "DFLT-N" Format.
The Explanation what these Formats are is not included in the powerArchiver Forums or else where. "DFLT-N" seems to refer to "Deflate, Normal" and the X variant for some higher compression, but not Deflate64.
Software 1, generating the zip:
final byte[] buffer = new byte[1024];
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
FileInputStream inputStream = null;
for (final String file : this.fileList) {
if (file.toString().contains(".xml")) {
final ZipEntry ze = new ZipEntry(File.separator + file);
zos.putNextEntry(ze);
try {
inputStream = new FileInputStream(sourceFolder + File.separator + file);
int len;
while ((len = inputStream.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
}
finally {
if (inputStream != null) {
inputStream.close();
}
}
}
}
zos.closeEntry();
}
catch (final IOException ex) {
ex.printStackTrace();
}
Software 2, reading the zip:
bool WfControlDataStorage::load(const QString& identifier, QByteArray& outZipFileContent) const
{
QFile dataFile(identifierToFilepath(identifier));
if(dataFile.open(QFile::ReadOnly)) {
outZipFileContent = dataFile.readAll();
dataFile.close();
return true;
}
return false;
}
#Holger Thank you for your Time, sounds like you did exactly what i did too.
Solution:
in my Project the zip Entry name had a leading "/" like "/someName". This was not visible in powerarchiver and also didnt hinder decompressing, but my recieving software had troubles resolving this name.
Repacking with powerarchiver removed that slash, so a bunch of undocumented behavior made my life hell.
In Terms of DFLT-X and DFLT-N, these are strange powerarchiver specific namings and i still cannot say how they determine the difference. But i can say, that deflate has no different "methods" nexto the simple levels from 0-9 and the "Deflate64" which is basically never used and obsolete. The DFLT-X naming is unrelated to both and imho completly irrelevant.

FileOutputStream, directory

this is my directory structure
Inside the server I have the following code for saving a file that gets sent from the client
fileName = reader.readLine();
DataInputStream dis = null;
try {
dis = new DataInputStream(csocket.getInputStream());
FileOutputStream fos = new FileOutputStream(fileName);
buffer = new byte[4096];
int fileSize = 15123;
int read = 0;
int totalRead = 0;
int remaining = fileSize;
while((read = dis.read(buffer, 0, Math.min(buffer.length, remaining))) > 0) {
totalRead += read;
remaining -= read;
fos.write(buffer, 0, read);
}
fos.close();
dis.close();
} catch (IOException e) {
}
break;
I'm wondering how I would go about saving the file within the xml folder? I've tried using getClass().getResource and such but nothing seems to work.
fileName is just a simple string containing the name of the file, not a path or anything.
I get the correct path using this code:
File targetDir = new File(getClass().getResource("xml").getPath());
File targetFile = new File(targetDir, fileName);
targetFile.createNewFile();
System.out.println(targetFile.getAbsolutePath());
dis = new DataInputStream(csocket.getInputStream());
FileOutputStream fos = new FileOutputStream(targetFile.getAbsolutePath(), false);
But it still won't save it there...
The best way is to receive explicitly the target path for storing files, either through a .properties file or a command-line argument. In this way, you make your program flexible to be installed and adapted in different environments.
But if you wish your program to assume the target directory automatically, the best option is to set a relative path before creating the FileOutputStream, as long as you start your program always from the same path:
File targetDir=new File("xml");
File targetFile=new File(targetDir, fileName);
FileOutputStream fos = new FileOutputStream(targetFile);
This will work assuming the program is started from server as current directory.
Update
Other minor suggestions about your program:
Never base the exit condition of the loop on a hard-coded file size, because it is not possible to know it a priori. Instead, check explicitly if the value returned by read is less than 0 => that means End Of File reached.
Consequently, do not bother to calculate the exact amount of data to get through a call to read. Just enter the buffer size, because you are setting a maximum data size.
Never let exceptions catched without a proper treatment: If you know how to make your program recover, enter a proper code into the catch block. Otherwise, you'd better not catch them: Declare them in the throws clause and let them be propagated to the caller.
Always create stream resources through the try-with-resources instruction, to ensure they got closed at the end:
try (FileOutputStream fos = new FileOutputStream(...))
{
// ... use fos...
}
Save unnecessary instructions: If you don't care about if the file already exists on the filesystem or not, don't call createNewFile. But if you care, check the returned value and bifurcate consequently.
I try to create file and it does created but not at ProjectName\src\com\company\xml but in ProjectName\out\production\ProjectName\com\company\xml
my code:
File targetDir = new File(this.getClass().getResource("xml").getPath());
// get the parent of the file
String parentPath = targetDir.getParent( );
String fileName="xml/name.txt";
//do something
File targetFile = new File(parentPath, fileName);
targetFile.createNewFile();
Just pay attention that after compilation you will try to save it into a jar file and it a complicated thing to do.
usually you need to save file into file outside from your jar(separate in the root) like this:

Downloading a file from a URL -- Nothing works

I run a Minecraft server for my friends, and a while back I very shoddily put together an installer which would download mods and install them properly to the correct location.
After about 6 hours of figuring out how to do what I was trying to do, I successfully got a working installer. I tried it again today, and found that it has stopped working. I've been trying to fix it, but to no avail. I cannot find any solution which actually gets the whole file to download, rather, an empty 4KB file is created. I tried on a different computer and the same thing happened. I'm running the latest version of Java.
This is the method I'm using to download the file. I have tried solutions using a ReadableByteChannel, but that yielded similar results, with a 1KB empty file.
public void download(String filename, URL url) {
try {
String fileName = filename;
URL link = url;
InputStream in = new BufferedInputStream(link.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
StringBuffer stringBuffer = new StringBuffer();
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(response);
fos.close();
System.out.println("Download complete!");
} catch (Exception e) {
System.out.println("Download failed, something went wrong!");
}
}
Is there something wrong with the method above? I can't really wrap my head around how downloading the file works, else I'd troubleshoot it myself. Any methods I can find on Google are going about it in pretty much the same way.
Printing stack trace:
at Install.download(Install.java:93)
at Install.downloadFile(Install.java:41)
at Install.main(Install.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
EDIT: Problem solved, used a different file hosting site to host the file. Now I just need to figure out how I can update the file without changing the URL.

java.io.FileNotFoundException: /u01/app/webapps/out/pj/Create.xlsx

I am trying to Compare last modified date of two excel files and replace the old file with new file.
In Scenario : When there is no file in the first place, so the code copies the file to that location and later reads it.
Issue is : It throws a FileNotFound exception when the excel file is not present on the server,even after writing the file to the
server(via code),but the file is not seen on the server. It works on
my machine(windows),but fails when deployed on server.
Again, it works like charm when the file is present on the server,while the old is being replaced by the new file.
Can you please help and explain on why its failing in the above scenario,and only on server ?
if(row.getValue("fileType").toString().equals("xlsx")&&checkindatefolder.after(localdate))
{
messagelist.add("we are going to get the replace file in the server");
InputStream inp=folder.getFile();
ZipInputStream izs = new ZipInputStream(inp);
ZipEntry e = null;
while ((e = izs.getNextEntry()) != null) {
System.out.println("e.isDirectory(): "+e.isDirectory());
if (!e.isDirectory()) {
filename=e.getName();
System.out.println("filename: "+filename);
FileOutputStream os=new FileOutputStream("path"+e.getName());
byte[] buffer = new byte[4096];
int read=0;
System.out.println("writing to file");
while ((read=izs.read(buffer))> 0) {
System.out.println("1111");
os.write(buffer,0,read);
}
System.out.println("writing to file complete");
inp.close();
os.flush();
os.close();
}
}
Do all parts of the path exist?
So in your example:
/u01/app/webapps/out/pj/Create.xlsx
Do all subdirectories exist?
/u01/app/webapps/out/pj
If not, than trying to write there might fail with a FileNotFoundException.
You should create the directories with Files.creatDirectories(Path) first.

How to copy files out of the currently running jar

I have a .jar that has two .dll files that it is dependent on. I would like to know if there is any way for me to copy these files from within the .jar to a users temp folder at runtime. here is the current code that I have (edited to just one .dll load to reduce question size):
public String tempDir = System.getProperty("java.io.tmpdir");
public String workingDir = dllInstall.class.getProtectionDomain().getCodeSource().getLocation().getPath();
public boolean installDLL() throws UnsupportedEncodingException {
try {
String decodedPath = URLDecoder.decode(workingDir, "UTF-8");
InputStream fileInStream = null;
OutputStream fileOutStream = null;
File fileIn = new File(decodedPath + "\\loadAtRuntime.dll");
File fileOut = new File(tempDir + "loadAtRuntime.dll");
fileInStream = new FileInputStream(fileIn);
fileOutStream = new FileOutputStream(fileOut);
byte[] bufferJNI = new byte[8192000013370000];
int lengthFileIn;
while ((lengthFileIn = fileInStream.read(bufferJNI)) > 0) {
fileOutStream.write(bufferJNI, 0, lengthFileIn);
}
//close all steams
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (UnsupportedEncodingException e) {
System.out.println(e);
return false;
}
My main problem is getting the .dll files out of the jar at runtime. Any way to retrieve the path from within the .jar would be helpful.
Thanks in advance.
Since your dlls are bundeled inside your jar file you could just try to acasses them as resources using ClassLoader#getResourceAsStream and write them as binary files any where you want on the hard drive.
Here is some sample code:
InputStream ddlStream = <SomeClassInsideTheSameJar>.class
.getClassLoader().getResourceAsStream("some/pack/age/somelib.dll");
try (FileOutputStream fos = new FileOutputStream("somelib.dll");){
byte[] buf = new byte[2048];
int r;
while(-1 != (r = ddlStream.read(buf))) {
fos.write(buf, 0, r);
}
}
The code above will extract the dll located in the package some.pack.age to the current working directory.
Use a class loader that is able to locate resources in this JAR file. Either you can use the class loader of a class as Peter Lawrey suggested, or you can also create a URLClassLoader with the URL to that JAR.
Once you have that class loader you can retrieve a byte input stream with ClassLoader.getResourceAsStream. On the other hand you just create a FileOutputStream for the file you want to create.
The last step then is to copy all bytes from the input stream to the output stream, as you already did in your code example.
Use myClass.getClassLoader().getResourceAsStream("loadAtRuntime.dll"); and you will be able to find and copy DLLs in the JAR. You should pick a class which will also be in the same JAR.

Categories

Resources