2010-04-09 3 views
0

iPhone 기반 zLib을 호출하여 HTTP 기반 서버에서 zlib 스트림의 압축을 풀려고 시도했지만 코드가 첫 번째 zlib 블록을 완료 한 후 항상 중지됩니다.iPhone에서 zLib, 처음에 멈춤 BLOCK

분명히 iPhone SDK는 표준 open Zlib을 사용하고 있습니다. 제 의심의 여지가 inflateInit2에 대한 매개 변수가 여기에 적합하지 않습니다.

zlib 설명서를 읽는 데 많은 시간을 할애했지만 그다지 도움이되지 않습니다.

여기가 자세한 내용입니다. 귀하의 도움에 감사드립니다.

(1) HTTP 요청 (압축 해제 된 경우)

NSURL *url = [NSURL URLWithString:@"http://192.168.0.98:82/WIC?query=getcontacts&PIN=12345678&compression=Y"]; 

(2)는 서버에서 얻는 데이터는이 같은 것입니다.

$REC_TYPE=SYS 
Status=OK 
Message=OK 
SetID= 
IsLast=Y 
StartIndex=0 
LastIndex=6 
EOR 

......

$REC_TYPE=CONTACTSDISTLIST 
ID=2 
Name=CTU+L%2EA%2E 
OnCallEnabled=Y 
OnCallMinUsers=1 
OnCallEditRight= 
OnCallEditDLRight=D 
Fields= 
CL= 
OnCallStatus= 
EOR 

(3) 그러나, 나는 단지 얻을 것이다 첫 번째 블록 : 스트림은 C#을 ZLIB 클래스 DeflateStream으로 압축되었다. iPhone에서 압축 해제 코드 (코드 조각 from somewhere here에서 복사 됨)는 다음과 같습니다. 줄 23 ~ 38 사이의 루프는 항상 두 번째 실행을 중단합니다.

+ (NSData *) uncompress: (NSData*) data 
    { 
1 if ([data length] == 0) return nil; 
2 NSInteger length = [data length]; 
3 unsigned full_length = length; 
4 unsigned half_length =length/ 2; 

5 NSMutableData *decompressed = [NSMutableData dataWithLength: 5*full_length + half_length]; 
6 BOOL done = NO; 
7 int status; 

8 z_stream strm; 
9 length=length-4; 
10 void* bytes= malloc(length); 
11 NSRange range; 
12 range.location=4; 
13 range.length=length; 
14 [data getBytes: bytes range: range]; 
15 strm.next_in = bytes; 
16 strm.avail_in = length; 
17 strm.total_out = 0; 
18 strm.zalloc = Z_NULL; 
19 strm.zfree = Z_NULL; 
20 strm.data_type= Z_BINARY; 
21 // if (inflateInit(&strm) != Z_OK) return nil; 

22 if (inflateInit2(&strm, (-15)) != Z_OK) return nil; //It won't work if change -15 to positive numbers. 
23 while (!done) 
24 { 
25  // Make sure we have enough room and reset the lengths. 
26  if (strm.total_out >= [decompressed length]) 
27  [decompressed increaseLengthBy: half_length]; 
28  strm.next_out = [decompressed mutableBytes] + strm.total_out; 
29  strm.avail_out = [decompressed length] - strm.total_out; 
30  
31  // Inflate another chunk. 
32  status = inflate (&strm, Z_SYNC_FLUSH); //Z_SYNC_FLUSH-->Z_BLOCK, won't work either 
33  if (status == Z_STREAM_END){ 
34  
35  done = YES; 
36  } 
37  else if (status != Z_OK) break; 
38 } 

39 if (inflateEnd (&strm) != Z_OK) return nil; 

40 // Set real length. 
41 if (done) 
42 { 
43  [decompressed setLength: strm.total_out]; 
44  return [NSData dataWithData: decompressed]; 
45 } 
46 else return nil; 
47 } 

답변

1

이 문제가 발생하여이를 분류했습니다. 코드는 Z_BUF_ERROR가 반환되면 깨지기 때문에 약간 버그가 있습니다. 아직 zlib Documentation을 읽는 중 Z_BUF_ERROR는 인플레이션을 검사해서는 안되며, 결과 출력이 괜찮은 경우에도 throw 될 수 있습니다. 이 당신을 위해 일하는

// Inflate another chunk. 
     status = inflate (&strm, Z_SYNC_FLUSH); 
     if ((status == Z_STREAM_END) || (status == Z_BUF_ERROR)) 
      done = YES; 

희망 : 따라서 일의 코드를 변경

.

편집 : (2011 년 6 월 18 일)
여기에 전체 인플레이션 방법이 나와 있습니다. 그것은을 NSData의 범주로 구현됩니다 :

@interface NSData (NSDataExtension) 
- (NSData *) zlibInflate; 
@end 

@implementation NSData (NSDataExtension) 
- (NSData *)zlibInflate 
{ 
if ([self length] == 0) return self; 

unsigned full_length = [self length]; 
unsigned half_length = [self length]/2; 

NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; 
BOOL done = NO; 
int status; 

z_stream strm; 
strm.next_in = (Bytef *)[self bytes]; 
strm.avail_in = [self length]; 
strm.total_out = 0; 
strm.zalloc = Z_NULL; 
strm.zfree = Z_NULL; 

if (inflateInit (&strm) != Z_OK) return nil; 

while (!done) 
{ 
    // Make sure we have enough room and reset the lengths. 
    if (strm.total_out >= [decompressed length]) 
     [decompressed increaseLengthBy: half_length]; 
    strm.next_out = [decompressed mutableBytes] + strm.total_out; 
    strm.avail_out = [decompressed length] - strm.total_out; 

    // Inflate another chunk. 
    status = inflate (&strm, Z_SYNC_FLUSH); 
    if (
     (status == Z_STREAM_END) || (status == Z_BUF_ERROR) 
     ) 
     done = YES; 
    else if (status != Z_OK) break; 
} 
if (inflateEnd (&strm) != Z_OK) return nil; 

// Set real length. 
if (done) 
{ 
    [decompressed setLength: strm.total_out]; 
    return [NSData dataWithData: decompressed]; 
} 
else return nil; 
} 
@end 

카를로스

+0

안녕하세요, 카를로스, 그것은 누군가가 마지막으로 작동있어보고 매우 고무적이다. 그러나 제안한 변경 사항을 적용했지만 작동하지 않습니다. 내 코드에는 다른 문제가 있습니다. 여기에 전체 인플레이션 코드를 첨부 할 수 있습니까? 감사! 세드릭 – cedric

+0

하이 세드릭, 내가 그것을 파헤 치는 것을 기억하려고 노력할 것이다. –

+0

약속대로, 나는 코드를 파헤 쳤다. 다른 답변으로 게시하려고합니다. 그것이 도움이된다면, 아마도 당신은 옳은 것으로 표시 할 수 있습니다. –