iOS how to store a NSDictionary or JSON in a file's xattr?

孤街醉人 提交于 2019-12-25 01:44:25

问题


I'm looking at extended file attributes for iOS and Mac files using setxattr command. From what I understand, I can store arbitrary data there, up to 128kb.

How can I write and read extended attributes as if I'm dealing with a dictionary, not dereferencing string pointers?

So far I have this code that attempts to set a single attribute.

NSString* filepath = [MyValueObject filepath]; 
const char *systemPath = [filepath fileSystemRepresentation];
const char *name = "special_value";
const char *value = "test string";

int result = setxattr(systemPath, name, &value, strlen(value), 0, 0);

If I need to store a small set of values (say 5 key-value pairs), I'm thinking of:

  1. Creating a NSDictionary with my attributes
  2. Converting the dictionary to JSON string
  3. Converting the string to character pointer
  4. Writing the string to the extended attributes
  5. To read the attribute back, I would read back the string pointer
  6. Convert to NSString
  7. Convert to JSON object
  8. Create a dictionary back
  9. Retrieve a value from dictionary

Does this seem like the right approach? Is there's an easier way to store metadata in extended attributes ? Maybe there is a category on NSObject that handles the pointer operations for xattr?


回答1:


I found a Cocoanetics/DTFoundation that allows reading/writing arbitrary strings to xattr: Together with other posts, I was able to accomplish what I wanted - write/restore a dictionary

#import "Note+ExtendedAttribute.h"
#include <sys/xattr.h>


@implementation MyFile (ExtendedAttribute)

-(NSString*)dictionaryKey
{
    return @"mydictionary";
}

-(BOOL)writeExtendedAttributeDictionary:(NSDictionary*)dictionary
{
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
                                                       options:0
                                                         error:&error];
    if (! jsonData) {
        return NO;
    }

    NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];



    const char *filepath = [[self filepath] fileSystemRepresentation];

    const char *key = [[self dictionaryKey] UTF8String];
    const char *value = [jsonString UTF8String];

    int result = setxattr(filepath, key, value, strlen(value), 0, 0);

    if(result != 0)
    {
        return NO;
    }

    return YES;
}

Reading:

-(NSMutableDictionary*)readExtendedAttributeDictionary
{
    const char *attrName = [[self dictionaryKey] UTF8String];
    const char *filePath = [[self filepath] fileSystemRepresentation];

    // get size of needed buffer
    int bufferLength = getxattr(filePath, attrName, NULL, 0, 0, 0);

    if(bufferLength<=0)
    {
        return nil;
    }

    // make a buffer of sufficient length
    char *buffer = malloc(bufferLength);

    // now actually get the attribute string
    getxattr(filePath, attrName, buffer, bufferLength, 0, 0);

    // convert to NSString
    NSString *retString = [[NSString alloc] initWithBytes:buffer length:bufferLength encoding:NSUTF8StringEncoding];

    // release buffer
    free(buffer);

     NSData *data = [retString dataUsingEncoding:NSUTF8StringEncoding];
    if(data == nil || data.length == 0)
    {
        return nil;
    }

    NSError *error = nil;
    id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

    if([json isKindOfClass:[NSDictionary class]])
    {
        return [NSMutableDictionary dictionaryWithDictionary:json];
    }

    if(error)
    {
        return nil;
    }


    return json;
}



回答2:


convert the dictionary to a binary plist and write that -- and vice versa :)

Write:

  1. create dict
  2. make binary plist
  3. write it

--

Read:

  1. read binary plist
  2. make a dictionary from it


来源:https://stackoverflow.com/questions/25408028/ios-how-to-store-a-nsdictionary-or-json-in-a-files-xattr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!