I'm trying to make the program to read QR codes, however when my code runs I am getting an exception javax.imageio.IIOException: Can't read input file. The image is in the src directory. Could someone please help me to find the problem in my code...
public class BarcodeSample {
public static void main(String[] args) {
Reader reader = new MultiFormatReader();
try {
BufferedImage image = ImageIO.read(new File("src/img.png"));
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = reader.decode(bitmap);
BarcodeFormat format = result.getBarcodeFormat();
String text = result.getText();
ResultPoint[] points = result.getResultPoints();
for (int i=0; i < points.length; i++) {
System.out.println(" Point[" + i + "] = " + points[i]);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
First, use File.separator instead of '/' as it places the right separator according to the OS it is running on.
Now the problem is with src/img.png. I suggest you put your images outside the src directory as this directory is used for code (not a must).
I do not know on which IDE you run it but make sure your workspace current directory is set to your project root directory so src/img.png will be found (assuming src is under you root current directory), otherwise you will get the file not found exception
Related
The below code works when running from my editor but the image fails to load when compiled into a runnable jar file with eclipse.
public static BufferedImage getRandomImage() {
// returns a random image from the Images folder
Random rand = new Random();
URL res = Card.class.getResource("Images"); // located in /src/.../Images
File f = new File(res.getFile());
if (!f.exists()) {
return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
}
File[] files = f.listFiles();
int random = rand.nextInt(files.length);
BufferedImage img = null;
try {
img = ImageIO.read(files[random]);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
Could someone please suggest how I can modify my code or editor to load the files when compiled.
I have read other methods of accessing files but since I need to select randomly from a folder, I need to use the File class.
There is no safe way to list resources at runtime.
(Some people may suggest approaches which work sometimes, but will not work all the time. Class.getResource is not guaranteed to provide a listing; ProtectionDomain.getCodeSource can return null.)
But you don’t need to. It’s your application; you already know what files you put into it.
The best way is to either hard-code the list of files, or include a simple text file that contains a list of the files.
As an example, assume you created (or generated) a file named image-files.txt in which each line contains the base name of an image file, and embedded that file in your application:
List<String> imageNames;
try (BufferedReader linesReader = new BufferedReader(
new InputStreamReader(
Card.class.getResourceAsStream("image-files.txt"),
StandardCharsets.UTF_8));
Stream<String> lines = linesReader.lines()) {
imageNames = lines.collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
int random = rand.nextInt(imageNames.length());
String imageName = imageNames.get(random)));
BufferedImage img;
try {
img = ImageIO.read(Card.class.getResource(imageName));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return img;
Note: The getFile() method of URL does not return a valid filename. It only returns the path portion of a URL. There are many characters which would be illegal in URLs, so the path portion percent-escapes them. If you ignore this fact, the value returned by getFile() will eventually fail.
(The reason for the misleading method name is that the URL class was part of Java 1.0, and in the mid-1990s, all URLs actually referred to physical files.)
I need to use the File class
Each .jar entry is just a subsequence of compressed bytes within a single .jar file, so you will never be able to use File to read such an entry. Class.getResource and Class.getResourceAsStream are the only correct ways to read those entries.
The problem is that you are trying to access a URL of a resource as a file.
with this you can get all the images, and then you can do this:
List<String> arr = getResourceFiles("Images");
String imgPath = arr.get(rand.nextInt(arr.size()));
InputStream stream = Card.class.getResourceAsStream("Images/" + imgPath);
try {
img = ImageIO.read(stream);
} catch (IOException e) {
e.printStackTrace();
}
return img;
I am attempting to copy a file from inside my JAR to disk, outside the JAR file. The files that I will need to copy are default configuration files for a large-scale accounting system and are needed on the computer file system.
I have searched StackOverflow, as well as other sites (found with Google) and have read around fifty answers, which I've tried all of them. The code below is the first that has not simply blown up (with NullPointerException or FileNotFoundException), but has actually attempted to get the resource located in the JAR file.
I have my JAR file set up as follows:
com.is2300.isis
MainClass.java (actual name is crazy long and I don't want to type it out right now)
com.is2300.isis.resources
Location of the resource file I would like to copy out to disk
com.is2300.isis.utils
Location of my class ResourceExporter (below - bottom) that has the file exporting methods.
My MainClass.main() entry-point function:
public static void main(String[] args) {
// Test our 'utils.ResourceExporter.exportResource(String resourceName)
//+ function.
// Set the start point of our substring to either 5 or 9, depending upon
//+ if we are debugging (in NetBeans) or not (executing the JAR).
if ( isDebugging ) {
startPoint = 5;
} else {
startPoint = 9;
}
// First, we'll try just the name of the resource file to export.
String rsName = "nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Then, we'll try it with the absolute path.
rsName = "/com/is2300/isis/resources/nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Then, we'll try it with the relative path.
rsName = "../resources/nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
// Last, we'll try it using dots instead of slashes.
rsName = "com.is2300.isis.resources.nwind.conf";
try {
System.out.println(ResourceExporter.exportResource(rsName,
MainClass.class, "/home/user/tmp", startPoint));
} catch (Exception ex) {
System.err.println(ex.getCause());
System.err.println(ex.getMessage());
ex.printStackTrace(System.err);
}
}
My ResourceExporter.exportResource() method:
public static String exportResource(String resourceName, Class cls,
String outPath, int startPoint) throws Exception {
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
InputStream in = new FileInputStream(files);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
int readBytes;
byte[] buffer = new byte[4096];
while ( (readBytes = in.read(buffer)) > 0 )
out.write(buffer, 0, readBytes);
in.close();
out.close();
return files.getAbsolutePath();
}
With what I'm doing in public static void main(String[] args), I would expect one of the calls to the ResourceExporter.exportResource() method to actually cause the file to be copied.
However, when I step through the exportResource() method, on each call after the line:
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
The variable files.getCanonicalPath() call shows /home/user/Projects/ProjectName/nullfiles and I do not understand why this is, nor what this is.
#JBNizet and #AndrewThompson:
Thank you both for your comments. Especially #JBNizet! You gave me a swift kick in the head that made me look closer at what I had written and immediately saw the issue. Thank you very much for that.
The fix was this: Instead of the convoluted thing I was doing:
File files = new File(cls.getResource(
cls.getResource(cls.getSimpleName() +
".class").toString().substring(
startPoint, cls.getResource(
cls.getSimpleName() + ".class").toString().lastIndexOf("/")
+ 1)) + "files");
InputStream in = new FileInputStream(files);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
Which I had written about 10 years ago and don't remember what I was thinking, I was able to simplify it to this:
InputStream in = ClassLoader.getSystemClassLoader().getSystemResourceAsStream(resourceName);
FileOutputStream out = new FileOutputStream(outPath +
resourceName.substring(resourceName.lastIndexOf("/")));
Now, the "file" (as a nod to the semantic correction by #AndrewThompson) is being located within the JAR file.
However, that was not the only change that had to be made. Where I set up the variable that is passed into the parameter resourceName was also not correct. I had it set up like so:
String rsName = "/com/is2300/isis/resources/nwind.conf";
However, the leading slash (/) was not supposed to be there. As soon as I changed the above line to:
String rsName = "com/is2300/isis/resources/nwind.conf";
everything just worked the way I expected.
Again, thanks to those two who commented. I appreciate your thoughts and assistance in getting my brain engaged.
Although there are many questions here that involve errors with naming files, the code below tries to implement those examples but fails to actually change the name of the file in the system for no apparent reason.
public static void main(String[] args)
{
File dir = new File("E:/Vglut2 pharmacology/60730/");
File[] directoryListing = dir.listFiles();
for (File filius : directoryListing) {
try
{
String oldName = filius.getName();
int imgNum = returnImageNumber(oldName);
double imgMag = returnImageMagnification(oldName);
String newName = oldName.substring(0, oldName.indexOf('_')).concat('_' + String.valueOf(imgNum)).concat('_' + String.valueOf(imgMag));
File nova = new File(newName);
filius.renameTo(nova);
System.out.println(newName);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The resulting string that I tested by printing offers the desired resulting final name, however, in the end, the filesystem remains unchanged. A similar example from a previous stack overflow question is as seen below-
File dir = new File("D:/xyz");
if (dir.isDirectory()) { // make sure it's a directory
for (final File f : dir.listFiles()) {
try {
File newfile =new File("newfile.txt");
if(f.renameTo(newfile)){
System.out.println("Rename succesful");
}else{
System.out.println("Rename failed");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
As seen there are no significant differences that I can tell which would affect the viability of this process. Note I am running Windows 10 Home edition as an admin if this is related. Thanks for the help.
filius.getName() only gets the last part of the files path. renameTo on the other hand needs the full path. So in fact you end up trying to move your file into a different directory.
Use:
File nova = new File(dir, newName);
in order to rename the file in the original directory.
I have a .jar that has two .dll files that it is dependent on. I would like to know if there is any way for me to copy these files from within the .jar to a users temp folder at runtime. here is the current code that I have (edited to just one .dll load to reduce question size):
public String tempDir = System.getProperty("java.io.tmpdir");
public String workingDir = dllInstall.class.getProtectionDomain().getCodeSource().getLocation().getPath();
public boolean installDLL() throws UnsupportedEncodingException {
try {
String decodedPath = URLDecoder.decode(workingDir, "UTF-8");
InputStream fileInStream = null;
OutputStream fileOutStream = null;
File fileIn = new File(decodedPath + "\\loadAtRuntime.dll");
File fileOut = new File(tempDir + "loadAtRuntime.dll");
fileInStream = new FileInputStream(fileIn);
fileOutStream = new FileOutputStream(fileOut);
byte[] bufferJNI = new byte[8192000013370000];
int lengthFileIn;
while ((lengthFileIn = fileInStream.read(bufferJNI)) > 0) {
fileOutStream.write(bufferJNI, 0, lengthFileIn);
}
//close all steams
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (UnsupportedEncodingException e) {
System.out.println(e);
return false;
}
My main problem is getting the .dll files out of the jar at runtime. Any way to retrieve the path from within the .jar would be helpful.
Thanks in advance.
Since your dlls are bundeled inside your jar file you could just try to acasses them as resources using ClassLoader#getResourceAsStream and write them as binary files any where you want on the hard drive.
Here is some sample code:
InputStream ddlStream = <SomeClassInsideTheSameJar>.class
.getClassLoader().getResourceAsStream("some/pack/age/somelib.dll");
try (FileOutputStream fos = new FileOutputStream("somelib.dll");){
byte[] buf = new byte[2048];
int r;
while(-1 != (r = ddlStream.read(buf))) {
fos.write(buf, 0, r);
}
}
The code above will extract the dll located in the package some.pack.age to the current working directory.
Use a class loader that is able to locate resources in this JAR file. Either you can use the class loader of a class as Peter Lawrey suggested, or you can also create a URLClassLoader with the URL to that JAR.
Once you have that class loader you can retrieve a byte input stream with ClassLoader.getResourceAsStream. On the other hand you just create a FileOutputStream for the file you want to create.
The last step then is to copy all bytes from the input stream to the output stream, as you already did in your code example.
Use myClass.getClassLoader().getResourceAsStream("loadAtRuntime.dll"); and you will be able to find and copy DLLs in the JAR. You should pick a class which will also be in the same JAR.
I'm new here and kinda new to java.
I've encountered a problem.
I have a very simple program that tries to create pngs and save them in a user selected folder.
byteimage is a a private byte[]:
byteimage = bcd.createPNG(300, 140, ColorSpace.TYPE_RGB, Color.BLACK, Color.BLACK);
setPath() is called inside the action listener of the browse button
private void setPath() {
JFileChooser pathchooser = new JFileChooser();
pathchooser.setMultiSelectionEnabled(false);
pathchooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
pathchooser.setApproveButtonMnemonic(KeyEvent.VK_ENTER);
pathchooser.showDialog(this, "OK");
File f = pathchooser.getSelectedFile();
if (f != null) {
filepath = f.getAbsolutePath();
pathfield.setText(filepath);
}
}
Byte to png method looks like this:
public void byteToPNG(String filename) {
try {
InputStream in = new ByteArrayInputStream(byteimage);
BufferedImage bufferedimg = ImageIO.read(in);
ImageIO.write(bufferedimg, "png", new File(filename));
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
This method is called like this:
byteToPNG(pathfield.getText() + System.getProperty("file.separator") + textfield.getText() + ".png");
textfield.getText() sets the actual name of the png.
Inside the constructor, default filepath is set:
filepath = System.getProperty("user.dir");
pathfield.setText(filepath);
The code runs fine from Eclipse and it produces a png image at the desired location.
Unfortunately, after exporting as jar, it starts but when the button for generating the png is pressed, nothing happens. I'm thinking there's a problem at InputStream or BufferedImage, but I'm a bit puzzled.
If the String fileName passed to byteToPNG isn't absolute (i.e. written in the form "C:/foo/bar/etc") that could be the cause of the broken jar. You could also try running the jar file in the terminal using the command:
java -jar myJarFile.jar.
This will cause a console window to remain open alongside your running jar application in which all your applications output (including any exceptions) will be printed.