JPEG文件结构无效:两个SOI标记错误?

时间:2015-06-27 22:42:50

标签: java sockets jpeg

This is the image that causes an error

我有这个问题,我尝试了所有我知道的但没有任何效果。 我试图通过套接字从数据库向客户端应用程序发送多个图像(一次一个图像),有时一切正常,但有时它声明这个“无效的JPEG文件结构:两个SOI标记”错误?

客户方:

    var currentStatus:UIUserNotificationSettings = UIApplication.sharedApplication().currentUserNotificationSettings()

服务器端:

UIApplication.sharedApplication()

2 个答案:

答案 0 :(得分:4)

不要使用available()来衡量输入的长度。 Javadoc中有一个特定的警告。这不是它的用途。

您的副本循环应如下所示:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

答案 1 :(得分:2)

首先要做的事情: 你遇到的错误:

每个JPEG图像始终以StartOfImage标记开头,以十六进制为单位:FFD8 您正在创建的缓冲区中的字节包含此SOI标记两次。 您很可能获得图像1的字节+图像2的某些字节,特别是包含第二个图像标记的起始字节。

我认为你在这里犯了一个错误:

byteToread =in.readInt();
bytesOut=new ByteArrayOutputStream();
bos = new BufferedOutputStream(bytesOut);     
while (byteToread >cmpt) {
    cmpt = in.read(dataEntre);
    bos.write(dataEntre, 0, cmpt);
    bos.flush();
    byteToread-=cmpt;
} 

例如,总共有100个字节的情况。 由于某种原因,你将以50,30,20字节的块为单位读取这100个字节。

这将给出以下内容:

iteration 1:
during while:   
    bytesToRead: 100
    cmpt: 0
at the end of the loop:
    bytesToRead: 50
    cmpt: 50
iteration 2:
during while:   
    bytesToRead: 50
    cmpt: 50

此时,byteToRead(50)不是>比cmpt(50)所以循环结束时你不写最后50个字节。

你可能需要这样的东西:

bytesToread = in.readInt();
bytesOut=new ByteArrayOutputStream();
bos = new BufferedOutputStream(bytesOut);     
while (byteToread > 0) {
    cmpt = in.read(dataEntre);
    bos.write(dataEntre, 0, cmpt);
    bos.flush();
    byteToread-=cmpt;
}

对于小图像,您可以一次性读取整个字节数量(虽然这不能保证,但很可能)。如果发生这种情况,那么您将在一次迭代中完成并且永远不会遇到问题。但是对于较大的图像,您可能会因为您读取的最后一个块而导致错过图像末尾的某些字节。这会造成麻烦(我认为)

第二个问题可能是(在服务器端)

byteToread=input.available();

从db获取的结果集可能没有可供您使用的所有字节。

来自available()的文档

  

请注意,虽然InputStream的某些实现将返回流中的总字节数,但许多实现不会。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区绝对不正确。

从我可以看到出错(并且基于我的测试程序),会发生以下情况:

1:你得到image1(比如200字节)。 2:您将长度(200)写入输出流 3:您将少于200个字节写入输出流(例如150)。 (因为逻辑错误) 4:你得到image2(比如300字节) 5:您将长度(300)写入输出流 6:你将N个字节写入输出流。

当你阅读

1:你读了image1.length。这会让你回归200。 2:你读了200个字节。因为你只从图像1写了150个字节,这意味着你从image1获得150个字节,从image2获得长度,然后从image2获得46个字节。

这导致您认为图像1的字节包含jpg的2个标头。 (image2的前46个字节将包含image2的标题)

我认为您需要附加调试器并逐步完成此操作并找出其他问题。给出的另一个答案显示了如何正确循环并计算您的读取字节。可能会有更多问题。