二进制结构到文件中的随机记录然后再返回

时间:2014-02-17 02:33:17

标签: ios objective-c cocoa-touch struct

我有一个数据结构,我想读取和写入二进制文件中的随机记录。我已经尝试过使用NSFileManager / NSFileHandle,并且无法弄清楚如何将我的数据类型转换为它想要看作文件的数据流。我尝试过类似问题的pread和pwrite。我认为fread和fwrite最适合,并且也有类似的问题。我的代码很糟糕,不值得发帖。

编辑 - 只是为了说明语法是如何挑战的,这就是我试图将结构转换为NSString然后转换为NSData以便我可以用NSFileManager编写它(得到EXC_BAD_ACCESS错误???):

NSString *d = (__bridge NSString *) &b224;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:d];

请帮忙,我是C的新手,到目前为止我已经花了一天时间了解这个问题,但没有成功。更糟糕的是,我认为,有些人会向我射箭。我找不到任何关于这样做的教程,希望有人可以指出我正确的方向。该结构覆盖7个32位int32_t整数并填充,以便每个记录为224位或28个8位字节。

在struct中使用int类型可以只使用几位长的整数吗?这似乎有效,甚至似乎保留了符号位,只要我给它一点额外的一点。

我想在使用Xcode 5的iPhone应用程序的Objective C代码中使用它。

这样做的速度和效率是一个主要问题。

编辑 - 文件最终会有数十万条记录,随机个别记录可能需要在一两分钟内更新。

已解决 - 请参阅评论。要创建NSdata * d以发送到文件:

NSData *d = [NSData dataWithBytes:(const void *) &b224 length:28];

将从文件中读取的NSData * r中的数据放回到结构中:

[r getBytes:&b224 length:28];

注1 - 将位字段分组为32组并且没有任何字段重叠任何32位边界似乎非常重要,不知道为什么我会留给专家来解决这个问题,至少当没有字段与边界重叠时,我得到了我想做的事情。

注意2 - 确保你永远不会在位域范围之外放入一个值,当你这样做时它们似乎没有被截断,它们会移动所有其他位并且你的记录会被破坏。

谢谢!,卡门

struct bfbits{
   int lat:28;
   BOOL real:1;
   BOOL inuse:1;
   BOOL inter:1;
   BOOL turn:1;

   int lon:29;
   BOOL units:1;
   BOOL onleft:1;
   int free2:1;

   int who:26;
   int free3:6;

   int day:16;
   int heading:9;
   int free4:7;

   int limit:7;
   int trucklimit:7;
   int altlimit:7;
   int warnft:10;
   int free5:1;

   int uses:16;
   int rejects:16;

   int starthr:5;
   int endhr:5;
   int beginday:4;
   int finishday:4;
   int beginmonth:5;
   int finishmonth:5;
   BOOL daynight:1;
   BOOL weekday:1;
   int free7:2;
};
struct bfbits b224;

1 个答案:

答案 0 :(得分:0)

几点

  • 一般的习语是“让它先工作,然后再担心让它快速”
  • 从磁盘读取文件很少会导致读取单个32位值。每次点击I / O时,很可能会抽取大量数据。多少取决于您的设备和操作系统。但此时它的大于整个文件。
  • 此外,每次从I / O缓冲区读取时,都会拉出整个缓存行,这也将大于单个32位值。

我想说的是,对所有这些使用位域并不会对你有所帮助,并且可能会使事情复杂化。另外:现代cpu和位字段......不完全是朋友。现代CPU设计用于执行与寄存器大小相同的操作,因此使用非静态掩码或执行变量>>和<<会很慢。如果你真的必须使用位域,请使用常量掩码。

此外,由于对齐,您可能很好地安排了数据。由于上面的高速缓存读取,将数据结构填充到最近的N个字节以保持高速缓存访​​问的对齐是很常见的。所以任何5位结构都会最终被填充到任何对齐的位置(可能是8个字节)。

最好的办法是将文件数据作为unsigned char *,然后查看缓冲区的内存内容。然后,将它与您早期准备的预先填充结构的内存内容进行比较,看看各种事物的对齐情况。

此时此刻。我只是把所有东西都变成了int32,然后看看你是否可以通过这种方式直接将所有内容拉到内存中。如果这样可行,那么您尝试打包数据会导致问题。