I'm uploading files to Dropbox, and I'm wondering if I can mark anything through NSFileManager to test to see whether a file has already been uploaded. I've been combing through the documentation and haven't found anything yet that could help.
So for instance, if I've uploaded a file called song.m4a, and the user changes the name of that file in the app, how would I be able to find out whether that file has been uploaded with the new name so that the file doesn't get uploaded again?
Are there any properties or attributes I could set to see if the file has been uploaded?
Thanks.
You can use hashing, e.g. you can calculate the MD5 hash of the file and store it in a local file on the phone, when the user tries to upload a file, you don't check its name, you simply recalculate the MD5 hash and check if it exists in your local file, if it does, then it was uploaded once before.
Edit:
You can convert anything to NSData and then calculate the hash of that NSData, e.g. in your case you can load the file like this
NSData* data = [NSData dataWithContentsOfFile:yourFilePath];
then you can hash it like this
- (NSString*)MD5:(NSData*)input
{
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5(input.bytes, input.length, md5Buffer);
// Convert unsigned char buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
and don't forget to import
#import <CommonCrypto/CommonDigest.h>
Related
I store a small PNG in a .plist.
When I open it in Xcode, the value of icone looks like classic NSData:
But when I open it as source code, here it is:
<key>icone</key>
<data>YnBsaXN0MDDUAQIDBAUINDVUJHRvcFgkb2JqZWN0 [...]
Hence my question : as it is not stored as NSData on the disk, how is this stored ? Base64?
In Xcode you see the hex representation of the NSData.
In the actual plist file you are seeing the base 64 encoded representation of the data.
Neither of these matter. In your code you simply do:
NSData *iconData = plistArray[0][#"icone"];
I'm new to iOS development and I'm trying to write an image as a jpeg file to the file system. From the logs I know that those file are indeed written to the file system, but when I try to save them to the camera roll they all appear black. I'm using the following code to write them as jpeg files:
[UIImageJPEGRepresentation(image, 1.0) writeToFile:jpegPath atomically:YES];
And the following code to write to camera roll:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Anybody know how to verify that those jpeg files are indeed written to the file system? And what I might be doing wrong in the second line of code?
EDIT: So here is the entire method:
- (BOOL)createImagesForSlides:(NSString *)documentsPath destinationURL:(NSURL *)destinationURL
{
NSFileManager *manager = [NSFileManager defaultManager];
CPDFDocument *document = [[CPDFDocument alloc] initWithURL:destinationURL];
NSString *folderName = [NSString stringWithFormat:#"/%#", document.title];
// create new folder
NSString *newFolderPath = [documentsPath stringByAppendingString:folderName];
BOOL result = [manager createDirectoryAtPath:newFolderPath withIntermediateDirectories:NO attributes:nil error:nil];
// create a jpeg file for each page of the pdf file
for (int i = 1; i <= document.numberOfPages; ++i) {
NSString *jpegPath = [NSString stringWithFormat:#"%#/%d.jpg", newFolderPath, i];
[UIImageJPEGRepresentation([[document pageForPageNumber:i] image], 1.0) writeToFile:jpegPath atomically:YES];
UIImageWriteToSavedPhotosAlbum([[document pageForPageNumber:i] image], nil, nil, nil);
}
return result;
}
document is a pointer to a CPDFDocument instance, and it's from some open source reader code available on github (iOS-PDF-Reader). What I basically do here is grab each page of the pdf document, generate an image, and then save them to the file system as jpeg file. Weird enough, even though there are more than 10 pages in the document, UIImageWriteToSavedPhotosAlbum only writes 5 files to camera roll. Any idea why?
It would probably be useful to see how you construct jpegPath here.
First, writeToFile:atomically: returns a BOOL, so check that for your first indication of success or failure.
There are a couple of ways you can verify that the image is written to the file system. If you are running on a device use something like iExplorer to access the file system and look at the file written. Since it is NSData* you can cheek the file size to make sure it looks reasonable. On the simulator, dig into the folder structure under ~/Library/Application Support/iPhone Simulator/ and examine the file. Without looking into the filesystem itself try reading the image back into another UIImage (imageWithData: in your case since you are writing a NSData* object).
There doesn't appear to be anything wrong with your UIImageWriteToSavedPhotosAlbum call according to the docs. It is OK for the last 3 arguments to be nil (all are marked as optional), you just have to be sure the UIImage is valid. Have you set a breakpoint to be sure you have a valid image (Xcode Quick Look feature)?
I'm new to iOS and am trying to read the contents of a spreadsheet into an iOS array.
The spreadsheet that I'm using is a simple 3 x 2 array of numbers for the first column and text for the second. I've tried reading it in with & without column headers, in .xls, .xlsx, . cdv, .txt (unicode and delimited) but without success. The file is called "funds", and the code I'm using is:
NSData *databuffer;
NSFileHandle * file;
NSString *docDir = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES)[0];
NSString *fileDir = [docDir stringByAppendingPathComponent:#"funds.xls"];
file = [NSFileHandle fileHandleForReadingAtPath:fileDir];
if (file == nil) NSLog (#"Failed to open file");
[file seekTOOffset: 10];
databuffer = [file readDataOfLength: 5];
[file closeFile];
It finds the directory of the file but gives up at [NSFileHandle fileHandleForReadingAtPath:fileDir].
What should I be doing? I need help with confirming what file type I should use as the source, and how to read it into an array.
When this has been solved, I'm likely to need to read in large amount of data, several columns, 4k rows, a mixture of text & non-integer numbers.
Is there a format or method I should be using when the volume of data is getting to that size?
Be sure to export the data from Excel in CSV format.
It's easy to use NSFileManager to access the file:
NSString *pathName = ...; /// fill in the file's pathname
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:pathName]) {
// read the file contents, see below
}
For small files, you could just say:
NSString *lines = [NSString stringWithContentsOfFile:filePath];
and then proceed to split the string into lines, and process each line.
For large files, better have a look at some more sophisticated techniques, like in Objective-C: Reading a file line by line.
As for parsing the CSV lines, use the NSString method componentsSeparatedByString to tokenize each line, something like:
NSArray *fields = [line componentsSeparatedByString:#","];
Actually, that's also what you would use to split the file contents you read into individual lines. Just pay attention to the line feeds (CR LF or LF). You will find something in how to split a string with newlines.
There is a very popular CocoaPod / Github project that both will write and parse CSV Files. https://github.com/davedelong/CHCSVParser
You can find here: Where can I find a CSV to NSArray parser for Objective-C? quite similar problem, btw. converting CSV to JSON should help you parsing data, since JSON could be easily converted to the NSDictionary or NSArray.
I use Numbers create csv and I have problem when I add "," to table.
I use some trick to fix it.
Sorry I try to add sample code here but it too long.
https://github.com/LovePick/CSVParser-Swift
I want to get the first 8 bytes or so of a file without reading the whole file. I'm using NSData to operate on the data and such, but I don't want to slow down my application with excessive file reads and writes because in some cases I'm having to read a 200 kilobyte file just to extract the first 2 bytes of data from the file. Is there any way to only read or write a part of the file without reading or overwriting the whole thing in Xcode with the iOS SDK?
The file system that I'm using is just the default one that's accessible through the NSFileManager class (I don't know of any other iOS file system).
You may take advantage of the higher level NSFileHandle class. The NSFileHandle class is an object-oriented wrapper for a file descriptor. You use file handle objects to access data associated with files, sockets, pipes, and devices. For files, you can read, write, and seek within the file. For sockets, pipes, and devices, you can use a file handle object to monitor the device and process data asynchronously.
- (NSData *)readDataOfLength:(NSUInteger)length
You can get more info in official documentation NSFileHandle Class Reference
Use the standard C file API (either FILE* or int file descriptors). The caveat is that you have to properly convert the string path to a correct char* file path. Also, don't forget to close the file when done. Consider a category on NSData, something kinda like this...
+ (id)dataWithContentsOfFile:(NSString *)filePath numBytes:(NSUInteger)numBytes
{
void *bytes = malloc(numBytes);
NSData *result = [NSData dataWithBytesNoCopy:bytes length:numBytes];
char const *path = [[NSFileManager defaultManager] fileSystemRepresentationWithPath:filePath];
int fd;
if ((fd = open(path, O_RDONLY)) < 0 || read(fd, bytes, numBytes) != numBytes) {
result = nil;
}
close(fd);
return result;
}
I 've use
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(inImage)];
CC_MD5(imageData, [imageData length], result);
for generate MD5 code of my picture and add them to NSDictionary for compare the image from photoLibrary.
But when I add some code or reboot my device , I find the hash code is totally changed .
How can resolve this problem ?
You should use
NSData *imageData = [NSData dataWithContentsOfFile:file];
CC_MD5(imageData, [imageData length], result);
that must work fine.
Also consider to use sha1 as basing algorithm.
PNG file format allows to have timestamps inside the binary data. This will be different every time you call UIImagePNGRepresentation. I am afraid you can't use MD5 to compare the data of two images this way. Try to extract the raw image data from the files and generate MD5 of the raw data.