So I'm trying to create a program in Unix that will take in a directory as a parameter and then recursively go through, open all of the folders, look through all of the files, and then delete all of the class files. I thought I was taking the correct steps as I was given code for a similar program and told to use it as a basis, but upon testing my program and I discover that nothing happens.
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
public class ClassFileDeleter {
public static void main(String[] args) throws ParseException {
String dirName = args[0];
deleteFile(dirName);
}
private static void deleteFile(String dirName) {
Path path = Paths.get(dirName);
File dir = path.toFile();
if(dir.exists()) {
File[] files = dir.listFiles();
if(dir.isDirectory()) {
for(File f:files) {
if(!f.isDirectory())
if(f.toString().endsWith(".class"))
System.out.println("yes");
else deleteFile(dirName + "/" + f.getName());
}}}
}}
I am at a loss at what I should do. I haven't attempted to delete anything yet because I don't want to delete anything that isn't a class file so I am using some dummy code that should print 'yes' once the program finds a class file. However when I run my code, absolutely nothing happens. I believe that there is either an issue with the way I am searching for class files (We are supposed to use endsWith) or with the way I am attempting to use recursion to look through all of the files in the specified directory. If I could have some assistance, that would be great.
I would start with a isFile check (and then test the extension of a file and log it if it matches), then you could recursively descend any directories. Something like,
private static void deleteFile(String dirName) {
File dir = new File(dirName);
if (dir.isFile()) {
if (dir.getName().endsWith(".class")) {
try {
System.out.println("Delete: " + dir.getCanonicalPath());
// dir.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File f : files) {
try {
deleteFile(f.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
It strikes me that the code that you have to recurse through the directory, is creating a file object not a directory.
A quick google gave me this from the Oracle java tutorial (http://docs.oracle.com/javase/tutorial/essential/io/dirs.html#listdir).
Listing a Directory's Contents
You can list all the contents of a directory by using the newDirectoryStream(Path) method. This method returns an object that implements the DirectoryStream interface. The class that implements the DirectoryStream interface also implements Iterable, so you can iterate through the directory stream, reading all of the objects. This approach scales well to very large directories.
Remember: The returned DirectoryStream is a stream. If you are not using a try-with-resources statement, don't forget to close the stream in the finally block. The try-with-resources statement takes care of this for you.
The following code snippet shows how to print the contents of a directory:
Path dir = ...;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file: stream) {
System.out.println(file.getFileName());
}
} catch (IOException | DirectoryIteratorException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can only be thrown by newDirectoryStream.
System.err.println(x);
}
The Path objects returned by the iterator are the names of the entries resolved against the directory. So, if you are listing the contents of the /tmp directory, the entries are returned with the form /tmp/a, /tmp/b, and so on.
This method returns the entire contents of a directory: files, links, subdirectories, and hidden files. If you want to be more selective about the contents that are retrieved, you can use one of the other newDirectoryStream methods, as described later in this page.
Note that if there is an exception during directory iteration then DirectoryIteratorException is thrown with the IOException as the cause. Iterator methods cannot throw exception exceptions.
So I'd take a look there and see what you can work out.
Related
I am trying to read a text file which is set in CLASSPATH system variable. Not a user variable.
I am trying to get input stream to the file as below:
Place the directory of file (D:\myDir) in CLASSPATH and try below:
InputStream in = this.getClass().getClassLoader().getResourceAsStream("SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("/SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("//SomeTextFile.txt");
Place full path of file (D:\myDir\SomeTextFile.txt) in CLASSPATH and try the same above 3 lines of code.
But unfortunately NONE of them are working and I am always getting null into my InputStream in.
With the directory on the classpath, from a class loaded by the same classloader, you should be able to use either of:
// From ClassLoader, all paths are "absolute" already - there's no context
// from which they could be relative. Therefore you don't need a leading slash.
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("SomeTextFile.txt");
// From Class, the path is relative to the package of the class unless
// you include a leading slash, so if you don't want to use the current
// package, include a slash like this:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
If those aren't working, that suggests something else is wrong.
So for example, take this code:
package dummy;
import java.io.*;
public class Test
{
public static void main(String[] args)
{
InputStream stream = Test.class.getResourceAsStream("/SomeTextFile.txt");
System.out.println(stream != null);
stream = Test.class.getClassLoader().getResourceAsStream("SomeTextFile.txt");
System.out.println(stream != null);
}
}
And this directory structure:
code
dummy
Test.class
txt
SomeTextFile.txt
And then (using the Unix path separator as I'm on a Linux box):
java -classpath code:txt dummy.Test
Results:
true
true
When using the Spring Framework (either as a collection of utilities or container - you do not need to use the latter functionality) you can easily use the Resource abstraction.
Resource resource = new ClassPathResource("com/example/Foo.class");
Through the Resource interface you can access the resource as InputStream, URL, URI or File. Changing the resource type to e.g. a file system resource is a simple matter of changing the instance.
This is how I read all lines of a text file on my classpath, using Java 7 NIO:
...
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
...
Files.readAllLines(
Paths.get(this.getClass().getResource("res.txt").toURI()), Charset.defaultCharset());
NB this is an example of how it can be done. You'll have to make improvements as necessary. This example will only work if the file is actually present on your classpath, otherwise a NullPointerException will be thrown when getResource() returns null and .toURI() is invoked on it.
Also, since Java 7, one convenient way of specifying character sets is to use the constants defined in java.nio.charset.StandardCharsets
(these are, according to their javadocs, "guaranteed to be available on every implementation of the Java platform.").
Hence, if you know the encoding of the file to be UTF-8, then specify explicitly the charset StandardCharsets.UTF_8
Please try
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
Your tries didn't work because only the class loader for your classes is able to load from the classpath. You used the class loader for the java system itself.
To actually read the contents of the file, I like using Commons IO + Spring Core. Assuming Java 8:
try (InputStream stream = new ClassPathResource("package/resource").getInputStream()) {
IOUtils.toString(stream);
}
Alternatively:
InputStream stream = null;
try {
stream = new ClassPathResource("/log4j.xml").getInputStream();
IOUtils.toString(stream);
} finally {
IOUtils.closeQuietly(stream);
}
To get the class absolute path try this:
String url = this.getClass().getResource("").getPath();
Somehow the best answer doesn't work for me. I need to use a slightly different code instead.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("SomeTextFile.txt");
I hope this help those who encounters the same issue.
If you use Guava:
import com.google.common.io.Resources;
we can get URL from CLASSPATH:
URL resource = Resources.getResource("test.txt");
String file = resource.getFile(); // get file path
or InputStream:
InputStream is = Resources.getResource("test.txt").openStream();
Ways to convert an InputStream to a String
To read the contents of a file into a String from the classpath, you can use this:
private String resourceToString(String filePath) throws IOException, URISyntaxException
{
try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath))
{
return IOUtils.toString(inputStream);
}
}
Note:
IOUtils is part of Commons IO.
Call it like this:
String fileContents = resourceToString("ImOnTheClasspath.txt");
You say "I am trying to read a text file which is set in CLASSPATH system variable." My guess this is on Windows and you are using this ugly dialog to edit the "System Variables".
Now you run your Java program in the console. And that doesn't work: The console gets a copy of the values of the system variables once when it is started. This means any change in the dialog afterwards doesn't have any effect.
There are these solutions:
Start a new console after every change
Use set CLASSPATH=... in the console to set the copy of the variable in the console and when your code works, paste the last value into the variable dialog.
Put the call to Java into .BAT file and double click it. This will create a new console every time (thus copying the current value of the system variable).
BEWARE: If you also have a User variable CLASSPATH then it will shadow your system variable. That is why it is usually better to put the call to your Java program into a .BAT file and set the classpath in there (using set CLASSPATH=) rather than relying on a global system or user variable.
This also makes sure that you can have more than one Java program working on your computer because they are bound to have different classpaths.
My answer is not exactly what is asked in the question. Rather I am giving a solution exactly how easily we can read a file into out java application from our project class path.
For example suppose a config file name example.xml is located in a path like below:-
com.myproject.config.dev
and our java executable class file is in the below path:-
com.myproject.server.main
now just check in both the above path which is the nearest common directory/folder from where you can access both dev and main directory/folder (com.myproject.server.main - where our application’s java executable class is existed) – We can see that it is myproject folder/directory which is the nearest common directory/folder from where we can access our example.xml file. Therefore from a java executable class resides in folder/directory main we have to go back two steps like ../../ to access myproject. Now following this, see how we can read the file:-
package com.myproject.server.main;
class Example {
File xmlFile;
public Example(){
String filePath = this.getClass().getResource("../../config/dev/example.xml").getPath();
this.xmlFile = new File(filePath);
}
public File getXMLFile() {
return this.xmlFile;
}
public static void main(String args[]){
Example ex = new Example();
File xmlFile = ex.getXMLFile();
}
}
If you compile your project in jar file:
you can put your file in resources/files/your_file.text or pdf;
and use this code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
public class readFileService(){
private static final Logger LOGGER = LoggerFactory.getLogger(readFileService.class);
public byte[] getFile(){
String filePath="/files/your_file";
InputStream inputStreamFile;
byte[] bytes;
try{
inputStreamFile = this.getClass().getResourceAsStream(filePath);
bytes = new byte[inputStreamFile.available()];
inputStreamFile.read(bytes);
} catch(NullPointerException | IOException e) {
LOGGER.error("Erreur read file "+filePath+" error message :" +e.getMessage());
return null;
}
return bytes;
}
}
I am using webshpere application server and my Web Module is build on Spring MVC. The Test.properties were located in the resources folder, i tried to load this files using the following:
this.getClass().getClassLoader().getResourceAsStream("Test.properties");
this.getClass().getResourceAsStream("/Test.properties");
None of the above code loaded the file.
But with the help of below code the property file was loaded successfully:
Thread.currentThread().getContextClassLoader().getResourceAsStream("Test.properties");
Thanks to the user "user1695166".
Use org.apache.commons.io.FileUtils.readFileToString(new File("src/test/resources/sample-data/fileName.txt"));
Don't use getClassLoader() method and use the "/" before the file name. "/" is very important
this.getClass().getResourceAsStream("/SomeTextFile.txt");
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile
{
/**
* * feel free to make any modification I have have been here so I feel you
* * * #param args * #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// thread pool of 10
File dir = new File(".");
// read file from same directory as source //
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
// if you wanna read file name with txt files
if (file.getName().contains("txt")) {
System.out.println(file.getName());
}
// if you want to open text file and read each line then
if (file.getName().contains("txt")) {
try {
// FileReader reads text files in the default encoding.
FileReader fileReader = new FileReader(
file.getAbsolutePath());
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(
fileReader);
String line;
// get file details and get info you need.
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
// here you can say...
// System.out.println(line.substring(0, 10)); this
// prints from 0 to 10 indext
}
} catch (FileNotFoundException ex) {
System.out.println("Unable to open file '"
+ file.getName() + "'");
} catch (IOException ex) {
System.out.println("Error reading file '"
+ file.getName() + "'");
// Or we could just do this:
ex.printStackTrace();
}
}
}
}
}
}
you have to put your 'system variable' on the java classpath.
I am trying to make a program that extracts multiple MP4 files from there individual folders and places them in a folder that is already created (code has been changed slightly so that it doesn't mess up any more of the MP4s, rather dummy text files).
I have managed to get so far as to list all folders/files in the specified folder however am having trouble moving them to a directory.
static File dir = new File("G:\\New Folder");
static Path source;
static Path target = Paths.get("G:\\gohere");
static void showFiles(File files[]) {
for (File file : files) { // Loops through each file in the specified directory in "dir" variable.
if (file.isDirectory()) { // If the file is a directory.
File[] subDir = file.listFiles(); // Store each file in a File list.
for (File subFiles : subDir) { // Loops through the files in the sub-directory.
if (subFiles.getName().endsWith(".mp4")) { // if the file is of type MP4
source = subFiles.toPath(); // Set source to be the abs path to the file.
System.out.println(source);
try {
Files.move(source, target);
System.out.println("File Moved");
} catch (IOException e) {
e.getMessage();
}
}
}
} else {
source = file.toPath(); // abs path to file
try {
Files.move(source, target);
System.out.println("File moved - " + file.getName());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
showFiles(dir.listFiles());
}
The problem is when I go to move the file from the source folder to the target, it removes or converts the target.
Files.move isn't like the command line. You're programming. You have to spell things out. You're literally asking Files.move to make it so that target (here, G:\GoHere) will henceforth be the location for the file you are moving. If you intended: No, the target is G:\GoHere\TheSameFileName then you have to program this.
Separately, your code is a mess. Stop using java.io.File and java.nio.Path together. Pick a side (and pick the java.nio side, it's an newer API for a good reason), and do not mix and match.
For example:
Path fromDir = Paths.get("G:\\FromHere");
Path targetDir = Paths.get(G:\\ToHere");
try (DirectoryStream ds = Files.newDirectoryStream(fromDir)) {
for (Path child : ds) {
if (Files.isRegularFile(child)) {
Path targetFile = targetDir.resolve(child.getFileName());
Files.move(child, targetFile);
}
}
}
resolve gives you a Path object that is what you need here: The actual file in the target dir.
I want to read a file in my java class. My question is similar to this one, but there are two differences. first, I use a different project layout:
/src/com/company/project
/resources
In the resources folder I have a file called "test.txt":
/resources/test.txt
In the project folder I have a class test.java
/src/com/company/project/test.java
I want mu java class to be able to read the contents of test.txt in a STATIC METHOD. I've tried the following:
private static String parseFile()
{
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String fileURL = classLoader.getResource("test.txt").getFile();
File file = new File(fileURL);
...
}
}
and the following paths:
File file1 = new File("test.txt");
File file2 = new File("/test.txt");
File file3 = new File("/resources/test.txt");
But they all throw a FileNotFoundException when I want to read the file. How can I correctly declare the path to my file in the snippet above with respect to my project setup and the fact that the method needs to be static?
You should use the class loader of the class which is in the same JAR as the resource instead of the TCCL. And then you need to specify the name of the resource with a full path. And it is typically not good to access those as files. Just open it directly for read (or copy it to a temp file if you need to):
InputStream is =
Project.class.getClassLoader().getResourceAsStream("/resource/test.txt");
BTW: if you simply want to open a file, you need to use a relative file name. This is searched relative to the start dir, which is normally the project main dir (in eclipse):
File resource = new File("resource/test.txt");
(but this wont work if you package it up as a JAR).
After endless trials, I gave up on ClassLoader and getResource methods of any kind.
Absolutely nothing worked, especially if the opening attempt was made from another project. I always ended up getting the bin folder instead of the src folder.
So I devised the following work around:
public class IOAccessory {
public static String getProjectDir() {
try {
Class<?> callingClass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
URL url = callingClass.getProtectionDomain().getCodeSource().getLocation();
URI parentDir = url.toURI().resolve("..");
return parentDir.getPath();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return "";
}
}
The getProjectDir method returns the physical path of the project from which it was called, e.g. C:/workspace/MyProject/.
After that, all you need to do is concatenate the relative path in MyProject of your resource file to open the stream:
public void openResource() throws IOException {
InputStream stream = null;
String projectDir = IOAccessory.getProjectDir();
String filePath = "resources/test.txt";
try {
stream = new FileInputStream(projectDir + filePath);
open(stream);
} catch(Exception e) {
e.printStackTrace();
} finally {
if (stream != null)
stream.close();
}
}
This technique works whether the openResource method is static or non-static, and whether it is called from within the project or from another project on the build path.
It really depends on how your IDE generates output from your project. Typically, classloaders load resources relative to the invoking classes, but if treated right, 'resources' will just end up in the 'root' of your output folder hierarchy, and you can access them accordingly.
For example, if I recreate your code in IntelliJ IDEA, in a class called com/acme/TestClass.class, the following output structure is generated within the IDE when building. This assumes I have "test.txt" sitting in a folder I called "resources", and that folder is specified as being a "resources root":
/com
/acme
TestClass.class
test.txt
The text file ends up in the output folder's root, so accessing it is simple. The following code works for me when I attempt to load the file in a static method within TestClass:
ClassLoader cl = TestClass.class.getClassLoader();
InputStream is = cl.getResourceAsStream("test.txt");
The only thing not covered in the other answers is that your URL conversion to file might not work correctly. If the directories above your project contain a characters that must be decoded then your call to 'getResource("test.txt").getFile()' is not giving you a valid java.io.File path.
I load shader for openGL ES from static function.
Remember you must use lower case for your file and directory name, or else the operation will be failed
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public static int loadShader() {
// Read file as input stream
InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");
// Convert input stream to string
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String shaderCode = s.hasNext() ? s.next() : "";
}
...
}
Another method to convert input stream to string.
byte[] bytes;
String shaderCode = "";
try {
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
shaderCode = new String(bytes);
}
catch (IOException e) {
e.printStackTrace();
}
I have around 500 text files inside a directory with each with the same prefix in their filename, for example: dailyReport_.
The latter part of the file is the date of the file. (For example dailyReport_08262011.txt, dailyReport_08232011.txt)
I want to delete these files using a Java procedure. (I could go for a shell script and add it a job in the crontab but the application is meant to used by laymen).
I can delete a single file using something like this:
try{
File f=new File("dailyReport_08232011.txt");
f.delete();
}
catch(Exception e){
System.out.println(e);
}
but can I delete the files having a certain prefix? (e.g. dailyReport08 for the 8th month) I could easily do that in shell script by using rm -rf dailyReport08*.txt .
But File f=new File("dailyReport_08*.txt"); doesnt work in Java (as expected).
Now is anything similar possible in Java without running a loop that searches the directory for files?
Can I achieve this using some special characters similar to * used in shell script?
No, you can't. Java is rather low-level language -- comparing with shell-script -- so things like this must be done more explicetly. You should search for files with required mask with folder.listFiles(FilenameFilter), and iterate through returned array deleting each entry. Like this:
final File folder = ...
final File[] files = folder.listFiles( new FilenameFilter() {
#Override
public boolean accept( final File dir,
final String name ) {
return name.matches( "dailyReport_08.*\\.txt" );
}
} );
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
You can use a loop
for (File f : directory.listFiles()) {
if (f.getName().startsWith("dailyReport_")) {
f.delete();
}
}
Java 8 :
final File downloadDirectory = new File("directoryPath");
final File[] files = downloadDirectory.listFiles( (dir,name) -> name.matches("dailyReport_.*?" ));
Arrays.asList(files).stream().forEach(File::delete)
With Java 8:
public static boolean deleteFilesForPathByPrefix(final String path, final String prefix) {
boolean success = true;
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get(path), prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) {
success = false;
e.printStackTrace();
}
return success;
}
Simple version:
public static void deleteFilesForPathByPrefix(final Path path, final String prefix) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path, prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) { // empty
}
}
Modify the Path/String argument as needed. You can even convert between File and Path. Path is preferred for Java >= 8.
I know I'm late to the party. However, for future reference, I wanted to contribute a java 8 stream solution that doesn't involve a loop.
It may not be pretty. I welcome suggestions to make it look better. However, it does the job:
Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
try {
Files.deleteIfExists(p);
} catch (Exception e) {
e.printStackTrace();
}
});
Alternatively, you can use Files.walk which will traverse the directory depth-first. That is, if the files are buried in different directories.
Use FileFilter like so:
File dir = new File(<path to dir>);
File[] toBeDeleted = dir.listFiles(new FileFilter() {
boolean accept(File pathname) {
return (pathname.getName().startsWith("dailyReport_08") && pathname.getName().endsWith(".txt"));
}
for (File f : toBeDeleted) {
f.delete();
}
There isn't a wildcard but you can implement a FilenameFilter and check the path with a startsWith("dailyReport_"). Then calling File.listFiles(filter) gives you an array of Files that you can loop through and call delete() on.
I agree with BegemoT.
However, just one optimization:
If you need a simple FilenameFilter, there is a class in the Google packages.
So, in this case you do not even have to create your own anonymous class.
import com.google.common.io.PatternFilenameFilter;
final File folder = ...
final File[] files = folder.listFiles(new PatternFilenameFilter("dailyReport_08.*\\.txt"));
// loop through the files
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
Enjoy !
You can't do it without a loop. But you can enhance this loop. First of all, ask you a question: "what's the problem with searching and removing in the loop?" If it's too slow for some reason, you can just run your loop in a separate thread, so that it will not affect your user interface.
Other advice - put your daily reports in a separate folder and then you will be able to remove this folder with all content.
or in scala
new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
Have a look at Apache FileUtils which offers many handy file manipulations.
I am trying to read a text file which is set in CLASSPATH system variable. Not a user variable.
I am trying to get input stream to the file as below:
Place the directory of file (D:\myDir) in CLASSPATH and try below:
InputStream in = this.getClass().getClassLoader().getResourceAsStream("SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("/SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("//SomeTextFile.txt");
Place full path of file (D:\myDir\SomeTextFile.txt) in CLASSPATH and try the same above 3 lines of code.
But unfortunately NONE of them are working and I am always getting null into my InputStream in.
With the directory on the classpath, from a class loaded by the same classloader, you should be able to use either of:
// From ClassLoader, all paths are "absolute" already - there's no context
// from which they could be relative. Therefore you don't need a leading slash.
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("SomeTextFile.txt");
// From Class, the path is relative to the package of the class unless
// you include a leading slash, so if you don't want to use the current
// package, include a slash like this:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
If those aren't working, that suggests something else is wrong.
So for example, take this code:
package dummy;
import java.io.*;
public class Test
{
public static void main(String[] args)
{
InputStream stream = Test.class.getResourceAsStream("/SomeTextFile.txt");
System.out.println(stream != null);
stream = Test.class.getClassLoader().getResourceAsStream("SomeTextFile.txt");
System.out.println(stream != null);
}
}
And this directory structure:
code
dummy
Test.class
txt
SomeTextFile.txt
And then (using the Unix path separator as I'm on a Linux box):
java -classpath code:txt dummy.Test
Results:
true
true
When using the Spring Framework (either as a collection of utilities or container - you do not need to use the latter functionality) you can easily use the Resource abstraction.
Resource resource = new ClassPathResource("com/example/Foo.class");
Through the Resource interface you can access the resource as InputStream, URL, URI or File. Changing the resource type to e.g. a file system resource is a simple matter of changing the instance.
This is how I read all lines of a text file on my classpath, using Java 7 NIO:
...
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
...
Files.readAllLines(
Paths.get(this.getClass().getResource("res.txt").toURI()), Charset.defaultCharset());
NB this is an example of how it can be done. You'll have to make improvements as necessary. This example will only work if the file is actually present on your classpath, otherwise a NullPointerException will be thrown when getResource() returns null and .toURI() is invoked on it.
Also, since Java 7, one convenient way of specifying character sets is to use the constants defined in java.nio.charset.StandardCharsets
(these are, according to their javadocs, "guaranteed to be available on every implementation of the Java platform.").
Hence, if you know the encoding of the file to be UTF-8, then specify explicitly the charset StandardCharsets.UTF_8
Please try
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
Your tries didn't work because only the class loader for your classes is able to load from the classpath. You used the class loader for the java system itself.
To actually read the contents of the file, I like using Commons IO + Spring Core. Assuming Java 8:
try (InputStream stream = new ClassPathResource("package/resource").getInputStream()) {
IOUtils.toString(stream);
}
Alternatively:
InputStream stream = null;
try {
stream = new ClassPathResource("/log4j.xml").getInputStream();
IOUtils.toString(stream);
} finally {
IOUtils.closeQuietly(stream);
}
To get the class absolute path try this:
String url = this.getClass().getResource("").getPath();
Somehow the best answer doesn't work for me. I need to use a slightly different code instead.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("SomeTextFile.txt");
I hope this help those who encounters the same issue.
If you use Guava:
import com.google.common.io.Resources;
we can get URL from CLASSPATH:
URL resource = Resources.getResource("test.txt");
String file = resource.getFile(); // get file path
or InputStream:
InputStream is = Resources.getResource("test.txt").openStream();
Ways to convert an InputStream to a String
To read the contents of a file into a String from the classpath, you can use this:
private String resourceToString(String filePath) throws IOException, URISyntaxException
{
try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath))
{
return IOUtils.toString(inputStream);
}
}
Note:
IOUtils is part of Commons IO.
Call it like this:
String fileContents = resourceToString("ImOnTheClasspath.txt");
You say "I am trying to read a text file which is set in CLASSPATH system variable." My guess this is on Windows and you are using this ugly dialog to edit the "System Variables".
Now you run your Java program in the console. And that doesn't work: The console gets a copy of the values of the system variables once when it is started. This means any change in the dialog afterwards doesn't have any effect.
There are these solutions:
Start a new console after every change
Use set CLASSPATH=... in the console to set the copy of the variable in the console and when your code works, paste the last value into the variable dialog.
Put the call to Java into .BAT file and double click it. This will create a new console every time (thus copying the current value of the system variable).
BEWARE: If you also have a User variable CLASSPATH then it will shadow your system variable. That is why it is usually better to put the call to your Java program into a .BAT file and set the classpath in there (using set CLASSPATH=) rather than relying on a global system or user variable.
This also makes sure that you can have more than one Java program working on your computer because they are bound to have different classpaths.
My answer is not exactly what is asked in the question. Rather I am giving a solution exactly how easily we can read a file into out java application from our project class path.
For example suppose a config file name example.xml is located in a path like below:-
com.myproject.config.dev
and our java executable class file is in the below path:-
com.myproject.server.main
now just check in both the above path which is the nearest common directory/folder from where you can access both dev and main directory/folder (com.myproject.server.main - where our application’s java executable class is existed) – We can see that it is myproject folder/directory which is the nearest common directory/folder from where we can access our example.xml file. Therefore from a java executable class resides in folder/directory main we have to go back two steps like ../../ to access myproject. Now following this, see how we can read the file:-
package com.myproject.server.main;
class Example {
File xmlFile;
public Example(){
String filePath = this.getClass().getResource("../../config/dev/example.xml").getPath();
this.xmlFile = new File(filePath);
}
public File getXMLFile() {
return this.xmlFile;
}
public static void main(String args[]){
Example ex = new Example();
File xmlFile = ex.getXMLFile();
}
}
If you compile your project in jar file:
you can put your file in resources/files/your_file.text or pdf;
and use this code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
public class readFileService(){
private static final Logger LOGGER = LoggerFactory.getLogger(readFileService.class);
public byte[] getFile(){
String filePath="/files/your_file";
InputStream inputStreamFile;
byte[] bytes;
try{
inputStreamFile = this.getClass().getResourceAsStream(filePath);
bytes = new byte[inputStreamFile.available()];
inputStreamFile.read(bytes);
} catch(NullPointerException | IOException e) {
LOGGER.error("Erreur read file "+filePath+" error message :" +e.getMessage());
return null;
}
return bytes;
}
}
I am using webshpere application server and my Web Module is build on Spring MVC. The Test.properties were located in the resources folder, i tried to load this files using the following:
this.getClass().getClassLoader().getResourceAsStream("Test.properties");
this.getClass().getResourceAsStream("/Test.properties");
None of the above code loaded the file.
But with the help of below code the property file was loaded successfully:
Thread.currentThread().getContextClassLoader().getResourceAsStream("Test.properties");
Thanks to the user "user1695166".
Use org.apache.commons.io.FileUtils.readFileToString(new File("src/test/resources/sample-data/fileName.txt"));
Don't use getClassLoader() method and use the "/" before the file name. "/" is very important
this.getClass().getResourceAsStream("/SomeTextFile.txt");
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile
{
/**
* * feel free to make any modification I have have been here so I feel you
* * * #param args * #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// thread pool of 10
File dir = new File(".");
// read file from same directory as source //
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
// if you wanna read file name with txt files
if (file.getName().contains("txt")) {
System.out.println(file.getName());
}
// if you want to open text file and read each line then
if (file.getName().contains("txt")) {
try {
// FileReader reads text files in the default encoding.
FileReader fileReader = new FileReader(
file.getAbsolutePath());
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(
fileReader);
String line;
// get file details and get info you need.
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
// here you can say...
// System.out.println(line.substring(0, 10)); this
// prints from 0 to 10 indext
}
} catch (FileNotFoundException ex) {
System.out.println("Unable to open file '"
+ file.getName() + "'");
} catch (IOException ex) {
System.out.println("Error reading file '"
+ file.getName() + "'");
// Or we could just do this:
ex.printStackTrace();
}
}
}
}
}
}
you have to put your 'system variable' on the java classpath.