I have a class thats responsible for animating some images. I have 3 player classes that each create their own instance of this animation class. Each player class sends a String path and a String array of file names to my animation class. So what im doing is checking if the String array of file names starts with up, down, left or right. I then add them to an array of buffered images, 4 in total named up, down, left and right.
Now when the player wants to move left for example, the left[] will animate, same goes for the up direction etc. The problem is that only one image gets stored in each array. For example the up[] of buffered images holds only one image for up, while their should be 3 (there are 3 images for each direction). I cant figure it out.
The following code is taken from my Animation class that processes the arrays. Can someone tell me if I am missing something?
If this made absolutely no sense, my apologies :)...it sounded good in my head
thanks
try
{
for (String file : fileName)
{
String path = PATH + file + EXT;
for (int i = 0; i < arrayLength; i++)
{
if (file.startsWith("u"))
{
up[i] = ImageIO.read(new File(path));
}
if(file.startsWith("d"))
{
down[i] = ImageIO.read(new File(path));
}
if (file.startsWith("l"))
{
left[i] = ImageIO.read(new File(path));
}
if (file.startsWith("r"))
{
right[i] = ImageIO.read(new File(path));
}
}
}
}
catch (IOException e)
{
System.out.println("Could not load images: " + e);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("Array out of bounds: " + e);
}
I'm having some trouble following your description, but looking at your code here are my thoughts on what could potentially be your problem. First unrelated to your problem a coding suggestion, you have mutually exclusive cases (file.startsWith(...)) that you test with ifs, you should have else so that when one tests positive the others can be ignored:
for (String file : fileName) {
String path = PATH + file + EXT;
for (int i = 0; i < arrayLength; i++) {
if (file.startsWith("u")) {
up[i] = ImageIO.read(new File(path));
} else if(file.startsWith("d")) {
down[i] = ImageIO.read(new File(path));
} else if (file.startsWith("l")) {
left[i] = ImageIO.read(new File(path));
} else if (file.startsWith("r")) {
right[i] = ImageIO.read(new File(path));
}
}
}
As for the logic of the code, one potential problem I see is your array index does not seem to be properly linked to the file. As of now your code could be rewritten thusly without changing its effects:
for (String file : fileName) {
String path = PATH + file + EXT;
BufferedImage array = null;
if (file.startsWith("u")) {
array = up;
} else if(file.startsWith("d")) {
array = down;
} else if (file.startsWith("l")) {
array = left;
} else if (file.startsWith("r")) {
array = right;
}
for (int i = 0; i < arrayLength; i++) {
array[i] = ImageIO.read(new File(path));
}
}
You are simply writing a new buffered image with the same path to the entire array (or whatever portion is included by the variable "arrayLength") on each iteration of the outer loop. Because of this if "file" is the same type every time (i.e. startsWith is the same value), your array will only ever contain the last item in the fileName array.
Here is where I will start guessing at your intent. I assume that each String in fileName, is one path that should be then next image in the array of the animation for that particular direction, so what you need is a separate index into each array:
int upArrayIndex = 0, downArrayIndex = 0,
leftArrayIndex = 0, rightArrayIndex = 0;
for (String file : fileName) {
String path = PATH + file + EXT;
if (file.startsWith("u")) {
up[upArrayIndex++] = ImageIO.read(new File(path));
} else if(file.startsWith("d")) {
down[downArrayIndex++] = ImageIO.read(new File(path));
} else if (file.startsWith("l")) {
left[leftArrayIndex++] = ImageIO.read(new File(path));
} else if (file.startsWith("r")) {
right[rightArrayIndex++] = ImageIO.read(new File(path));
}
}
I hope this is on the right track for the question you are asking, or at least gets you an idea where to start.
Here's a non-answer answer. Set a breakpoint in this method with a debugger. Are you running this code in an IDE like Eclipse? Root causing this problem will be much easier when you actually see the execution flow of your program - and its an essential tool for any developer who wants to truly understand some given code. As a side note, I think your problem has to do with arrayLength.
Related
(Hello world level tester here)
I've got a java application to delete a bunch of files post tests to keep everything clean, however the issue is I can't seem to get it to work, this is my first time touching on an array and it's a slightly more complex one than the ones they show in the tutorials, any assistance would be greatly appreciated.
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
File filePath = new File(home+fileArray);
System.out.println(filePath);
for (String count: fileArray) {
if (filePath.exists()) {
filePath.delete();
System.out.println("Deleted");
}
else
{
System.out.println("failed");
Assert.fail();
}
System.out.println(count);
}
You should concat new file path for every element in an array, so need to put work with a file in for body. So in every iteration, you get in variable filePath next element of an array and then you need to concat this variable to base path home + filePath. Now you are looking at needed file, you can create file object and work with it.
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
for (String filePath: fileArray) {
File file = new File(home + filePath);
System.out.println(filePath);
if (file.exists()) {
file.delete();
System.out.println("Deleted");
} else {
System.out.println("failed");
Assert.fail();
}
}
Seem like you expect that in variable count you will see a number of iterated files. In this case, it does not work like this. Such form of for acting like this: for (String arrayElement : arrayToWorkWith) - mean that on every iteration in variable arrayElement will be put next element from array arrayToWorkWith. If you need to count number of element during iterations you can introduce separate variable and increment it or use another form of for cycle - for (int i = 0; i < fileArray.length; i++).
try it this way
String[] fileArray;
fileArray = new String[8];
fileArray[0] = "/Downloads/file1.csv";
fileArray[1] = "/Downloads/file2.csv";
fileArray[2] = "/Downloads/file3.csv";
fileArray[3] = "/Downloads/file4.csv";
fileArray[4] = "/Downloads/file5.csv";
fileArray[5] = "/Downloads/file6.csv";
fileArray[6] = "/Downloads/file7.csv";
fileArray[7] = "/Downloads/file8.csv";
String home = System.getProperty("user.home");
//File filePath = new File(home+fileArray); thats wrong here and will give you a invalid file anyway as you concatenating a string with an object
for (String file: fileArray) {
File filePath = new File(home+file); //here you need to define the file
if (filePath.exists()) {
filePath.delete();
System.out.println("Deleted");
}
else
{
System.out.println("failed");
Assert.fail();
}
System.out.println(file);
}
I'm trying to code something to copy the content of one file into another existent file without deleting its content.
The problem is that, that other existent file is created inside a loop and I don't know how to do it to save it and then using it in another method.
Here's the loop:
if (line.startsWith("tipo1.")) {
FileWriter fw = new FileWriter(name + ".txt");
char[] vector = name.toCharArray();
char[] vector2 = address.toCharArray();
int index = 0;
while (index < vector.length) {
fw.write(vector[index]);
index++;
}
index = 0;
while (index < vector2.length) {
fw.write(vector2[index]);
index++;
}
fw.close();
}
And what I want to do is to save (name + ".txt") file and then adding the content of another file into it.
I'm sure it's not so difficult to do, but I'm really stuck.
You already have two separate pieces of information being written into the file: the name (as vector) and the address (as vector2). Why not just read in your other file as, say, vector3 and add one more while loop?
If you want this done the easy way then use Apache IO, and use: File ip = new File("input.txt"); File op = new File("output.txt"); FileUtils.copyFile(ip, op);
FileReader ip = new FileReader("input.txt");
FileWriter op = new FileWriter("output.txt", true);
int c;
while (true) {
c = ip.read();
if (c == -1) {
break;
}
op.write((char)c);
}
ip.close();
op.close();
I have read many other questions and resources regarding this issue and am still getting nowhere. I asked a question about this the other day and was referred to the other questions again. Maybe I am just not getting it but I have been trying to getResourceAsStream for my java project for 2 days so I can get the jar to work to no avail.
I have two places in my project causing issues. My buffered image class:
public static BufferedImage loadImage(String fileName) {
try {
File file = new File(fileName);
//System.out.println("Is the file there for " + fileName + " : " + file.exists());
BufferedImage sub = ImageIO.read(file);
return toCompatibleImage(sub);
}
catch (IOException e) {
System.out.println("Image load failed: " +fileName);
// e.printStackTrace();
return null;
}
}
My GifHandler class:
public enum GifHandler {
Mouse("Resources/Images/cursor/", ".gif", 45, 45),
Coaster("Resources/Images/animatedCoaster/", ".gif", Carnies.PWIDTH, Carnies.PHEIGHT/2),
Fire("Resources/Images/fire/", ".gif", 100, 100);
public BufferedImage[] sequence;
int playing = 0;
GifHandler(String dir_name, String type, int width, int height) {
int numImgs = new File(dir_name).list().length;
if (sequence == null) {
sequence = new BufferedImage[numImgs];
for (int i = 0; i < numImgs; i++) {
sequence[i] = ImageLoader.loadScaledImage(dir_name + i + type, width, height, false);
}
}
}
}
I have added the resources folder to my build path libraries. My project file structure is like this:
"Project/src/defaultpackage/classfiles"
"Project/resources/Images/imagefiles"
I want to reference the imagefiles from the classfiles, obviously.
I have tried changing to getResourceAsStream, but always get null on the path.
For example, a change to the imageLoader class as shown, returns null:
String path = ImageLoader.class.getResourceAsStream(fileName).toString();
Where fileName is passed in as "resource/Images/alphabet.png" for example.
I've tried every combination of adding and removing /, only referencing the /alphabet.png without leading folders etc. I am at the end of my rope. Please help out. If I haven't linked enough code for this to make sense, the repo for it is at github.com/madamsmall/carnies
My project file structure is like this: "Project/src/defaultpackage/classfiles" "Project/resources/Images/imagefiles"
When you use getClass().getResourceAsStream(), the program will start it's search from the location of the calling class. So by passing "resource/Images/alphabet.png", you're saying that resources is in classfiles, which it isn't. To fix it, you need to allow the search to be traversed back. You can do that by adding a / to the path. So getClass().getResourceAsStream("/resource/Images/alphabet.png")
Another option is to use the the class loader, which will search from the the root. In that case, you don't need the extra / and your current path would be correct. getClass().getClassLoader().getResourceAsStream("resource/Images/alphabet.png");
Note: getClass() and ImageLoader.class are interchangeable in most cases, in case you're wondering why I used getClass()
UPDATE
Use this example as a test
import java.awt.Image;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageLoader {
public static void main(String[] args) throws IOException {
InputStream is = ImageLoader.class.getResourceAsStream("/resource/images/alphabet.png");
Image image = ImageIO.read(is);
JLabel label = new JLabel(new ImageIcon(image));
JOptionPane.showMessageDialog(null, label);
}
}
UPDATE 2
I just noticed that resource is not in your src which it should be, so when it's built, it gets built into the class path.
UPDATE 3
If you want to get a list of all the file names, you can use this method. Then you can do whatever you want with those file names.
private String[] getFileNames() throws URISyntaxException {
URL url = getClass().getResource("/resources/images/");
File file = new File(url.toURI());
String[] fileNames = file.list();
for (String s : fileNames) {
System.out.println(s);
}
return fileNames;
}
Hi right now I have the following method I am using to read one file at a time in a the same directory as the class that has this method:
private byte[][] getDoubleByteArrayOfFile(String fileName, Region region)
throws IOException
{
BufferedImage image = ImageIO.read(getClass().getResource(fileName));
byte[][] alphaInputData =
new byte[region.getInputXAxisLength()][region.getInputYAxisLength()];
for (int x = 0; x < alphaInputData.length; x++)
{
for (int y = 0; y < alphaInputData[x].length; y++)
{
int color = image.getRGB(x, y);
alphaInputData[x][y] = (byte)(color >> 23);
}
}
return alphaInputData;
}
I was wondering how I can make it so that instead of having "fileName" as a argument I can but a directory name as a argument and then iterate through all of the files within that directory and perform the same operation on it. Thanks!
If you are using Java 7, then you need to take a look at NIO.2.
Specifically, take a look at the Listing a Directory's Contents section.
Path dir = Paths.get("/directory/path");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file: stream) {
getDoubleByteArrayOfFile(file.getFileName(), someRegion);
}
} 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);
}
Here is a quick example that may help:
private ArrayList<byte[][]> getDoubleByteArrayOfDirectory(String dirName,
Region region) throws IOException {
ArrayList<byte[][]> results = new ArrayList<byte[][]>();
File directory = new File(dirName);
if (!directory.isDirectory()) return null //or handle however you wish
for (File file : directory.listFiles()) {
results.add(getDoubleByteArrayOfFile(file.getName()), region);
}
return results;
}
Not exactly what you asked for since it's wrapping your old method rather than re-writing it, but I find it a bit cleaner this way, and leaves you with the option of still processing a single file. Be sure to tweak the return type and how to handle the region based on your actual requirements (hard to tell from the question).
It is rather simple, using the File#listFiles() which returns a list of files in the specified File, which must be a directory. To make sure that the File is a directory, simply use File#isDirectory(). The problem occurs where you decide how to return the byte buffer. Since the method returns a 2d buffer, it is necessary to use a 3d byte buffer array, or in this case a List seems to me like the best choice since an unknown number of files will exist in the directory in question.
private List getDoubleByteArrayOfDirectory(String directory, Region region) throws IOException {
File directoryFile = new File(directory);
if(!directoryFile.isDirectory()) {
throw new IllegalArgumentException("path must be a directory");
}
List results = new ArrayList();
for(File temp : directoryFile.listFiles()) {
if(temp.isDirectory()) {
results.addAll(getDoubleByteArrayOfDirectory(temp.getPath(), region));
}else {
results.add(getDoubleByteArrayOfFile(temp.getPath(), region));
}
}
return results;
}
You can, see the list and listFiles documentation for how to do this.
We can use recursion to process a directory with subdirectories also. Here I am deleting file one by one, you can call any other function to process it.
public static void recursiveProcess(File file) {
//to end the recursive loop
if (!file.exists())
return;
//if directory, go inside and call recursively
if (file.isDirectory()) {
for (File f : file.listFiles()) {
//call recursively
recursiveProcess(f);
}
}
//call processing function, for example here I am deleting
file.delete();
System.out.println("Deleted (Processed) file/folder: "+file.getAbsolutePath());
}
How to resolve this error ? I couldn't find solution using different paths, even manually. Please explain how to read an image into the buffered image using absolute path.
private BufferedImage[] image = new BufferedImage[9];
private int imageNo = 0;
private Boolean draw = false;
private int drawType;
private String [] realtivePath;
private String [] absolutePath;
//=============================================================================
public DrawPanel() {
int i,j;
absolutePath = new String[9];
realtivePath = new String []{"B_Pictures\\Burj Khalifa.jpg", "B_Pictures\\Taipei 101.jpg", "B_Pictures\\Willis Tower.jpg",
"B_Pictures\\Empire State Building.jpg", "B_Pictures\\Chrysler Building.jpg",
"B_Pictures\\Woolworth Building.jpg", "B_Pictures\\Met Life Tower.jpg",
"B_Pictures\\Singer Building.jpg", "B_Pictures\\Philadelphia City Hall.jpg"};
//======================================================================
for(i = 0;i < 9; i++)
{
absolutePath[i] = new File(realtivePath[i]).getAbsolutePath();
System.out.println("Path is: "+absolutePath[i]);
}
//=======================================================================
try {
for (j = 0; j < 9; j++) {
image[j] = ImageIO.read(new File(absolutePath[j])); //<-- can't read absolute path!
}
}catch (IOException e) {
e.printStackTrace();
//System.out.println("Error reading file");
}
obviously your absolute paths are incorrect. you are resolving the relative paths based on the directory in which you are running your java application. apparently those are the wrong relative paths (or you are running the app in a different location than you think you are).
UPDATE:
as a clarification, File.getAbsolutePath() makes a relative path absolute if it is currently relative. this is a purely textual change and does not imply any validity for the resulting absolute path. e.g. if you have a relative path "foo/bar" and you make it absolute based on the current directory "/blah", then your resulting absolute path is "/blah/foo/bar". that does not imply that "/blah/foo/bar" is a valid path.
Here's an easy way to check your code:
System.out.println("Path is: "+absolutePath[i] + ", isReadable " + new File(absolutePath[i]).canRead());