【问题标题】:NSPropertyListSerialization propertyListWithData fails with binary plistNSPropertyListSerialization propertyListWithData 失败并显示二进制 plist
【发布时间】:2014-10-06 05:15:54
【问题描述】:

更新:已解决。代码已更新。

我正在编写一些代码来处理 Objective-C++ 中的 plist。

当我将函数传递给 XML plist 的路径时,一切正常,输出显示:

2014-08-12 17:06:47.932 plist_tests[96368:507] plist was in xml format

当我将函数传递给二进制 plist 的路径时,我收到以下错误:

2014-08-12 17:02:23.598 plist_tests[95709:507] could not deserialize plist: Error Domain=NSCocoaErrorDomain Code=3840 "The data couldn’t be read because it isn’t in the correct format." (Unexpected character b at line 1) UserInfo=0x7f9f2040cd60 {NSDebugDescription=Unexpected character b at line 1, kCFPropertyListOldStyleParsingError=The data couldn’t be read because it isn’t in the correct format.}

这是代码。请注意,我的用例不能使用 dictionaryWithContentsOfFile

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

#import <Foundation/Foundation.h>

class Status {
public:
  Status(int c, std::string m) : code_(c), message_(m) {}
public:
  int getCode() { return code_; }
  std::string getMessage() { return message_; }
  bool ok() { return getCode() == 0; }
  std::string toString() { return getMessage(); }
private:
    int code_;
    std::string message_;
};

Status readFile(const std::string& path, std::string& content) {
  if (!boost::filesystem::exists(path)) {
    return Status(1, "File not found");
  }

  std::ifstream file_h(path);
  if (file_h) {
     file_h.seekg (0, file_h.end);
     int len = file_h.tellg();
     file_h.seekg (0, file_h.beg);
     char *buffer = new char [len];
     file_h.read(buffer, len);
     if (!file_h) {
      return Status(1, "Could not entire file");
     }
     content.assign(buffer, len);
  } else {
    return Status(1, "Could not open file for reading");
  }

  return Status(0, "OK");
}

void parsePlist(const std::string& path) {
  std::string file_content;
  Status readFileStatus = readFile(path, file_content);
  if (!readFileStatus.ok()) {
    NSLog(@"Couldn't read file");
    return;
  }
  NSData *plist_content = [NSData dataWithBytes:file_content.c_str()
                                         length:file_content.size()];

  NSError *error;
  NSPropertyListFormat plist_format;
  id plist = [NSPropertyListSerialization propertyListWithData:plist_content
                                                       options:NSPropertyListImmutable
                                                        format:&plist_format
                                                         error:&error];

  if (plist == nil) {
    NSLog(@"could not deserialize plist: %@", error);
  } else {
    switch (plist_format) {
    case NSPropertyListOpenStepFormat:
      NSLog(@"plist was in openstep format");
      break;
    case NSPropertyListXMLFormat_v1_0:
      NSLog(@"plist was in xml format");
      break;
    case NSPropertyListBinaryFormat_v1_0:
      NSLog(@"plist was in binary format");
      break;
    default:
      NSLog(@"plist was in unknown format");
      break;
    }
  }
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    std::cout << "Usage: plist <filename>" << std::endl;
    return 1;
  }
  parsePlist(argv[1]);
  return 0;
}

编译:g++ -lboost_system -lboost_filesystem -lglog -fobjc-arc -fobjc-link-runtime -framework Foundation plist.mm -o plist

我头疼的原因是,如果我在二进制 plist 上执行 plutil -convert xml1 file.plist -o -,它就可以正常工作。

【问题讨论】:

    标签: c++ ios objective-c macos plist


    【解决方案1】:

    将数据转换为NSString,然后再转换为NSData 的方式对 XML 有点不利,而对二进制数据则非常不利。而是这样做:

    NSData *plist_content = [NSData dataWithBytes: file_content.c_str()
                                    length: file_content.size() ];
    

    您的readFile 函数也有问题。考虑这条线

    content = std::string(buffer);
    

    std::string 如何知道缓冲区的长度?它寻找一个 NUL 字节,但这与二进制数据有关。您可以将该行替换为

    content.assign( buffer, len );
    

    或者如果你的路径是绝对路径,你可以去掉readFile然后说

    NSData *plist_content = [NSData dataWithContentsOfFile:
                                    [NSString stringWithUTF8String: path.c_str() ];
    

    【讨论】:

    • +1,不需要去NSString做中介。
    • 虽然是一个更好的主意,但更改 plist_content 的填充方式并不能解决问题:/错误仍然相同。
    • @marpaia,我认为readFile 也是您的代码,但您没有向我们展示。也许问题就在那里。
    • @JWWalker 你是凡人中的神,谢谢。
    猜你喜欢
    • 2017-01-30
    • 1970-01-01
    • 2010-09-20
    • 2016-10-24
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多