Get a file from a given classpath - java

public String getQuery(String nameFile, Package pathFile)
{
// How to get on InputStrem nameFile and pathFile
}
I was not able to make it through classloader
String path = getClass().getPackage().getName().replace('.', File.pathSeparatorChar);
String file = path + "file.txt";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
return in = null

The pathSeparatorChar is : on Unix and ; on Windows. It has nothing to do with the char used to load resources from the ClassLoader, which is /, on all platforms.
Moreover, you forgot a separator between the path and the file name. It should be
String path = getClass().getPackage().getName().replace('.', '/');
String file = path + "/file.txt";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
Or, much simpler, since Class has a method which can load resources from the same package as the class directly:
InputStream in = this.getClass().getResourceAsStream("file.txt");

Related

FileNotFoundException exception when reading from a HTML resource

I try to open and read an HTML file from within class path.
Please find the directory structure in screenshot below
Inside class SendEmail class I want to read that verification.html file.
Code
When using the code below, it is throwing me a java.io.FileNotFoundException exception here:
emailContent = readHTMLFile("../emailTemplate/EmailVerificationTemplate/verification.html");
The readHTMLFile method looks like this:
public String readHTMLFile(String path) throws IOException {
String emailContent = "";
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new FileReader(path));
while ((emailContent = bufferedReader.readLine()) != null) {
stringBuilder.append(emailContent);
}
return stringBuilder.toString();
}
However, when I use an absolute path everything is working fine.
I am very new to Java world.
Please help me to fix this 🙏🏻.
verification.html looks rather like a "class path resource" than a file...
(A file is very environment dependent (e.g. thinking of its path/location), whereas a "CPR" we package & supply with our application & can refer to it with a known&fixed (absolute or relative) (class path) address.
Nor maven nor gradle (by default) "includes" anything else from src/main/java than *.java files. So please move the according files (including structure/packages) to src/main/resources (or src/test/... accordingly).
When the resource is finally in classpath, since spring:3.2.2, we can do that:
String emailBody = org.springframework.util.StreamUtils.
copyToString(
new org.springframework.core.io.ClassPathResource(
"/full/package/of/emailTemplate/EmailVerificationTemplate/verification.html")
.getInputStream(),
/* you must know(!), better: */
Charset.forName("UTF-8")
);
(..also outside/before spring-boot-application.)
In spring context, the Resource (Classpath-, ServletContext-, File(!)-, URL-, ...) can also be "injected", like:
#Value("classpath:/full/package/...")Resource verificationEmailBody
..instead of calling the constructor.
See also:
Spring Core#Resources reference doc
Resource javadoc
How do I read / convert an InputStream into a String in Java?
How do I load a resource and use its contents as a string in Spring
When you need to refer to verification.html as a File, then please ensure:
It has a distinct (absolute (ok!) or relative (good luck!)) address (in all target environments)!
Files and resources in Java
Your file is located inside the classpath. This is a special location within your source-code (here in package utils.emailTemplate.EmailVerificationTemplate). So we call it a classpath resource or simply resource.
Classpath resources
Usually those resources are destined to be published with your code, although they are actually not code.
In the Maven standard directory layout you would put them inside the special src/main/resources folder, separated from code.
Locating and reading resources
Resources are located relative from classpath using the classpath: schema. Since they are part of the sources, package-tree you can also locate them relative to one of your classes.
From your SendEmail class, the given template has relative path ../. So you can instantiate it as Resource building the URL using this.getClass().getResource(Stirng relativePath) from within your SendEmail class:
class SendEmail {
private final String relativePath = "../emailTemplate/EmailVerificationTemplate/verification.html";
// build the URL for the resource relative from within your class
public URL getVerificaitonEmailTemplateUrl() {
URL templateResourceUrl = this.getClass().getResource(relativePath);
return templateResourceUrl;
}
// load the resource
public InputStream getVerificaitonEmailTemplateStream() {
InputStream is = this.getClass().getResourceAsStream(relativePath);
return is;
}
}
Load a resource as input-stream getResourceAsStream(String name)
using the relative path from inside your class.
Alternative using Spring's special-purpose extension ClassPathResource:
private final String relativePath = "../emailTemplate/EmailVerificationTemplate/verification.html";
public String loadContentAsFile() {
ClassPathResource resource = new ClassPathResource(relativePath);
File file resource.getFile();
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
public InputStream getContentAsStream() {
ClassPathResource resource = new ClassPathResource(relativePath);
InputStream is resource.getInputStream();
return is;
}
Attention: This reading from a file works only if your resource is inside the file system. Not if your resource is inside a JAR:
This implementation returns a File reference for the underlying class path resource, provided that it refers to a file in the file system.
A safer and more robust way to read from the ClassPathResource is resource.getInputStream().
From InputStream to String
To fix your method, you could simply exchange the File related parts to InputStream:
public String readHTML(InputStream is) throws IOException {
String emailContent = "";
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
while ((emailContent = bufferedReader.readLine()) != null) {
stringBuilder.append(emailContent);
}
return stringBuilder.toString();
}
Or even simpler (see Baeldung's tutorial linked below):
String text = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8)) // choose the encoding to fit
.lines()
.collect(Collectors.joining("\n"));
Then re-use it to read from any stream (e.g. a File, a Resource, ClassPathResource, even a URL). For example:
public String loadTemplate(String relativeResourcePath) throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream(relativeResourcePath)
String text = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
return text;
}
See also
Baeldung: Access a File from the Classpath using SpringBaeldung
Baeldung: Java InputStream to String

Upload an Image using springboot in linux

I try to upload an image using spring-boot. The app should be capable for Linux and windows. The below codes are working only in windows, not in Linux. I tried in different ways. getDefaultFolderPath() is creating folder in both OS if not exists. But Files.write(path, bytes); is working only in windows.
String imageWindowsPath = "C:\\myapp\\";
String imageLinuxPath = "user.home";
private String uploadImage(MultipartFile file, HttpServletRequest request) {
String fileName = "blur.png";
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
Path path = Paths.get(getDefaultFolderPath() + fileName);
Files.write(path, bytes);
}
//few other codes
retrun "";
}
//Creating folder if not exists... This is working for both OS
public String getDefaultFolderPath() {
String path = "";
try {
String os = System.getProperty("os.name");
if (os.toUpperCase().indexOf("WINDOWS") != -1) {
File file = new File(imageWindowsPath+"slider");
if (!file.exists())
file.mkdirs();
path = imageWindowsPath+"/slider/";
}
else if (os.toUpperCase().indexOf("LINUX") != -1) {
String userHome = System.getProperty(imageLinuxPath);
String appName = "slider";
Path linuxpath = Paths.get(userHome, appName);
Files.createDirectories(linuxpath);
path = imageLinuxPath+"/slider/";
}
} catch (Exception e) {
e.printStackTrace();
}
//few codes
return path;
}
Please suggest me a solution if anyone knows. Thanks in advance.
String imageLinuxPath = "user.home";
String userHome = System.getProperty(imageLinuxPath);
String appName = "slider";
Path linuxpath = Paths.get(userHome, appName);
Files.createDirectories(linuxpath);
creates a directory based on the environment variable "user.home"
path = imageLinuxPath+"slider/";
return path;
returns "user.homeslider/"
Since the content of the environment variable user.home is probably not "user.home", the path will not be the directory that was created.
This means that you are trying to write to a directory that does not exist.
I would like to add that the difference between Windows and Linux is entirely your own creation. Java can treat them exactly the same way if you have a Windows property with the home path.

How to get absolute directory path from relative path + classloader

I have a class whose constructor receives a relative resources path (language properties files) and the corresponding classloader (the path is relative to the package of the classLoader):
public Language(String relDir, ClassLoader classLoader) {
...
}
Whithin that class I have a method that loads all found resource files (properties files such as MyFile_en_GB.properties), and it doesn't know whow many language resources there will be beforehand. It uses languagesDir as an absolute path for finding the resources.
private void loadLanguages() {
DirectoryStream.Filter<Path> filter = (path) -> {
return Files.isRegularFile(path) & path.getFileName()toString().startsWith("MyFile");
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(languagesDir, filter)) {
for (Path entry : stream) {
String fileName = entry.getFilename().toString();
...
loadPropertiesFile(filename)
}
} catch (..) {}
}
There, languagesDir works with an absolute path. However, when I tried:
String dir = classLoader.getResource(relDir).toString();
it throws an exception. I guess it is because it expects a file and not a directory
How can I get the absolute path of the resources? Should I try another aproach and work only with relative paths (how to do this)?
edit: About the exception:
classLoader.getResource(relDir) gives a null URL
try to use resourceFile.getName() after change URL to file.
URL resourceURL = classLoader.getResource(..);
File resourceFile = new File(new URL(resourceURL).toURI());
String fullPath = resourceFile.getName();
it throws an exception. I guess it is because it expects a file and
not a directory
If that is the case you can feed files instead directory. To get the absolute path you try as below
String dirPath = "C:\\Softwares";
File dir = new File( dirPath );
for ( String fileName : dir.list() ) {
File file = new File( dirPath + "\\" + fileName );
if ( file.isFile() ) {
// System.out.println( file.getAbsolutePath() );
String dir = classLoader.getResource( file.getAbsolutePath() ).toString();
}
}

merging two strings to shape a file path

assuming that we have a folder with path:
path="C:\\Users\\me\\Desktop\\here"
also, consider a File[] named readFrom has different files. as an example, consider following path which refering to a file:
C:\\Users\\me\\Desktop\\files\\1\\sample.txt"
my question is, how can i have a string with following value:
String writeHere= "C:\\Users\\me\\Desktop\\here\\files\\1\\sample.txt"
EDIT
I should have mentioned that this path is unknown, we need first to read a file and get its path then write it into another folder, so for the path of writing I need writeHere as input. in conclusion , the answer should contains the way to get the path from the file too.
String s1="C:\\Users\\me\\Desktop\\here";
String s2="C:\\Users\\me\\Desktop\\files\\1\\sample.txt";
String s3=s2.substring(s2.indexOf("\\files"));
System.out.println(s1+s3);
OUTPUT
C:\Users\me\Desktop\here\files\1\sample.txt
To get Absolute Path of file
File f=new File("C:\\Users\\me\\Desktop\\files\\1\\sample.txt");
System.out.println(f.getAbsolutePath());
Split the into arrays and merge the path with split-ted string
String path="C:\\Users\\me\\Desktop\\here";
String [] splt = yourPath.split("\\");
finalPath = path + "\\" + splt[3] + "\\" + splt[4] + "\\" + splt[5];
yourPath is the path refering to a file
Changing the folder's path
File afile =new File("C:\\Users\\me\\Desktop\\files\\1\\sample.txt");
afile.renameTo(new File(finalPath))
If you just need the String and do not need to read the file, use string concatenation with is just str1 + str2. If you need the File object create a base File object on the initial path and then two new File objects from that:
File path = new File("C:\\Users\\me\\Desktop\\here");
String[] files = { "files\\1\\sample.txt", "files\\3\\this.avi" };
for (filename in files) {
File f = new File(path, filename);
...
}
Oh, I think I see better what you want to do. You want to "reparent" the files:
// Note:
// newParent I assume would be a parameter, not hardcoded
// If so, there is no hardcoding of the platform specific path delimiter
// the value, start, is also assumed to be a parameter
File newParent = new File("C:\\Users\\me\\Desktop\\here");
File[] readFrom = ...;
for (File f in readFrom) {
String[] parts = f.list();
String[] needed = Arrays.copyOfRange(parts, start, parts.length);
File newFile = new File(newParent);
for (String part in needed) {
newFile = new File(newFile, part);
}
...
}
I think you could do something like:
String name = "Rafael";
String lastname = " Nunes";
String fullname = name + lastname;
Here you can see the string concatenation working, and you can often visit the Java documentation.

Where to put a file to read from a class under a package in java?

I have a properties file contains the file name only say file=fileName.dat. I've put the properties file under the class path and could read the file name(file.dat) properly from it in the mainClass. After reading the file name I passed the file name(just name not the path) to another class under a package say pack.myClass to read that file. But the problem is pack.myClass could not get the file path properly. I've put the file fileName.dat both inside and outside the packagepack but couldn't make it work.
Can anybody suggest me that where to put the file fileName.dat so I can read it properly and the whole application would be portable too.
Thanks!
The code I'm using to read the config file and getting the file name:
Properties prop = new Properties();
InputStream in = mainClass.class.getResourceAsStream("config.properties");
prop.load(in);
in.close();
myClass mc = new myClass();
mc.readTheFile(prop.getProperty("file"));
/*until this code is working good*/
Then in myClass which is under package named pack I am doing:
public void readTheFile(String filename) throws IOException {
FileReader fileReader = new FileReader(filename); /*this couldn't get the file whether i'm putting the file inside or outside the package folder */
/*after reading the file I've to do the BufferReader for further operation*/
BufferedReader bufferedReader = new BufferedReader(fileReader);
I assume that you are trying to read properties file using getResource method of class. If you put properties file on root of the classpath you should prefix file name with '/' to indicate root of classpath, for example getResource("/file.dat"). If properties file is under the same folder with the class you on which you invoke getResource method, than you should not use '/' prefix.
When you use a relative file name such as fileName.dat, you're asking for a file with this name in the current directory. The current directory has nothing to do with packages. It's the directory from which the JVM is started.
So if you're in the directory c:\foo\bar when you launch your application (using java -cp ... pack.MyClass), it will look for the file c:\foo\bar\fileName.dat.
Try..
myClass mc = new myClass();
InputStream in = mc.getClass().getResourceAsStream("/pack/config.properties");
..or simply
InputStream in = mc.getClass().getResourceAsStream("config.properties");
..for the last line if the main is in myClass The class loader available in the main() will often be the bootstrap class-loader, as opposed to the class-loader intended for application resources.
Class.getResource will look in your package directory for a file of the specified name.
JavaDocs here
Or getResourceAsStream is sometimes more convenient as you probably want to read the contents of the resource.
Most of the time it would be best to look for the "fileName.dat" somewhere in the "user.home" folder, which is a system property. First create a File path from the "user.home" and then try to find the file there. This is a bit of a guess as you don't provide the exact user of the application, but this would be the most common place.
You are currently reading from the current folder which is determined by
String currentDir = new File(".").getAbsolutePath();
or
System.getProperty("user.dir")
To read a file, even from within a jar archive:
readTheFile(String package, String filename) throws MalformedURLException, IOException
{
String filepath = package+"/"+filename;
// like "pack/fileName.dat" or "fileName.dat"
String s = (new SourceBase()).getSourceBase() + filepath;
URL url = new URL(s);
InputStream ins = url.openStream();
BufferedReader rdr = new BufferedReader(new InputStreamReader(ins, "utf8"));
do {
s = rdr.readLine();
if(s!= null) System.out.println(s);
}
while(s!=null);
rdr.close();
}
with
class SourceBase
{
public String getSourceBase()
{
String cn = this.getClass().getName().replace('.', '/') + ".class";
// like "packagex/SourceBase.class"
String s = this.getClass().getResource('/' + cn).toExternalForm();
// like "file:/javadir/Projects/projectX/build/classes/packagex/SourceBase.class"
// or "jar:file:/opt/java/PROJECTS/testProject/dist/
// testProject.jar!/px/SourceBase.class"
return s.substring(0, s.lastIndexOf(cn));
// like "file:/javadir/Projects/projectX/build/classes/"
// or "jar:file:/opt/java/PROJECTS/testProject/dist/testProject.jar!/"
}
}

Categories