Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 读取从JavaEE服务器返回的字节流_Iphone_Objective C_Cocoa Touch - Fatal编程技术网

Iphone 读取从JavaEE服务器返回的字节流

Iphone 读取从JavaEE服务器返回的字节流,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我们有一个JavaEE服务器和servlet向移动客户端提供数据(第一个是JavaME,现在很快就是iPhone)。servlet使用以下代码写出数据: DataOutputStream dos = new DataOutputStream(out); dos.writeInt(someInt); dos.writeUTF(someString); 。。。等等 此数据在HTTP响应正文中以字节的形式返回给客户端,以减少传输的字节数 在iPhone应用程序中,响应负载加载到NSData对象中

我们有一个JavaEE服务器和servlet向移动客户端提供数据(第一个是JavaME,现在很快就是iPhone)。servlet使用以下代码写出数据:

DataOutputStream dos = new DataOutputStream(out);

dos.writeInt(someInt);

dos.writeUTF(someString);
。。。等等

此数据在HTTP响应正文中以字节的形式返回给客户端,以减少传输的字节数

在iPhone应用程序中,响应负载加载到NSData对象中。现在,在花了好几个小时试图弄清楚如何在Objective-C应用程序中读取数据之后,我几乎准备放弃,因为我还没有找到任何好的方法将数据读入NSInteger和NSString(与上述协议相对应)

有没有人能告诉我们如何从java应用程序编写的二进制协议中读取数据?非常感谢您的帮助


谢谢

主要是要了解二进制数据格式本身。写什么并不重要,只要你知道字节的意思

因此,的文档是您的最佳选择。它们(希望)指定二进制数据的所有内容


接下来,我将尝试在iPhone上创建一个类,将相同的格式读入适当的数据结构。我根本不知道目标C,但我确信读取4个字节不会太难,知道第一个字节是最重要的(etc),并进行适当的位旋转以获得正确的整数类型。(基本上是读取一个字节,将其向左移位8,读取下一个字节并将其添加到结果中,将整批字节向左移位8位,等等)可能有更有效的方法来实现这一点,但首先要得到一些有效的方法。当你有了所有的单元测试之后,你可以继续优化它。

别忘了Objective-C就是穿着漂亮衣服的C——C擅长这种卑躬屈膝的行为。在很大程度上,您应该能够定义一个看起来像数据的C结构,并将指向数据的指针转换为指向该结构的指针。现在,要使用哪种类型,以及是否需要进行字节交换,将取决于Java如何构造此流;这就是您需要花时间阅读Java文档的原因


但从根本上说,这是一种设计的味道。您遇到这个问题是因为您对您的客户机平台所做的假设不再有效。如果这是一个选项,我建议您为相同的函数提供第二个更可移植的接口(只需添加“WithXML”包装器或其他东西就足够了)。如果您最终移植到另一个不使用Java的平台,这将节省您的时间。

Carl,如果您确实无法更改服务器提供的内容,请查看。它应该是您正在寻找的指针。也就是说:使用本机java序列化作为传输格式的想法听起来不是一个好主意。我的第一选择是。如果这仍然太大,我可能宁愿使用像或这样的东西。它们还提供二进制序列化,但采用跨语言的方式。(还有老一套的ASN1——但那很痛苦)

你必须自己去做这个解压;幸运的是,这相当简单。Java的
DataOutputStream
类以big-endian(网络)格式写入整数。所以,为了解Marshall整数,我们获取4个字节,并将它们解压成一个4字节的整数

对于UTF-8字符串,
DataOutputStream
首先写入一个2字节的值,指示后面的字节数。我们在中读取,然后读取后面的字节。然后,为了解码字符串,我们可以使用
NSString
方法如下:

NSData*数据=…;//这来自HTTP请求
int length=[数据长度];
const uint8_t*字节=(const uint8_t*)[数据字节];
如果(长度<4)
; // 哦,句柄错误
//demarshall从4字节开始计算大端整数

uint32_t myInt=(bytes[0]嗯,我们之所以选择二进制协议而不是基于xml的消息,是因为我们正在通过无线承载(如GPRS、Edge)传输大量数据然后每一位都会起作用。如果我们要传输xml,数据量大约会增加15倍,典型的响应大约是200-300kb。有一些函数像
NSSwapBigIntToHost()
在Objective-C中帮助您完成conversion@user102008:
NSSwapBigIntToHost
在功能上与
ntohl
完全相同,这完全取决于您想要使用哪一个。
NSData *data = ...;  // this comes from the HTTP request
int length = [data length];
const uint8_t *bytes = (const uint8_t *)[data bytes];

if(length < 4)
    ; // oops, handle error

// demarshall the big-endian integer from 4 bytes
uint32_t myInt = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | (bytes[3]);
// convert from (n)etwork endianness to (h)ost endianness (may be a no-op)
// ntohl is defined in <arpa/inet.h>
myInt = ntohl(myInt);

// advance to next datum
bytes += 4;
length -= 4;

// demarshall the string length
if(length < 2)
    ; // oops, handle error
uint16_t myStringLen = (bytes[0] << 8) | (bytes[1]);
// convert from network to host endianness
myStringLen = ntohs(myStringLen);
bytes += 2;
length -= 2;

// make sure we actually have as much data as we say we have
if(myStringLen > length)
    myStringLen = (uint16_t)length;

// demarshall the string
NSString *myString = [[NSString alloc] initWithBytes:bytes length:myStringLen encoding:NSUTF8StringEncoding];
bytes += myStringLen;
length -= myStringLen;