I need to use the writeToFile: methods in writing data (that is encrypted) to a file. However, say I have:
NSData *encryptedData = [data AES256EncryptWithKey:key];
And I write the encryptedData to a file by:
[encryptedData writeToFile:#"file.txt" automatically:YES];
This for some reason does not write the data to "file.txt." This is a very simple question and I know I am missing something super basic. If file.txt is not actually there, it must be created.
This probably has nothing to do with Cocoa or NSData.
On Unix (like Mac OS X), paths that start with / are absolute. Paths that start with ~ are relative to the current user's home directory. Anything else (such as file.txt) is relative to the current directory. When running something from Xcode, that is the path of the executable (the compiler's output path).
So, to write that to the desktop, that would be:
[encryptedData writeToFile:#"~/Desktop/file.txt" atomically:YES];
For the documents folder, that would be:
[encryptedData writeToFile:#"~/Documents/file.txt" atomically:YES];
Don't forget that paths are also case-sensitive.
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
returns a boolean to say if it was successful or not. I'd start there, if you see a YES then the file wrote somewhere successfully.
If that doesn't work then i'd double check the object you're trying to encode supports the NSCoding protocol. If you object doesn't support NSCoding take a look at this blog post for a nifty simple way of adding it.
Also its "atomically" not "automatically" :)
Related
I'm experiencing a problem on OS X, where stat intermittently returns a struct whose st_mtime has a value of 0, for certain files.
Why does this happen, and is there any alternative function that will provide me with a reliable modified date for a file?
If you are using Objective-C, NSFileManager has a nice API named "attributesOfItemAtPath:error:" where one of the things passed back in the NSDictionary object is "fileModificationDate".
You also can use CoreFoundation CFURL functions, like "CFURLCopyResourcePropertyForKey" which has something called "kCFURLAttributeModificationDateKey" which you can get the value of.
I don't know their reliability, but what about ls -l or find -ls?
EDIT:
I just found this: Getting the last modified date of a file in C
On OS X, st_mtimespec.tv_sec is the equivalent of st_mtime.
This may sound silly, but check the return code of stat(). If it returns anything but zero, there was an error (e.g., file not found).
I just spent a few hours tracking this down myself.
I want to guess a received NSData's encoding. I searched in Stackoverflow and found one answer here which indicates "can't".
However, I noticed a NSString method stringWithContentsOfFile:usedEncoding:error:, and I wanted to know whether I can achieve this goal in sequence below:
1> Get an NSData object
2> Store this NSData object into a file with random file name in directory /tmp
3> Call NSString's stringWithContentsOfFile:usedEncoding:error: method to read from this temporary file.
4> Delete the temporary file.
5> Read the enc parameter to determine the encoding
I know I can experiment by myself, but I have no various data source with different encoding in my hand. Therefore I raised a question here. Could my opinion work? Could this solution find every possible encoding OS X could recognized?
Some MacOSX applications like iTunes don't really have problems when I move a file around - they still find the moved file easily (and I'm pretty sure they have not have opened the file before).
How are they doing it? One possibility I could think of is the FS event notification system. (related question)
But I remember that I have seen some absolute file handle / id or so and I thought that maybe they can always query the current file name by that file handle. Is there something like that? Maybe the inode nr but that is a bit too less because I'm not sure how to get the filename from an inode nr and how to open the file.
As Albert mentioned Alias Manager has been depreciated, the replacement is the URL Bookmark methods
I think what you're looking for is NSURL's bookmarks — I'm on an iPad do unable to produce proper links due to Apple's shortsighted web page design but the essence of it is that you obtain a bookmark from a URL and can subsequently resolve a bookmark back to a URL. The system works around any movements in the file in the interim.
I just found out about the Alias Manager which sounds like what I am searching for. Unfortunately, that seems deprecated. (related question) Some info about the deprecation.
(Another related question) There is also the NSURL class which provides such functions.
Python code:
import AppKit
def getFileNativeId(filepath):
if not os.path.isfile(filepath): return None
filepath = os.path.abspath(filepath)
filepath = unicode(filepath)
url = AppKit.NSURL.alloc().initFileURLWithPath_(filepath)
bookmark = url.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_(AppKit.NSURLBookmarkCreationPreferFileIDResolution,None,None,None)
bytes = bookmark[0].bytes().tobytes()
return bytes
def getPathByNativeId(fileid):
nsdata = AppKit.NSData.alloc().initWithBytes_length_(fileid, len(fileid))
url, _, _ = AppKit.NSURL.URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_(nsdata, AppKit.NSURLBookmarkResolutionWithoutUI, None,None,None)
if not url: return None
return unicode(url.path())
To determine the size of a file, I have always used:
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
unsigned long long size = [fileAttributes fileSize];
However, the method attributesOfItemAtPath:error: does not traverse symbolic links. Apple so suggests:
If the item at the path is a symbolic link—that is, the value of the NSFileType key in the attributes dictionary is NSFileTypeSymbolicLink—you can use the destinationOfSymbolicLinkAtPath:error: method to retrieve the path of the item pointed to by the link.
This would be great, if the sandbox does not prevent me from accessing the pointed file:
deny file-read-xattr /path/to/the/original/file
So, my question is: how can I obtain the size of a file pointed by a symbolic link under the OS X sandbox?
It seems to be a bug. If the user has specifically dragged a symlink to the app, that's a clear statement of user intent and you'd expect to have access to the symlink and the target. In fact, I can access the original file and read its contents, but not its attributes. So I filed the bug report #13143810.
EDIT: My bug report has been closed as duplicate of #12991152, which is actually "open."
I see that this has been answered previously by Ken T., but I have a case where the code appears to work, and the call to setxattr() returns 0, but the item I want to modify does not change.
Specifically, I'm trying to change the metadata attribute kMDItemDisplayName, and my call looks like this (modeled after the sample posted by Ken T):
[Note: the "name" param below is an NSString *]
rc = setxattr([pathString cStringUsingEncoding:NSUTF8StringEncoding],
"kMDItemDisplayName",
[name cStringUsingEncoding:NSUTF8StringEncoding],
[name lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
0,
0);
Doing an mdls on the file in question shows that the kMDItemDisplayName attribute is present, but I can't get it to change to anything other than the actual file name (which I assume is the default behavior).
Am I misunderstanding something about how setxattr() is supposed to work?
Any help very much appreciated.
Oh, BTW, why am I trying to do this? It appears (from examining how Bare Bones' Yojimbo does things) that Spotlight uses the kMDItemDisplayName value to list files in the Spotlight search results menu in the finder, which is something I'd like to implement in my app.
Thanks!
Heyyyy... wait a minute...
From the command line, doing xattr -l shows that as far as xattr knows, there is an attribute called kMDItemDisplayName, and it is what I set it to be... However, mdls on the same file still shows the kMDItemDisplayName attribute as the file name.
Do I need to be asking about Launch Services instead of xattr stuff??
OK. After hunting around a bit more and reading more Apple documentation I realized what I need to do. I'm answering my own question in the hope that this information may be of some assistance to someone else down the line.
Because I had to write my own mdimporter to support my app's file format, I thought I'd try adding the kMDItemDisplay name item to the metadata store at metadata import time.
To my amazement and delight, it worked on the first try!
So, the answer is, if you want to overwrite or add custom kMDItem* types, you do so at metadata import time, using a Spotlight importer.
Hope that someone finds this helpful!