BufferedReader Null Pointer Exception Class Resource

I have a parser for OBJ files and MTL Files however I keep on getting a null pointer exception even though it is there. I know I have my file correct because I double-check where the files are. resources (source file)/res/meshes/{}.obj,.mtl

Here is my MyFile class

package com.darkerminecraft.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MyFile {

    private static final String FILE_SEPARATOR = "/";

    private String path;
    private String name;

    public MyFile(String path) {
        this.path = FILE_SEPARATOR + path;
        String[] dirs = path.split(FILE_SEPARATOR);
        this.name = dirs[dirs.length - 1];
    }

    public MyFile(String... paths) {
        this.path = "";
        for (String part : paths) {
            this.path += (FILE_SEPARATOR + part);
        }
        String[] dirs = path.split(FILE_SEPARATOR);
        this.name = dirs[dirs.length - 1];
    }

    public MyFile(MyFile file, String subFile) {
        this.path = file.path + FILE_SEPARATOR + subFile;
        this.name = subFile;
    }

    public MyFile(MyFile file, String... subFiles) {
        this.path = file.path;
        for (String part : subFiles) {
            this.path += (FILE_SEPARATOR + part);
        }
        String[] dirs = path.split(FILE_SEPARATOR);
        this.name = dirs[dirs.length - 1];
    }

    public String getPath() {
        return path;
    }

    @Override
    public String toString() {
        return getPath();
    }

    public InputStream getInputStream() {
        return Class.class.getResourceAsStream(path);
    }

    public BufferedReader getReader() throws Exception {
        try {
            InputStreamReader isr = new InputStreamReader(getInputStream());
            BufferedReader reader = new BufferedReader(isr);
            return reader;
        } catch (Exception e) {
            System.err.println("Couldn't get reader for " + path);
            throw e;
        }
    }

    public String getName() {
        return name;
    }

}

This is my parser class

package com.darkerminecraft.graphics.mesh;

import java.util.ArrayList;
import java.util.List;

import org.joml.Vector3f;

import com.darkerminecraft.utils.MyFile;

public class MeshLoader {

    public static Mesh load3DModel(String fileName) {
        MyFile objFile = new MyFile("res/meshes/" + fileName + ".obj");

        String line = "";
        String mtlFileName = "";
        String currentFaceMat = "";

        Mesh mesh = new Mesh();

        try {
            while ((line = objFile.getReader().readLine()) != null) {
                String[] lineParts = line.split(" ");
                switch (line.substring(0, 2)) {
                case "v ":
                    Vertex v = new Vertex(createVector(lineParts));
                    mesh.addVertex(v);
                    break;
                case "vn":
                    Normal n = new Normal(createVector(lineParts));
                    mesh.addNormal(n);
                    break;
                case "mt":
                    mtlFileName = lineParts[1];
                    break;
                case "us":
                    currentFaceMat = lineParts[1];
                    break;
                case "f ":
                    Face face = createFace(currentFaceMat, lineParts);
                    mesh.addFace(face);
                    break;
                }
                objFile.getReader().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        MyFile mtlFile = new MyFile("res/meshes/" + mtlFileName + ".mtl");
        Material mat = null;
        try {
            while ((line = mtlFile.getReader().readLine()) != null) {
                String[] lineParts = line.split(" ");
                switch (line.substring(0, 2)) {
                case "ne":
                    mat = new Material(lineParts[1]);
                    mesh.addMaterial(lineParts[1], mat);
                    break;
                case "Ka":
                    mat.setKa(createVector(lineParts));
                    break;
                case "Kd":
                    mat.setKd(createVector(lineParts));
                    break;
                case "Ks":
                    mat.setKs(createVector(lineParts));
                    break;
                case "Ns":
                    mat.setNs(Float.parseFloat(lineParts[1]));
                    break;
                case "d ":
                    mat.setD(Float.parseFloat(lineParts[1]));
                    break;
                case "il":
                    mat.setIllum(Float.parseFloat(lineParts[1]));
                    break;
                }
                mtlFile.getReader().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        mesh.normalArray = new float[mesh.vertices.size() * 3];
        
        for(Face face : mesh.faces) {
            decodeNormals(face.indices1, mesh);
            decodeNormals(face.indices2, mesh);
            decodeNormals(face.indices3, mesh);
        }
        
        List<Vertex> materialVertices = new ArrayList<>();
        for(Face face : mesh.faces) {
            Vertex v1 = new Vertex(face.material, face.indices1);
            Vertex v2 = new Vertex(face.material, face.indices2);
            Vertex v3 = new Vertex(face.material, face.indices3);
            materialVertices.add(v1);
            materialVertices.add(v2);
            materialVertices.add(v3);
        }
        
        mesh.vertexArray = new float[mesh.vertices.size() * 3];
        mesh.indexArray = new int[mesh.indices.size() * 3];
        mesh.colorArray = new float[mesh.vertices.size() * 3];
        
        int vertexPointer = 0;
        int colorPointer = 0;
        for(Vertex vertex : mesh.vertices) {
            mesh.vertexArray[vertexPointer++] = vertex.getPosition().x;
            mesh.vertexArray[vertexPointer++] = vertex.getPosition().y;
            mesh.vertexArray[vertexPointer++] = vertex.getPosition().z;
            mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().x;
            mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().y;
            mesh.colorArray[colorPointer++] = mesh.materials.get(vertex.getMaterialName()).getKd().z;
        }
        
        return mesh;
    }

    private static Vector3f createVector(String[] lineData) {
        float x = Float.parseFloat(lineData[1]);
        float y = Float.parseFloat(lineData[2]);
        float z = Float.parseFloat(lineData[3]);

        return new Vector3f(x, y, z);
    }

    private static Face createFace(String materialName, String[] lineData) {
        String[] indices1 = lineData[1].split("/");
        String[] indices2 = lineData[2].split("/");
        String[] indices3 = lineData[3].split("/");

        return new Face(materialName, indices1, indices2, indices3);
    }
    
    private static void decodeNormals(Vector3f vertex, Mesh mesh) {
        int vertexPointer = (int) vertex.x - 1;
        mesh.indices.add(vertexPointer);
        Normal normal = mesh.normals.get((int) vertex.z - 1);
        mesh.normalArray[vertexPointer * 3] = normal.getNormal().x;
        mesh.normalArray[vertexPointer * 3 + 1] = normal.getNormal().y;
        mesh.normalArray[vertexPointer * 3 + 2] = normal.getNormal().z;
    }

}

I am getting this NullPointerException

Couldn't get reader for /res/meshes/Crate1.obj
java.lang.NullPointerException
    at java.base/java.io.Reader.<init>(Reader.java:167)
    at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72)
    at com.darkerminecraft.utils.MyFile.getReader(MyFile.java:59)
    at com.darkerminecraft.graphics.mesh.MeshLoader.load3DModel(MeshLoader.java:22)
    at com.darkerminecraft.Game.main(Game.java:10)
Couldn't get reader for /res/meshes/.mtl
java.lang.NullPointerException
    at java.base/java.io.Reader.<init>(Reader.java:167)
    at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72)
    at com.darkerminecraft.utils.MyFile.getReader(MyFile.java:59)
    at com.darkerminecraft.graphics.mesh.MeshLoader.load3DModel(MeshLoader.java:53)
    at com.darkerminecraft.Game.main(Game.java:10)

Answer

Class, or more accurately java.lang.Class is a system class, which means that Class.class.getResourceAsStream(...) only looks in the system ClassLoader for the resource, i.e. it doesn’t use the ClassLoader that is responsible for the application code and resources.

Change code to MyFile.class.getResourceAsStream(...) or getClass().getResourceAsStream(...)

Leave a Reply

Your email address will not be published. Required fields are marked *