ImageIO Can & #39; t create output stream!
The ImageIO class is often used when java generates verification codes. After a project is deployed on a windows 2008 server today, the Verification Code cannot be flushed. Exceptions can be caught in the background, the bread contains Can't create output stream!
Preliminary investigation
When I started writing this solution, I had not solved the problem.
The project has successfully run many versions and runs OK on windows server 2003. Run on Windows 7.
However, the Verification Code cannot be obtained on windows server 2008, which has aroused my great interest!
The main exception information is as follows:
ERROR 2015-11-25 10:25:44, 061 com. honzh. socket. server. communicate. biz. CodeBiz: Can't create output stream! Javax. imageio. IIOException: Can't create output stream! At javax. imageio. ImageIO. write (Unknown Source) Caused by: javax. imageio. IIOException: Can't create cache file! At javax. imageio. ImageIO. createImageOutputStream (Unknown Source)... 11 moreCaused by: java. io. IOException: the system cannot find the specified path. At java. io. winNTFileSystem. createFileExclusively (Native Method) at java. io. file. checkAndCreate (Unknown Source) at java. io. file. createTempFile0 (Unknown Source) at java. io. file. access $100 (Unknown Source) at java. io. file $1. createTempFile (Unknown Source) at sun. misc. IOUtils. createTempFile (Unknown Source) at javax. imageio. stream. fileCacheImageOutputStream.
(Unknown Source) at com. sun. imageio. spi. OutputStreamImageOutputStreamSpi. createOutputStreamInstance (Unknown Source)... 12 more
Through this exception information, I began to trace the source code, of course, by looking at the source code.
First lookImageIO. writeContent, you can find that the createImageOutputStream throws an IIOException.
public static boolean write(RenderedImage im, String formatName, OutputStream output) throws IOException { if (output == null) { throw new IllegalArgumentException(output == null!); } ImageOutputStream stream = null; try { stream = createImageOutputStream(output); } catch (IOException e) { throw new IIOException(Can't create output stream!, e); } boolean val; try { val = write(im, formatName, stream); } finally { stream.close(); } return val; }
Let's look at the createImageOutputStream method. You can find the createOutputStreamInstance method of the ImageOutputStreamSpi class.
try { return spi.createOutputStreamInstance(output, usecache, getCacheDirectory()); } catch (IOException e) { throw new IIOException(Can't create cache file!, e); }
Then, we locate the createOutputStreamInstance method of OutputStreamImageOutputStreamSpi,OutputStreamImageOutputStreamSpi inherits the ImageOutputStreamSpi class.
public ImageOutputStream createOutputStreamInstance(Object output, boolean useCache, File cacheDir) throws IOException { if (output instanceof OutputStream) { OutputStream os = (OutputStream)output; if (useCache) { return new FileCacheImageOutputStream(os, cacheDir); } else { return new MemoryCacheImageOutputStream(os); } } else { throw new IllegalArgumentException(); } }
OK, the key point is coming. Let's continue digging until it reachesFileCacheImageOutputStream Constructor.
public FileCacheImageOutputStream(OutputStream stream, File cacheDir) throws IOException { if (stream == null) { throw new IllegalArgumentException(stream == null!); } if ((cacheDir != null) && !(cacheDir.isDirectory())) { throw new IllegalArgumentException(Not a directory!); } this.stream = stream; this.cacheFile = sun.misc.IOUtils.createTempFile(imageio, .tmp, cacheDir); this.cache = new RandomAccessFile(cacheFile, rw); this.closeAction = StreamCloser.createCloseAction(this); StreamCloser.addToQueue(closeAction); }
Here, I think you need to take a look at the javadoc of this method.
Constructs a FileCacheImageOutputStream that will write to a given outputStream.
A temporary file is used as a cache. if cacheDiris non-null and is a directory, the file will be created there. if it is null, the system-dependent default temporary-file directory will be used (see the documentationFile. createTempFileFor details ).
Let's take a look at the File. createTempFile method. At this time, we need to go to the java api help documentation!
CreateTempFile
Public static File createTempFile (String prefix,
String suffix,
File directory)
Throws IOException creates an empty file in the specified directory and generates its name using the given prefix and suffix string. If this method is returned successfully, you can ensure that:
The file indicated by the returned abstract path name does not exist before this method is called.
This method and all its variants do not return the same abstract path name again in the current call of the virtual machine.
This method only provides partial functions of temporary files. You can use the deleteOnExit () method to automatically delete files created by this method.
The prefix parameter must be at least three bytes long. We recommend that you use a short and meaningful string with a prefix, such as "hjb" or "mail ". The suffix parameter can be null. In this case, the suffix ". tmp" is used ".
To create a new file, you may need to adjust the prefix and suffix to meet the requirements of the underlying platform. If the prefix is too long, it is truncated, but the first three characters are always retained. If the suffix is too long, it will be truncated, but if it starts with a period ('.'), the period and the first three characters followed by it will always be retained. After these adjustments, the name of the new file is generated by connecting the prefix, five or more internally generated characters, and the suffix.
If the directory parameter is null, the System-related default temporary file directory is used. The default temporary file directory is specified by the system attribute java. io. tmpdir. On UNIX systems, the default value of this attribute is usually "/tmp" or "/var/tmp ";In Microsoft Windows, the value is usually "C: WINNTTEMP". When calling a Java virtual machine, you can provide different values for this system attribute, but there is no guarantee that changing this attribute by program will affect the temporary directory used by this method.
Parameters:
Prefix-the prefix string used to generate the file name. It must be at least three characters long.
Suffix-the suffix string used to generate the file name. It can be null. In this case, the suffix ". tmp" is used"
Directory-the directory where the created file is located. If the default temporary file directory is used, this parameter is null.
Return Value:
The abstract path name of the new empty file.
Throw:
IllegalArgumentException-if the prefix parameter contains less than three characters
IOException-if the file cannot be created
SecurityException-if a security manager exists and its SecurityManager. checkWrite (java. lang. String) method does not allow File Creation
Note: Let's take a look at the windowsC: WINNTTEMPDirectory.
WINNT is something I don't know. Ask du Niang:
Microsoft Windows NT (New Technology) is a network operating system launched by Microsoft in 1993 for workstations, network servers, and large computers. It can also be used as a PC operating system. It is closely integrated with communication services and is compiled based on OS/2 NT. OS/2 is jointly developed by Microsoft and IBM. It is divided into Microsoft OS/2 NT and ibm OS/2. After the cooperation, IBM continued to provide the previous OS/2 version to the market. Microsoft changed its OS/2 NT name to Windows NT, the first generation of Windows NT 3.1.
Probably it means the above.
Then, I compared windows server 2008 and windows server
Sorry, I couldn't find what I wanted. I'm not happy!
Continue Exploration
Let's look back and find this keyword:
The default temporary file directory is specified by the system attribute java. io. tmpdir.
Write a program to test
public class Test { public static void main(String[] args) { System.out.println(System.getProperty(java.io.tmpdir)); }}
| System |
Output |
| Win7 |
C: UsersabcAppDataLocalTemp |
| Servers 2008 |
C: UsersADMINI ~ 1 AppDataLocalTemp |
Find the directory. The approximate directory of windows 2008 should be C: UsersAdministratorAppDataLocal, but it cannot be found. 2 is not found.
Create a new 2 Directory and try again. The verification code can be output!