为什么Java不能从InputStream正确地重新创建此映像?
我已经从各个角度考虑过了。。。问题是,我最终编写了完美的字节数,文件非常相似,但有些字节不同。我在Scite中打开了Java生成的文件以及原始文件,尽管它们很接近,但它们并不相同。有办法解决这个问题吗?我尝试了一切可能的方法——我使用了不同的包装器、读取器、写入器和不同的方法来获取字节数组(或将其作为字符——两者都尝试过)并将其生成文件
测试中的图像位于http://www.google.com/images/srpr/nav_logo13.png。代码如下:
import java.awt.Image;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.imageio.ImageIO;
public class ImgExample
{
private String address = "http://www.google.com";
/**
* Returns a 3 dimensional array that holds the RGB values of each pixel at the position of the current
* webcam picture. For example, getPicture()[1][2][3] is the pixel at (2,1) and the BLUE value.
* [row][col][0] is alpha
* [row][col][1] is red
* [row][col][2] is green
* [row][col][3] is blue
*/
public int[][][] getPicture()
{
Image camera = null;
try {
int maxChars = 35000;
//The image in question is 28,736 bytes, but I want to make sure it's bigger
//for testing purposes as in my case, it's an image stream so it's unpredictable
byte[] buffer = new byte[maxChars];
//create the connection
HttpURLConnection conn = (HttpURLConnection)(new URL(this.address+"/images/srpr/nav_logo13.png")).openConnection();
conn.setUseCaches(false);
//wrap a buffer around our input stream
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
int bytesRead = 0;
while ( bytesRead < maxChars && reader.ready() )
{
//reader.read returns an int - I'm assuming this is okay?
buffer[bytesRead] = (byte)reader.read();
bytesRead++;
if ( !reader.ready() )
{
//This is here to make sure the stream has time to download the next segment
Thread.sleep(10);
}
}
reader.close();
//Great, write out the file for viewing
File writeOutFile = new File("testgoog.png");
if ( writeOutFile.exists() )
{
writeOutFile.delete();
writeOutFile.createNewFile();
}
FileOutputStream fout = new FileOutputStream(writeOutFile, false);
//FileWriter fout = new FileWriter(writeOutFile, false);
//needed to make sure I was actually reading 100% of the file in question
System.out.println("Bytes read = "+bytesRead);
//write out the byte buffer from the first byte to the end of all the chars read
fout.write(buffer, 0, bytesRead);
fout.flush();
fout.close();
//Finally use a byte stream to create an image
ByteArrayInputStream byteImgStream = new ByteArrayInputStream(buffer);
camera = ImageIO.read(byteImgStream);
byteImgStream.close();
} catch ( Exception e ) { e.printStackTrace(); }
return ImgExample.imageToPixels(camera);
}
public static int[][][] imageToPixels (Image image)
{
//there's a bunch of code here that works in the real program, no worries
//it creates a 3d arr that goes [x][y][alpha, r, g, b val]
//e.g. imageToPixels(camera)[1][2][3] gives the pixel's blue value for row 1 col 2
return new int[][][]{{{-1,-1,-1}}};
}
public static void main(String[] args)
{
ImgExample ex = new ImgExample();
ex.getPicture();
}
}
# 1 楼答案
我认为您的问题是您正在使用InputStreamReader。来自javadocs
您不希望转换为字符流
# 2 楼答案
您也不应该像这样使用ready()。你只是在浪费时间和睡眠。read()将一直阻止,直到数据到达,并且它将阻止正确的时间长度,而不是任意猜测。Java中的规范复制循环如下所示:
# 3 楼答案
BufferedReader用于读取字符流,而不是字节/二进制流
缓冲读取器。read()以0到65535范围内的整数形式返回读取的字符。这可能会截断字节值大于65535的任何二进制数据
我认为您希望直接使用
InputStream.read()
,而不是用BufferedReader
/InputStreamReader
包装最后,与问题无关,但是如果您打开一个FileOutputStream以append=false,那么删除任何已经存在的文件实际上没有任何意义——append=false也会做同样的事情
# 4 楼答案
我所看到的问题是,您正在使用^{} s。在Java中,
Reader
s用于处理字符流,而不是二进制流,它所做的字符转换很可能是更改您的字节的原因相反,您应该直接从^{} 中}将阻塞,直到数据可用,但在到达流的末尾时返回-1
read()
InputStream
的{编辑:您还可以将InputStream包装为^{}