I can request the URL for the jar file or classes directory where Java loaded a class from:
Class clazz = ...
URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
but how to correctly convert this to a File (or Path) - especially with respect to some characters of the path escaped in URLs? I've tried this:
String fileName = URLDecoder.decode(url.getFile(), "UTF-8");
File jarFileOrClassesDir = new File(fileName);
but this causes problems if there is a + inside the path (the + is replaced with a space).
but this causes problems if there is a + inside the path (the + is replaced with a space).
This is standar behavior of URLDecoder. See more information at JavaDoc [1], plus (+) is mentioned there as well.
Solution using Paths
Using Paths#get(URI) [2] should preserve all "special" symbols and you can pass directly URI which can be retrieved directly from URL using URL#toURI() [3].
So in summary:
final var filePath = Paths.get(url.toURI()); // We can extract any information from Path e.g. fileName.
shoud work as expected.
[1] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URLDecoder.html
[2] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Paths.html#get(java.net.URI)
[3] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#toURI()
Related
I am making an HTTP Server in Java so that (on start) it finds all files in a directory (and it's sub-directories) and adds them to the server. But when getting the path of a file and trying to give it to HttpServer.createContext(), it throws a java.lang.IllegalArgumentException: Illegal value for path or protocol. (with the string argument, say "\folder/index.html"). To get this value, I used
file.getParent().substring(24) + "/" + file.getName()
I used substring because I had to exclude the folder the web server is in. The illegal character is the backslash. I have tried extending File to change separator and separatorChar, but that only created 2 new variables. While using String.replace() didn't seem to have any effect. Is there a different method than File.getParent or File.getPath that I can use, or is there a way to use String.replace that I am not seeing?
EDIT:
String.replace() seems to be the best answer... But I am not completely sure how to use it.
EDIT 2: For some reason the backslash isn't showing up, so I changed it.
You have to use the java System.getProperty.
Notice that, in this context, "file.separator" is a key which we are
using to get this property from current system executing the java VM.
Insteady of using a slash (/), you should choose a platform agnostic file separator, as an example it should be:
String separator = System.getProperty("file.separator");
System.out.println(separator);
// unix / , windows \
Have a look at Paths.get(...)
Try Paths.get(".") // current working directory.
Or tell it, on which path it should start:
Use System.getProperty("user.dir"), for current loged in user, home directory.
String pathStr = "/";
Path homeDir = Paths.get(System.getProperty("user.dir"))
Getting from the user directory into the data directory: homeDir.get("data")
Path dataPath = Paths.get(System.getProperty("user.dir"));
File dataFile = dataPath.toFile();
Now use operations on dataFile, to check what files and directories there are, on that location of the file system.
i'm using OutputStream to create a pdf file for download as follow:
byte[] infoFile = info.getBytes();
String infoName = info.getFileName();
String contentType = info.getContentType();
response.setContentType(contentType);
response.setHeader("Content-disposition", "attachment;filename=\"" + infoName + "\"");
response.setContentLength(infoFile.length);
// till now no problem, the file name is ok
OutputStream out = response.getOutputStream();
out.write(infoFile);
//here, as soon as the previous line is executed a file is generated with wrong characters
// ex. D:__Profiles__User__Downloads__infoFile.pdf
Here the file produced is something like "D:__Profiles__User__Downloads__infoFile.pdf"
while i expect the file "D:\Profiles\User\Downloads\infoFile.pdf"
What's wrong?
What's wrong?
Your expectation that the filename in a Content-disposition header should have path information.
From RFC 6266 section 4.3
Recipients MUST NOT be able to write into any location other than
one to which they are specifically entitled. To illustrate the
problem, consider the consequences of being able to overwrite
well-known system locations (such as "/etc/passwd"). One strategy
to achieve this is to never trust folder name information in the
filename parameter, for instance by stripping all but the last
path segment and only considering the actual filename (where 'path
segments' are the components of the field value delimited by the
path separator characters "" and "/").
And similarly in the Mozilla docs
The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done.
Basically you should only be specifying infoFile.pdf. It's up to the user which directory that file is saved in.
I have tried to read a file from controller class with this code
ReadFile readFile = new ReadFile();
String text = readFile.readFile("\resources\testing.txt");
renderRequest.setAttribute("text", text);
I have fetched it from view.jsp as
<%
String content = (String)request.getAttribute("text");
%>
But I am getting file not found exception. What is the way to get file content.
In a Java string, \ starts an escape sequence and "\r" and "\t" are escaped characters. For example "\t" is a string with the tab character. If you literally need \t in a string, you'll have to escape the backslash
doSomething("\\resources\\testing.txt");
or just eliminate the hassle: Java operates well when you use the forward slash as directory separator
doSomething("/resources/testing.txt");
Note that this refers to a file in the root directory of whatever drive the current path is on, it might be C:\resources\testing.txt or D:\resources\testing.txt - unless your ReadFile implementation manipulates the path somehow (which I leave up to your judgement). You can test this independent of Liferay, just in a command line application. The exception gets thrown way before your jsp gets displayed (I've changed the tags to flag the relevance)
This is pure Java, completely independent of Liferay.
The problem is with your relative path of resources file (testing.txt), that needs to be absolute. And to create absolute path, first you would require, portletContext which you can get from request, as following:
MVC Portlet:
PortletContext portletContext = request.getPortletSession().getPortletContext();
Where request is either renderRequest / actionRequest object. While in JSF, you can get request from externalContext, as following:
JSF Portlet:
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
PortletRequest request = (PortletRequest) externalContext.getRequest();
PortletContext portletContext = request.getPortletSession().getPortletContext();
Also, as suggested by Olaf Kock, if you use \, you would require to escape it, otherwise use /. I prefer to use File.separator, as it returns slash as per OS (I think!).
String relativeFilePath = File.separator + "resources" + File.separator + "testing.txt";
Now, you can get absolute path using portletContext as,
String absoluteFilePath = portletContext.getRealPath(relativeFilePath);
And then, rest of your code goes, as:
ReadFile readFile = new ReadFile();
String text = readFile.readFile(absoluteFilePath);
renderRequest.setAttribute("text", text);
Since you're getting a FileNotFoundException, Are you sure you're pointing to the proper file route? Have you tried with the absolute path? What SO are you using? Because maybe the file separators ("\") are the cause of your problem.
HIH.
Regards.
I have path to local directory:
String myPath = "C:\install";
I need to pass this path to method in third-party library. Third-party use path to directory in following ways:
File f = new File(s);
URL u = f.toURL();
and
new MyObject("file://" + myPath);
If it simply "C:\install", then I get exception while executing second pice of code (MyObject) - there is only 2 slashes instead 3. But if I add one slash to beginning of the string: "\C:\install", then second pice of code executes correctly, but File#toURL(); converts it to file:/C:/install - i.e. it ignores slash at the beginning..
I have get this exception. but this exception is not reproduced again. I want to get the cause of this
Exception Caught while Checking tag in XMLjava.net.URISyntaxException:
Illegal character in opaque part at index 2:
C:\Documents and Settings\All Users\.SF\config\sd.xml
stacktrace net.sf.saxon.trans.XPathException.
Why this exception occured. How to deal with so it will not reproduce.
A valid URI does not contain backslashes, and if it contains a : then the characters before the first : must be a "protocol".
Basically "C:\Documents and Settings\All Users\.SF\config\sd.xml" is a pathname, and not a valid URI.
If you want to turn a pathname into a "file:" URI, then do the following:
File f = new File("C:\Documents and Settings\All Users\.SF\config\sd.xml");
URI u = f.toURI();
This is the simplest, and most reliable and portable way to turn a pathname into a valid URI in Java. It should work on Windows, Mac, Linux and any other platform that supports Java. (Other solutions that involve using string bashing on a pathname are not portable.)
But you need to realize that "file:" URIs have a number of caveats, as described in the javadocs for the File.toURI() method. For example, a "file:" URI created on one machine usually denotes a different resource (or no resource at all) on another machine.
The root cause for this is file path contains the forward slashes instead of backward slashes in windows.
Try like this to resolve the problem:
"file:" + string.replace("\\", "/");
You must have the string like so:
String windowsPath = file:/C:/Users/sizu/myFile.txt;
URI uri = new URI(windowsPath);
File file = new File(uri);
Usually, people do something like this:
String windowsPath = file:C:/Users/sizu/myFile.txt;
URI uri = new URI(windowsPath);
File file = new File(uri);
or something like this:
String windowsPath = file:C:\Users\sizu\myFile.txt;
URI uri = new URI(windowsPath);
File file = new File(uri);
It needs a complete uri with type/protocol
e.g
file:/C:/Users/Sumit/Desktop/s%20folder/SAMPLETEXT.txt
File file = new File("C:/Users/Sumit/Desktop/s folder/SAMPLETEXT.txt");
file.toURI();//This will return the same string for you.
I will rather use direct string to avoid creating extra file object.
I had the same "opaque" error while passing a URI on the command line to a script. This was on windows. I had to use forward slashes, NOT backslashes. This resolved it for me.
it doesn't like spaces as well and it has to be / instead of \ or `\ or //
zipFilePath = "C:/test/v";