Angus Moore
Angus Moore

Reputation: 4191

Java IO can't read input file?

I have just started learning java and I've been working on this code for a moving object with keyboard input. I am now trying to add in a background, but it keeps erroring with:

javax.imageio.IIOException: Can't read input file!
    at javax.imageio.ImageIO.read(Unknown Source)
    at game.GameLoop.run(GameLoop.java:24)
    at java.lang.Thread.run(Unknown Source)

The code I have in Game.java is:

package game;

import java.applet.*;
import java.awt.*;

public class Game extends GameLoop{

    public void init(){
        setSize(864,480);
        Thread th = new Thread(this);
        th.start();
        offscreen = createImage(864,480);
        d = offscreen.getGraphics();
        addKeyListener(this);
    }

    public void paint(Graphics g){
        d.clearRect(0, 0, 864, 480);
        d.drawImage(background, 0, 0, this);
        d.drawRect(x, y, 20, 20);
        g.drawImage(offscreen, 0, 0, this);
    }

    public void update(Graphics g){
        paint(g);
    }
}

And here is my GameLoop.java:

package game;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class GameLoop extends Applet implements Runnable, KeyListener{

    public int x, y;
    public Image offscreen;
    public Graphics d;
    public boolean up, down, left, right;
    public BufferedImage background;

    public void run(){
        x = 100;
        y = 100;
        try {
            background = ImageIO.read(new File("background.png"));
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        while(true){
            x = 100;
            y = 100;
            while(true){
                if (left == true){
                    x-=4;
                }
                if (right == true){
                    x+=4;
                }
                if (up == true){
                    y-=4;
                }
                if (down == true){
                    y+=4;
                }
                if ( x <= 0 ){
                    x = 0;
                }
                if ( y <= 0 ){
                    y = 0;
                }
                if ( x >= 843 ){
                    x = 843;
                }
                if ( y >= 460 ){
                    y = 459;
                }
                repaint();
            try{
                Thread.sleep(20);
            } catch(InterruptedException e){
                e.printStackTrace();
            }
            }
        }
    }

    //@Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == 37){
            left = true;
        }
        if(e.getKeyCode() == 38){
            up = true;
        }
        if(e.getKeyCode() == 39){
            right = true;
        }
        if(e.getKeyCode() == 40){
            down = true;
        }
    }

    //@Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == 37){
            left = false;
        }
        if(e.getKeyCode() == 38){
            up = false;
        }
        if(e.getKeyCode() == 39){
            right = false;
        }
        if(e.getKeyCode() == 40){
            down = false;
        }
    }

    //@Override
    public void keyTyped(KeyEvent e) {
    }
}

Sorry about the editing I can't seem to get it all in the ``, and I will also fix the messy code, but do you guys have any ideas what is causing this error, there is a file in the src dir called background.png, it is very basic and made in MS paint, if that helps.

Thanks.

Upvotes: 0

Views: 13448

Answers (2)

konsnos
konsnos

Reputation: 34

@Patricia Shanahan Your comment actually helped me to solve the same problem.

I've used that code:

File here = new File(".");
try {
    System.out.println(here.getCanonicalPath());
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

and from there you can figure out the correct path to use.

Upvotes: 1

Andrew Thompson
Andrew Thompson

Reputation: 168825

There are two places a simple, sand-boxed applet can obtain images.

Where

  1. A loose file on the same server the applet was supplied from. E.G. This might be used for a sand-boxed 'image slideshow' where the image names are supplied in applet parameters.
  2. A Jar on the run-time class-path of the applet. Best for resources which would not typically change (barring localized images, where it becomes more complicated). E.G. This might be used for button/menu icons, or BG images.

"background.png" strongly indicates the 2nd scenario - 'part of the app. itself'.

How to find

Both types of resources should identified by URL (do not try to establish a File as it will fail when the applet is deployed).

The way to obtain an URL for the 2nd case is something along the lines of:

URL urlToBG = this.getClass().getResource("/path/to/the/background.png");

..where /path/to/the/ might simply be /resources/ or /images/. It is the path within a Jar on the classpath, where the image can be found.

How to load

Most methods that will load a File are overloaded to accept an URL. This notably applies to ImageIO.read(URL).

While the Applet class has inbuilt methods to load images, I recommend sticking with ImageIO since it provides more comprehensive feed-back on failure.

Further tips

Tip 1

Thread.sleep(20);

Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n) implement a Swing Timer for repeating tasks or a SwingWorker for long running tasks. See Concurrency in Swing for more details.

Tip 2

It is the third millennium, time to start using Swing instead of AWT. That would mean extending JApplet instead of Applet. Then you might shift the logic of painting into a JPanel that is double-buffered by default, and could be used in either the applet or a frame (or a window or a dialog..).

Tip 3

setSize(864,480);

The size of an applet is set in HTML, and the applet should accept whatever size it is assigned and work within that. Taking that into account, statements like:

d.clearRect(0, 0, 864, 480);

..should read more like:

d.clearRect(0, 0, getWidth(), getHeight());

Upvotes: 4

Related Questions