I have two Java applications. One application will contain resource files and will be used as library to other Java application.
First app com.test.resourceusing.MainClass.java which contains res/base.xml resource file.
package com.test.resourceusing;
import java.io.BufferedInputStream;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;
public class MainClass {
public MainClass() {
super();
}
public static void main(String[] args) {
MainClass main = new MainClass();
try {
main.start();
} catch (MalformedURLException e) {
}
}
public void start() throws MalformedURLException {
URL url = getClass().getResource("res/base.xml");
System.out.println(url.getPath());
System.out.println(url.getFile());
File f = new File(url.getFile());
if (f.exists()) {
System.out.println("File exist!");
BufferedInputStream result = (BufferedInputStream)
getClass().getResourceAsStream("res/base.xml");
Scanner scn = new Scanner(result);
while(scn.hasNext()){
System.out.println(scn.next());
}
} else {
System.out.println("Not working! :(");
}
}
}
Result is:
/C:/Work/Projects/ResourceUsing/classes/com/test/resourceusing/res/base.xml
/C:/Work/Projects/ResourceUsing/classes/com/test/resourceusing/res/base.xml
File exist!
<?xml
version='1.0'
encoding='utf-8'?>
<schema>
</schema>
Then I create .jar file which contains all resource files and try to use it as library in other application.
Second app:
resourcetest.MainClassTest.java
package resourcetest;
import com.test.resourceusing.MainClass;
import java.net.MalformedURLException;
public class MainClassTest {
public MainClassTest() {
super();
}
public static void main(String[] args) {
MainClass main = new MainClass();
try {
main.start();
} catch (MalformedURLException e) {
}
}
}
Result is:
file:/C:/Work/Projects/ResourceUsing/deploy/archive1.jar!/com/test/resourceusing/res/base.xml
file:/C:/Work/Projects/ResourceUsing/deploy/archive1.jar!/com/test/resourceusing/res/base.xml
Not working! :(
I don't understand why it's not working, is there problems in my code? Or this solution is not possible in Java?
Do you see the difference in the location of those files?
/C:/Work/Projects/ResourceUsing/classes/com/test/resourceusing/res/base.xml
file:/C:/Work/Projects/ResourceUsing/deploy/archive1.jar!/com/test/resourceusing/res/base.xml
You cannot access a resource that is located in a JAR file with the File API.
Your code is already on the way. A simple edit should work:
public void start() throws IOException {
URL url = getClass().getResource("res/base.xml");
if (url != null) {
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println("File exist!");
try(InputStream result = url.openStream()) {
try(Scanner scn = new Scanner(result)) {
while(scn.hasNext()) {
System.out.println(scn.next());
}
}
}
} else {
System.out.println("Not working! :(");
}
}
After deeper searching looks like I found a reason - https://stackoverflow.com/a/10605316/1117515.
In this case I need to use getResourceAsStream().
Related
I'm having real difficulties figuring out how this needs to be coded without using FileUtils import. I have found thousands of tutorials on how to move files to empty folders, that's easy. The difficulty is finding out how Java can move files to directories that already have files in the folder. As I understand it the REPLACE_EXISTING parameter means it will overwrite identical file names if detected in the destination directory, but the directory doesn't have a file with a matching name of the file I'm attempting to copy/move. What am I missing? How can I make this happen?
java.nio.file.DirectoryNotEmptyException occuring.
enter code here
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class Move {
static File source = new File("sourcefolderhere");
static File destination = new File("destfolderhere");
public static void move(File src, File dest) throws IOException {
Files.move(src.toPath().toAbsolutePath(), dest.toPath().toAbsolutePath(),
StandardCopyOption.REPLACE_EXISTING);
}
public static void main(String[] args) throws IOException {
try {
if(source.isDirectory() && destination.isDirectory()) {
File[] content = source.listFiles();
for(int i = 0; i < content.length; i++) {
System.out.println(content[i]);
move(source, destination);
}
}
else if (!destination.isDirectory()){
System.out.println("create folder here");
destination.mkdir();
File[] content = source.listFiles();
for(int i = 0; i < content.length; i++) {
move(source, destination);
}
}
}
catch(Exception ex) { System.out.println(ex);
}
finally {
}
}
}
I tried the code in IDE File.move method with parameter StandardCopyOption.REPLACE_EXISTING works only if you have file in the destination folder. otherwise use File.move the normal way. I have also modified your code a little just to avoid code duplication.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
public class Move {
static File source = new File("sourcefolderhere");
static File destination = new File("destfolderhere");
public static void move(File src, File dest) throws IOException {
System.out.println(src.getName());
if(isExist(src.getName()))
Files.move(src.toPath().toAbsolutePath(), Paths.get(destination.getAbsolutePath()+File.separator+src.getName()) , StandardCopyOption.REPLACE_EXISTING);
else
Files.move(src.toPath().toAbsolutePath(), Paths.get(destination.getAbsolutePath()+File.separator+src.getName()));
}
public static boolean isExist(String souceFileName){
//If you are not using java 8 code
/*String[] destFiles = destination.list();
for(String fileName : destFiles){
if(souceFileName.equals(fileName))
return true;
}
return false;*/
return Arrays.stream(destination.list())
.anyMatch(fileName -> fileName.equals(souceFileName));
}
public static void main(String[] args) throws IOException {
try {
if(!source.isDirectory())
throw new IllegalArgumentException("Source Folder doesn't Exist");
if(!destination.exists())
destination.mkdir();
if (source.isDirectory() && destination.isDirectory()) {
File[] content = source.listFiles();
for (int i = 0; i < content.length; i++) {
System.out.println(content[i]);
move(content[i], destination);
}
}
} catch (Exception ex) {
System.out.println(ex);
} finally {
}
}
}```
I have got this class for loading blue images, which works fine in Eclipse but not in the exported jar. How can I access all the blue images in the folder (directory) called "blue" without knowing the names of the images?
public class Blue
{
public static void read() throws Exception
{
File directoryBlueImages = new File(
Blue.class.getResource("blue").getFile());
String[] blueImages = directoryBlueImages.list();
List<BufferedImage> blueImagesList = new ArrayList<>();
for (String blueImage : java.util.Objects.requireNonNull(blueImages))
{
blueImagesList.add(ImageIO
.read(Blue.class.getResourceAsStream("blue/" + blueImage)));
}
ApplicationImages.setBlueImages(blueImagesList);
}
}
UPDATE
I have tried this, but it does not work either. I am getting a NullPointer exception. I tried "/blue" and "blue" and even ".blue".
import java.awt.image.BufferedImage;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
import vokabeltrainer.ApplicationImages;
public class Blue
{
public static void read() throws Exception
{
List<BufferedImage> blueImagesList = new ArrayList<>();
try (Stream<Path> pathStream = Files.walk(Paths.get(Blue.class
.getClassLoader().getResource("blue").toURI().toURL().getPath()))
.filter(Files::isRegularFile))
{
for (Path file : (Iterable<Path>) pathStream::iterator)
{
blueImagesList.add(ImageIO
.read(Blue.class.getResourceAsStream(file.toString())));
;
}
}
ApplicationImages.setBlueImages(blueImagesList);
}
}
I adapted an answer from How to list the files inside a JAR file?
First I distinguish wether I am running from jar or Eclipse:
try
{
Blue.readZip(); // when inside jar
}
catch (Exception e)
{
try
{
Blue.read(); // during development
}
catch (Exception e1)
{
System.out.println("Could not read blue.");
e1.printStackTrace();
}
}
Then class Blue looks like this:
public class Blue
{
private static List<BufferedImage> blueImagesList = new ArrayList<>();
public static void read() throws Exception
{
File directoryBlueImages = new File(
Blue.class.getResource("blue").getFile());
String[] blueImages = directoryBlueImages.list();
for (String blueImage : java.util.Objects.requireNonNull(blueImages))
{
blueImagesList.add(ImageIO
.read(Blue.class.getResourceAsStream("blue/" + blueImage)));
}
ApplicationImages.setBlueImages(blueImagesList);
}
public static void readZip() throws Exception
{
CodeSource src = Blue.class.getProtectionDomain().getCodeSource();
if (src != null)
{
URL jar = src.getLocation();
ZipFile zipFile = new ZipFile(jar.getFile());
ZipInputStream zip = new ZipInputStream(jar.openStream());
while (true)
{
ZipEntry ze = zip.getNextEntry();
if (ze == null)
break;
String name = ze.getName();
if (name.startsWith("vokabeltrainer/resources/blue/"))
{
blueImagesList.add(ImageIO.read(zipFile.getInputStream(ze)));
}
}
}
else
{
throw new IOException("can not find code source for blue images");
}
ApplicationImages.setBlueImages(blueImagesList);
}
}
On the same directory of my Main.java file, I have a package/folder named database, and inside the database package I have a file named Data.txt.
This is my code of Main.java, but it is throwing this error:
java: exception java.io.FileNotFoundException
How can I get the file from a relative file? I'm used to web development, and usually something with a . dot like "./folder/file.txt" works.
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Main {
public static void main(String[] args) {
readFile();
}
public static void readFile() {
File file = new File("./database/Data.txt");
Scanner scanner = new Scanner(file);
try {
while (scanner.hasNextLine()) {
int i = scanner.nextInt();
System.out.println(i);
}
scanner.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
You are not importing FileNotFoundException class. also, scanner statement throws the exception which should inside try. Solution is as below.
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Main {
public static void main(String[] args) {
readFile();
}
public static void readFile() {
File file = new File("database/Data.txt");
try {
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
int i = scanner.nextInt();
System.out.println(i);
}
scanner.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Only check if those content can read using scanner or not. Content having int properly. otherwise it will throw java.util.InputMismatchException.
Are you working on a mac or windows system.
I am on windows and ".\database\Data.txt" would most probably work depending on where the file is in your file structure.
I have a very different situation to deal with. Something never seen before.
I have a codebase which is not a maven based project. It basically is set of Pig Script that are executed on Hadoop Cluster.
Now there is requirement to test these scripts using PigUnit, so I created a maven based project with all dependencies needed for the project.
Visually it looks like
user_mapper/
src/main/
user.pig
other.pig
test/
pom.xml
src/java/
/UserTest.java
/OtherTest.java
As you could see, test is a maven based project in itself.
What I need
In UserTest.java I want to refer to relative path of user.pig
How can I provide a relative path in UserTest.java?
Try the following code (internally uses commons-io jar)
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class FileReader {
Logger logger = Logger.getLogger(FileReader.class.getName());
static String webAppPath;
private static final boolean IS_WINDOWS = System.getProperty( "os.name" ).contains( "indow" );
private InputStream inputStream;
private static FileReader fileReader;
public String getAbsolutePath(Class appClass, String relativePath) {
try {
String parentPath = "";
if (StringUtils.isNotBlank(webAppPath)) {
parentPath = webAppPath;
} else {
parentPath = appClass.getProtectionDomain().getCodeSource().getLocation().getPath();
}
String osAppropriatePath = IS_WINDOWS ? parentPath.substring(1) : parentPath;
String absolutePath = osAppropriatePath + relativePath;
File file = new File(absolutePath);
if (!file.exists()) {
FileUtils.writeStringToFile(file, IOUtils.toString(readFile(relativePath), "UTF-8"));
}
return absolutePath;
} catch (IOException ioe) {
logger.log(Level.SEVERE, null, ioe);
return relativePath;
}
}
public void closeFileReader() {
synchronized (this) {
try {
inputStream.close();
} catch (IOException ex) {
Logger.getLogger(FileReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private FileReader() {
}
public static FileReader getInstance() {
return new FileReader();
}
public static String getWebAppPath() {
return webAppPath;
}
public static void setWebAppPath(String webAppPath) {
FileReader.webAppPath = webAppPath;
}
}
And call the class to get the relative path as follows
FileReader.getInstance().getAbsolutePath(user.pig, "user.pig");
I solved this issue by using java.io.File as
final String filePath = new File("../src/user.pig").getAbsolutePath();
I am thinking using truezip API in Java to manipulate with ear file by
extract ear into tmp directory,
then search through jars in tmp,
if found properties in jar,
then extract it into tmp,
modify that property
then pack it back into jar,
then pack jar back into ear.
OR is there a better way in using shell script?
Please advise.
Thanks
Using TrueZIP 7, you could use something like this:
public static void main(String args[]) throws IOException {
// Remember to add the following dependencies to the class path:
// Compile time artifactId(s): truezip-file
// Run time artifactId(s): truezip-kernel, truezip-driver-file, truezip-driver-zip
TFile.setDefaultArchiveDetector(new TDefaultArchiveDetector("ear|jar|war"));
search(new TFile(args[0])); // e.g. "my.ear"
TFile.umount(); // commit changes
}
private void search(TFile entry) throws IOException {
if (entry.isDirectory()) {
for (TFile member : dir.listFiles())
search(member);
} else if (entry.isFile()) {
if (entry.getName().endsWith(".properties");
update(entry);
} // else is special file or non-existent
}
private void update(TFile file) throws IOException {
Properties properties = new Properties();
InputStream in = new TFileInputStream(file);
try {
properties.load(in);
} finally {
in.close();
}
// [your updates here]
OutputStream out = new TFileOutputStream(file);
try {
properties.store(out, "updated");
} finally {
out.close();
}
}
I used the answer from #Christian Schlichtherle to get me started on what I was trying to accomplish, but the usage of True Zip has changed quite a bit. I thought I'd post what I needed to do here to hopefully help someone.
You need to create a class that extends TApplication. In my case I'm making it abstract so I can reuse the setup code in my implementing logic classes.
Application.java:
import de.schlichtherle.truezip.file.TApplication;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TConfig;
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
/**
* An abstract class which configures the TrueZIP Path module.
*/
abstract class Application<E extends Exception> extends TApplication<E> {
/**
* Runs the setup phase.
* <p>
* This method is {#link #run run} only once at the start of the life
* cycle.
*/
#Override
protected void setup() {
TConfig.get().setArchiveDetector(
new TArchiveDetector(
TArchiveDetector.NULL,
new Object[][] {
{ "zip", new ZipDriver(IOPoolLocator.SINGLETON)},
{ "ear|jar|war", new JarDriver(IOPoolLocator.SINGLETON)},
}));
}
}
Then you just extend the abstract class and implement the "work" method as shown.
ChangeProperty.java:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.ServiceConfigurationError;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import de.schlichtherle.truezip.file.TFileOutputStream;
public class ChangeProperty extends Application<IOException> {
public static void main(String args[]) throws IOException {
try {
System.exit(new ChangeProperty().run(args));
} catch (ServiceConfigurationError e) {
// Ignore this error because what we wanted to accomplish has been done.
}
}
private void search(TFile entry) throws IOException {
System.out.println("Scanning: " + entry);
if (entry.isDirectory()) {
for (TFile member : entry.listFiles())
search(member);
} else if (entry.isFile()) {
if (entry.getName().endsWith(".properties")) {
update(entry);
}
}
}
private void update(TFile file) throws IOException {
System.out.println("Updating: " + file);
Properties properties = new Properties();
InputStream in = new TFileInputStream(file);
try {
properties.load(in);
} finally {
in.close();
}
// [your updates here]
// For example: properties.setProperty(key, newValue);
OutputStream out = new TFileOutputStream(file);
try {
properties.store(out, "updated by loggerlevelchanger");
} finally {
out.close();
}
}
#Override
protected int work(String[] args) throws IOException {
search(new TFile(args[0]));
return 0;
}
}