Search code examples
javajarioinputstreamembedded-resource

read file from inside jar Not Working


In Java, I have tried the different techniques of reading a file inside the jar. I have gotten one to work inside another program, but not this one. The InputStream that I get from the classname.class.getClassLoader().getResourceAsStream(filenamestring); method returns null.

 package mainpkg;

 import java.awt.GridLayout;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.JTextField;
 import javax.swing.UIManager;

 public class MainClass extends JFrame{
JTextField jtf = new JTextField();
boolean isInstalling = false;
public MainClass(){
    super("StringThatTitleWillBe");
}
public void initiate(){
    setLookAndFeel();
    setSize(550, 400);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    GridLayout bl = new GridLayout(2, 1, 10, 10);
    setLayout(bl);

    JButton b = new JButton("Install");
    b.addMouseListener(new MouseListener(){

        @Override
        public void mouseClicked(MouseEvent arg0) {
            if(!isInstalling){
            isInstalling = true;
            install();
            }
        }

        @Override
        public void mouseEntered(MouseEvent arg0) {

        }

        @Override
        public void mouseExited(MouseEvent arg0) {

        }

        @Override
        public void mousePressed(MouseEvent arg0) {

        }

        @Override
        public void mouseReleased(MouseEvent arg0) {

        }

    });
    add(b);
    jtf.setEditable(false);
    add(jtf);
    //show
    setVisible(true);
}
private void setLookAndFeel() {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception exc) {
        System.out.print("failed to load look and feel");
    }
}
public static void main(String[] args){
    MainClass m = new MainClass();
    m.initiate();
}

public void install() {
    String files = "name of jarfile inside the jar to be read";
    InputStream stream = MainClass.class.getClassLoader().getResourceAsStream(files);
    File f = new File(files);
    if(stream == null)
        System.out.println("stream is null");
    try {
        int val = stream.read();
        BufferedWriter br = new BufferedWriter(new FileWriter(f));
        while(val != -1){
        br.write(val);
        val = stream.read();
        }
        stream.close();
        br.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    isInstalling = false;
     }
 }

It Prints "stream is null" and gives an error on the line: stream.read(); I know that means that the file is not being converted to an InputStream properly. Have I made a stupid mistake??? please help. Thanks in advance Edit: the file that I want to copy in the same directory as the jar is directly inside the jar. It is not in a package or any such additional directory.


Solution

  • If a getResourceAsStream(String) returns null, that means that the class loader can't find a resource with the name you gave it. Either it is plain wrong, or maybe you have used a relative name and the resource isn't in the "/" directory in the JAR.

    For details, read the javadoc for ClassLoader.getResourceAsStream, paying careful attention to:

    • the value returned, and
    • the handling of relative pathnames (follow the getResource link!!).

    If you want to load a resource using a relative name that is resolved relative the classes package, you should write this:

        MainClass.class.getResourceAsStream(files);
    

    The Class.getResource... methods resolve relative names relative to the class. So the above would resolve "foo.txt" to "/mainpkg/foo.txt" ... where your version would resolve it to "/foo.txt".