jpgs save in linux, but 0 byte files on Windows
Hi All,
Part of an open source project I'm involved with uses some code to save thumbnail and small version images of an original jpg file. This works fine on Linux but when run on Windows the images that are created are 0 byte files, the names etc are all fine, just no image in the file.
Before I post any code, any ideas on why this would occur?
Thanks
[381 byte] By [
ipv6gurua] at [2007-11-27 4:04:23]

> Before I post any code, any ideas on why this would occur?
The traditional culprit, before you post any code, is line 42.
Could be on Windows you squash an exception after you create the file but before
you close/flush the stream writing to it. Could be anything.
Do post a small example that compiles and demonstrates the problem.
do you properly close the FileOutputStream instance?
... did you properly close the outermost output stream? e.g. a BufferedOutputStream?
ejpa at 2007-7-12 9:09:15 >

@ejp : did you see my answer ?!! :)
> @ejp : did you see my answer ?!! :)And did you see the subtle difference between yours and his? :-)
> The traditional culprit, before you post any code, is
> line 42.
:)
>
> Could be on Windows you squash an exception after you
> create the file but before
> you close/flush the stream writing to it. Could be
> anything.
True, sometimes you geniuses can point out an error merely by what the event is doing ;)
>
> Do post a small example that compiles and
> demonstrates the problem.
At the moment, I can post a snippet of the .java file that writes the thumbnails.
BufferedImage thumbBuffer = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
URI fUri = new URI(fName);
String persistentFilePath = persistentStoreLocation + fUri.getPath().substring(0, fUri.getPath().lastIndexOf("/"));
File persistentFileDir = new File(persistentFilePath);
persistentFileDir.mkdirs();
String persistentFilename = fUri.getPath().substring(fUri.getPath().lastIndexOf("/"));
File persistentImgFile = new File(persistentFilePath + persistentFilename);
if (persistentImgFile.exists() == false) {
persistentImgFile.createNewFile();
}
ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName("JPEG").next();
ImageWriteParam wp = writer.getDefaultWriteParam();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(persistentImgFile);
IIOImage imgImage = new IIOImage(thumbBuffer, null, null);
writer.setOutput(imgOut);
writer.write(null,imgImage,wp);
currentImage = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
}
if (null != grayscaleFilter) {
grayscaleFilter.filter(currentImage, currentImage);
}
if (null != colorFilter) {
colorFilter.filter(currentImage, currentImage);
}
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
p.setQuality(this.quality[0], true);
encoder.setJPEGEncodeParam(p);
encoder.encode(currentImage);
out.flush();
} catch (java.net.URISyntaxException e) {
throw new ProcessingException("error message "+ fName ,e);
} catch (ImageFormatException e) {
throw new ProcessingException("error message.");
} finally {
inputStream.close();
}
} else {
...
@everyone
There is a theme in some of the answers here that the culprit is probably not closing things properly, hopefully the code snippet will help.
A newbie question then, would the not closing of streams etc properly make this sort of scenario, where it still works fine on linux but not on windows?
FileOutPutStream is not used, but ImageOutputStream is, is there any advantage of one over the other when saving images, or ImageOutputStream must be used in this case.?
oh, forgot to say, thanks all for your quick responses, much appreciated.
forgot to say 2 - this is not my code, merely taking a look to try and see what I can find and help out the project , not alot so far hence coming to you guys .
ImageOutputStream imgOut=null;
try{
BufferedImage thumbBuffer = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
URI fUri = new URI(fName);
String persistentFilePath = persistentStoreLocation + fUri.getPath().substring(0, fUri.getPath().lastIndexOf("/"));
File persistentFileDir = new File(persistentFilePath);
persistentFileDir.mkdirs();
String persistentFilename = fUri.getPath().substring(fUri.getPath().lastIndexOf("/"));
File persistentImgFile = new File(persistentFilePath + persistentFilename);
if (persistentImgFile.exists() == false) {
persistentImgFile.createNewFile();
}
ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName("JPEG").next();
ImageWriteParam wp = writer.getDefaultWriteParam();
imgOut = ImageIO.createImageOutputStream(persistentImgFile);//CHANGE HERE
IIOImage imgImage = new IIOImage(thumbBuffer, null, null);
writer.setOutput(imgOut);
writer.write(null,imgImage,wp);
currentImage = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
}
if (null != grayscaleFilter) {
grayscaleFilter.filter(currentImage, currentImage);
}
if (null != colorFilter) {
colorFilter.filter(currentImage, currentImage);
}
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
p.setQuality(this.quality[0], true);
encoder.setJPEGEncodeParam(p);
encoder.encode(currentImage);
out.flush();
} catch (java.net.URISyntaxException e) {
throw new ProcessingException("error message "+ fName ,e);
} catch (ImageFormatException e) {
throw new ProcessingException("error message.");
} finally {
////////////////////////CHANGES HERE
try {
if(inputStream!=null){
inputStream.close();
}
} catch (Exception e) {
//TODO: handle exception
}
try {
if(out!=null)
out.close();
} catch (Exception e) {
// TODO: handle exception
}
try {
if(imgOut!=null)
imgOut.close();
} catch (Exception e) {
// TODO: handle exception
}
}
} else {
@georgemc : I told u many times to fuc_k your self!!
> @georgemc : I told u many times to fuc_k your self!!Have you? I never noticed. Anyways, no, I don't think I will, thanks all the same. Perhaps you ought to put a bit more thought into your posts if you don't like being picked up on mistakes. Simple enough, really
That looks good, thanks, I'll give it a whirl and let you know how I go.
> @ejp : did you see my answer ?!! :)Yes I did see your answer and it is obvious from your subsequent code that you didn't see my question. Try again.
ejpa at 2007-7-12 9:09:15 >

> A newbie question then, would the not closing of
> streams etc properly make this sort of scenario,
> where it still works fine on linux but not on
> windows?
You should always close streams/writers in a finally block. It's certainly possible, however, that your file system on linux is flushing things for you. There's no requirement the the FS *not* flush to disk if you don't tell it to, only that it does when you do tell it.
After adding in the above code, I now get error messages such asjava.io.IOException: No outputstream available!The jpegs are still created at 0 bytes, then this error message, so I guess it can't write to the file after it has successfully created it?
add this to all catch blocks :e.printStackTrace();then post the whole error message.
See replies 3, 5, and 11.
ejpa at 2007-7-21 21:01:51 >

Thanks for the reply, I did that. Full traces may be suppressed in the output I get due to cocoon, here is what I have :-
java.io.IOException: No outputstream available!
at org.apache.cocoon.bean.helpers.DelayedOutputStream.getTargetOutputStr
eam(DelayedOutputStream.java:213)
at org.apache.cocoon.bean.helpers.DelayedOutputStream.flush(DelayedOutpu
tStream.java:159)
X [0] gallery/demo/B_023_2A.thumb.jpg
BROKEN: URI not found: No outputstream available!
at org.apache.cocoon.util.BufferedOutputStream.realFlush(BufferedOutputS
tream.java:128)
at org.apache.cocoon.environment.AbstractEnvironment.commitResponse(Abst
ractEnvironment.java:270)
at org.apache.cocoon.Cocoon.process(Cocoon.java:568)
at org.apache.cocoon.bean.CocoonWrapper.getPage(CocoonWrapper.java:426)
at org.apache.cocoon.bean.CocoonBean.processTarget(CocoonBean.java:496)
at org.apache.cocoon.bean.CocoonBean.process(CocoonBean.java:357)
at org.apache.cocoon.Main.main(Main.java:311)
* [45/48][0/0]0.484s 0bgallery/demo/B_007_18A.thumb.jpg
java.io.IOException: No outputstream available!
at org.apache.cocoon.bean.helpers.DelayedOutputStream.getTargetOutputStr
eam(DelayedOutputStream.java:213)
at org.apache.cocoon.bean.helpers.DelayedOutputStream.flush(DelayedOutpu
tStream.java:159)
X [0] gallery/demo/B_007_18A.thumb.jpg
BROKEN: URI not found: No outputstream available!
at org.apache.cocoon.util.BufferedOutputStream.realFlush(BufferedOutputS
tream.java:128)
at org.apache.cocoon.environment.AbstractEnvironment.commitResponse(Abst
ractEnvironment.java:270)
at org.apache.cocoon.Cocoon.process(Cocoon.java:568)
at org.apache.cocoon.bean.CocoonWrapper.getPage(CocoonWrapper.java:426)
at org.apache.cocoon.bean.CocoonBean.processTarget(CocoonBean.java:496)
at org.apache.cocoon.bean.CocoonBean.process(CocoonBean.java:357)
at org.apache.cocoon.Main.main(Main.java:311)
* [46/52][5/40]0.328s 8.2Kbgallery/demo/pic_6.html
* [47/51][0/0]0.375s 0bgallery/demo/B_023_2A.small.jpg
java.io.IOException: No outputstream available!
at org.apache.cocoon.bean.helpers.DelayedOutputStream.getTargetOutputStr
eam(DelayedOutputStream.java:213)
at org.apache.cocoon.bean.helpers.DelayedOutputStream.flush(DelayedOutpu
tStream.java:159)
X [0] gallery/demo/B_023_2A.small.jpg
BROKEN: URI not found: No outputstream available!
at org.apache.cocoon.util.BufferedOutputStream.realFlush(BufferedOutputS
tream.java:128)
at org.apache.cocoon.environment.AbstractEnvironment.commitResponse(Abst
ractEnvironment.java:270)
at org.apache.cocoon.Cocoon.process(Cocoon.java:568)
at org.apache.cocoon.bean.CocoonWrapper.getPage(CocoonWrapper.java:426)
at org.apache.cocoon.bean.CocoonBean.processTarget(CocoonBean.java:496)
at org.apache.cocoon.bean.CocoonBean.process(CocoonBean.java:357)
at org.apache.cocoon.Main.main(Main.java:311)
not sure if that helps any, remember we are trying to narrow down a windows only problem, as the code does work well on linux systems.
Thanks
see last line http://mail-archives.apache.org/mod_mbox/cocoon-cvs/200306.mbox/%3C20030604092553.75582.qmail@icarus.apache.org%3E
ok thanks, maybe should I be now moving on to the coccon lists to resolve this (seeing as the app is cocoon based) ? I was hoping it was a generic java issue that could be solved here.In other words I have no idea how to inteprete the link you gave and how to solve it.Thanks
OK,OK, the problem is right here:
try {
if(out!=null)
out.close();
} catch (Exception e) {
// TODO: handle exception
}
try {
if(imgOut!=null)
imgOut.close();
The first close is of the 'inner' output stream so the outer output stream which is closed later has nowhere to write its final flush(). Inner streams should never be closed at all, whether input or output streams.
ejpa at 2007-7-21 21:01:51 >

Thanks ejp, I realise this is what you were getting at.
A couple of things, the code you say where the problem lies is from code suggested here, it was not in the original code. The sentiment remains the same though and I appreciate that and am trying hard to solve it, seems simple in principle but it is just not happening for me.
that try block that contains the imgOut.close for example does not work, imgClose can not be resolved, I'm guessing because that whole image writing
code segment is inside an if block which is inside of its own try block.
I am reluctant to re-organise all of this due the fact it works properly (on the surface) in linux.
I will mess with it some more before I come crawling back I guess .
Thanks for the pointers. I've awarded some points for the first code effort posted in this thread, more to come when I finally get it resolved correctly.
> I am reluctant to re-organise all of this due the
> fact it works properly (on the surface) in linux.
I would be much more reluctant *not* to because of the fact that it clearly *doesn't* work in Windows. :-)
Seriously, he's pointed out exactly what you're doing wrong--and it *is* wrong--so the fact that it happens not to be causing problems in one environment is irrelevant, wouldn't you say?
jverda at 2007-7-21 21:01:51 >

> I am reluctant to re-organise all of this due the
> fact it works properly (on the surface) in linux.
You have no choice. You must reorganize it, because it doesn't work. Just 'playing' with it is how you got into this mess. There are only about 20 lines of code involved: don't make a drama out of nothing.
ejpa at 2007-7-21 21:01:51 >

Hi Jeff, Yes I can see how you can see where it is *exactly* but I can not, he pointed out where the error lies from code suggested here, it was not in the original code, I've been trying for days now and either keep getting 0 byte files, or errors.
Here is the whole of that class as I have it now, it may reveal something else I'm doing wrong.
protected void processStream(InputStream inputStream) throws IOException, ProcessingException {
if (hasTransform()) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("image " + ((width == 0) ? "?" : Integer.toString(width))
+ "x"+ ((height == 0) ? "?" : Integer.toString(height))
+ " expires: " + expires);
}
String fName = super.inputSource.getURI();
fName = fName.replaceFirst(".jpg","." + this.variant + ".jpg");
try {
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(inputStream);
BufferedImage original = decoder.decodeAsBufferedImage();
BufferedImage currentImage = original;
if (width > 0 || height > 0) {
JPEGDecodeParam decodeParam = decoder.getJPEGDecodeParam();
double ow = decodeParam.getWidth();
double oh = decodeParam.getHeight();
if (usePercent) {
if (width > 0) {
width = Math.round((int)(ow * width) / 100);
}
if (height > 0) {
height = Math.round((int)(oh * height) / 100);
}
} // :END if (usePercent)
AffineTransformOp filter = new AffineTransformOp(getTransform(ow, oh, width, height), AffineTransformOp.TYPE_BILINEAR);
WritableRaster scaledRaster = filter.createCompatibleDestRaster(currentImage.getRaster());
filter.filter(currentImage.getRaster(), scaledRaster);
//write the thumbnail.
BufferedImage thumbBuffer = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
URI fUri = new URI(fName);
String persistentFilePath = persistentStoreLocation + fUri.getPath().substring(0, fUri.getPath().lastIndexOf("/"));
File persistentFileDir = new File(persistentFilePath);
persistentFileDir.mkdirs();
String persistentFilename = fUri.getPath().substring(fUri.getPath().lastIndexOf("/"));
File persistentImgFile = new File(persistentFilePath + persistentFilename);
if (persistentImgFile.exists() == false) {
persistentImgFile.createNewFile();
}
ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName("JPEG").next();
ImageWriteParam wp = writer.getDefaultWriteParam();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(persistentImgFile);
IIOImage imgImage = new IIOImage(thumbBuffer, null, null);
writer.setOutput(imgOut);
writer.write(null,imgImage,wp);
currentImage = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
} // :END if (width > 0 || height > 0)
if (null != grayscaleFilter) {
grayscaleFilter.filter(currentImage, currentImage);
}
if (null != colorFilter) {
colorFilter.filter(currentImage, currentImage);
}
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
p.setQuality(this.quality[0], true);
encoder.setJPEGEncodeParam(p);
encoder.encode(currentImage);
} //:END try
catch (java.net.URISyntaxException e) {
throw new ProcessingException("Error creating persistent file for transformed version of "+ fName ,e);
} catch (ImageFormatException e) {
throw new ProcessingException("Error reading the image. " +
"Note that only JPEG images are currently supported.");
} finally {
// Bugzilla Bug 25069, close inputStream in finally block
// this will close inputStream even if processStream throws
// an exception
out.close();
//inputStream.close();
} //:END finally
} //:END if (hasTransform())
else {
// only read the resource - no modifications requested
if (getLogger().isDebugEnabled()) {
getLogger().debug("passing original resource");
} // :END if
super.processStream(inputStream);
}// :END else
} // :END protected void processStream
Putting imgOut.close(); into that finally block doesn't work, it cannot be resolved, that finally block is for the try higher up the chain.
I've tryed all sorts of refactoring but just keep bu&&ering it up.
Can you see anything else that might be causing me problems now there is more code to look at?
Thanks. and apologies for being thick, I am new at this.
Blimey.
ImageOutputStream imgOut = ImageIO.createImageOutputStream(persistentImgFile);
IIOImage imgImage = new IIOImage(thumbBuffer, null, null);
writer.setOutput(imgOut);
writer.write(null,imgImage,wp);
imgOut.close();// <================
ejpa at 2007-7-21 21:01:51 >

Well, I'm guessing 'Blimey' means you are losing patience,. I don't blame you, however that really was one of the first things I tried , it made no difference, so I removed it. I have put it back now and still get 0 byte files.
Other things I have tried :-
putting in or removing out.close();
or out.flush();
just before the } catch (java.net.URISyntaxException e) {
makes no difference.
putting in or removing inputStream.close();
in the finally block makes no difference.
I'll keep looking, thanks for your efforts, point are yours anyway.
Message was edited by:
ipv6guru
> > I am reluctant to re-organise all of this due the
> > fact it works properly (on the surface) in linux.
>
> You have no choice. You must reorganize it,
> because it doesn't work. Just 'playing' with it is
> how you got into this mess. There are only about 20
> lines of code involved: don't make a drama out of
> nothing.
Sorry, I missed this post, trust me, I AM taking another fresh look at it.