🎯 Ejemplos recomendados
Balanced sample collections from various categories for you to explore
Ejemplos de Operaciones de Archivos macOS Objective-C
Ejemplos de operaciones de archivos macOS Objective-C incluyendo lectura/escritura de archivos de texto, copiar/mover archivos, recorrido de directorios y validación de archivos
💻 Lectura/Escritura de Archivos de Texto objectivec
🟢 simple
⭐⭐
Leer y escribir archivos de texto con varias opciones de codificación y manejo de errores
⏱️ 20 min
🏷️ objectivec, macos, file operations, io
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Text File Read/Write Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic Text File Writing
@interface TextFileWriter : NSObject
// Write simple text to file
+ (BOOL)writeText:(NSString *)text toFile:(NSString *)path error:(NSError **)error {
return [text writeToFile:path
atomically:YES
encoding:NSUTF8StringEncoding
error:error];
}
// Write text with specific encoding
+ (BOOL)writeText:(NSString *)text
toFile:(NSString *)path
encoding:(NSStringEncoding)encoding
error:(NSError **)error {
BOOL success = [text writeToFile:path
atomically:YES
encoding:encoding
error:error];
if (success) {
NSLog(@"Text written with encoding %ld to: %@", (long)encoding, path);
}
return success;
}
// Append text to existing file
+ (BOOL)appendText:(NSString *)text toFile:(NSString *)path error:(NSError **)error {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
if (fileHandle) {
// File exists, append to it
[fileHandle seekToEndOfFile];
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
[fileHandle writeData:data];
[fileHandle closeFile];
NSLog(@"Text appended to: %@", path);
return YES;
} else {
// File doesn't exist, create new
return [self writeText:text toFile:path error:error];
}
}
// Write text with line endings
+ (BOOL)writeLines:(NSArray<NSString *> *)lines
toFile:(NSString *)path
error:(NSError **)error {
NSString *content = [lines componentsJoinedByString:@"\n"];
BOOL success = [self writeText:content toFile:path error:error];
if (success) {
NSLog(@"%lu lines written to: %@", (unsigned long)lines.count, path);
}
return success;
}
// Write with NSData (more control)
+ (BOOL)writeData:(NSData *)data toFile:(NSString *)path error:(NSError **)error {
BOOL success = [[NSFileManager defaultManager] createFileAtPath:path
contents:data
attributes:nil];
if (success) {
NSLog(@"File created at: %@", path);
}
return success;
}
@end
// MARK: - 2. Basic Text File Reading
@interface TextFileReader : NSObject
// Read entire file as string
+ (NSString *)readTextFromFile:(NSString *)path error:(NSError **)error {
NSString *content = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:error];
if (content && !*error) {
NSLog(@"Read %lu characters from: %@", (unsigned long)content.length, path);
}
return content;
}
// Read with encoding detection
+ (NSString *)readTextWithEncodingFromFile:(NSString *)path error:(NSError **)error {
NSStringEncoding encodings[] = {
NSUTF8StringEncoding,
NSUTF16StringEncoding,
NSASCIIStringEncoding,
NSISOLatin1StringEncoding
};
NSInteger encodingCount = sizeof(encodings) / sizeof(NSStringEncoding);
for (NSInteger i = 0; i < encodingCount; i++) {
NSString *content = [NSString stringWithContentsOfFile:path
encoding:encodings[i]
error:NULL];
if (content) {
NSLog(@"Read file with encoding: %ld", (long)encodings[i]);
return content;
}
}
if (error) {
*error = [NSError errorWithDomain:@"ReadError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Could not read file with any supported encoding"}];
}
return nil;
}
// Read line by line
+ (NSArray<NSString *> *)readLinesFromFile:(NSString *)path error:(NSError **)error {
NSString *content = [self readTextFromFile:path error:error];
if (!content) return nil;
NSArray *lines = [content componentsSeparatedByString:@"\n"];
NSLog(@"Read %lu lines from: %@", (unsigned long)lines.count, path);
return lines;
}
// Read with NSFileHandle (for large files)
+ (NSString *)readWithFileHandleFromFile:(NSString *)path error:(NSError **)error {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
if (!fileHandle) {
if (error) {
*error = [NSError errorWithDomain:@"ReadError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to open file for reading"}];
}
return nil;
}
NSData *data = [fileHandle readDataToEndOfFile];
[fileHandle closeFile];
NSString *content = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
if (content) {
NSLog(@"Read %lu bytes using FileHandle", (unsigned long)data.length);
}
return content;
}
// Read specific range
+ (NSString *)readRangeFromFile:(NSString *)path
start:(NSUInteger)start
length:(NSUInteger)length
error:(NSError **)error {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
if (!fileHandle) {
if (error) {
*error = [NSError errorWithDomain:@"ReadError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to open file"}];
}
return nil;
}
[fileHandle seekToFileOffset:start];
NSData *data = [fileHandle readDataOfLength:length];
[fileHandle closeFile];
NSString *content = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
if (content) {
NSLog(@"Read %lu bytes from offset %lu", (unsigned long)length, (unsigned long)start);
}
return content;
}
@end
// MARK: - 3. File Info Helper
@interface FileInfoHelper : NSObject
+ (NSDictionary<NSFileAttributeKey, id> *)getAttributesAtPath:(NSString *)path {
return [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
}
+ (void)printFileInfoAtPath:(NSString *)path {
NSDictionary *attributes = [self getAttributesAtPath:path];
if (!attributes) {
NSLog(@"No file info available for: %@", path);
return;
}
NSLog(@"\n--- File Info: %@ ---", path);
NSNumber *fileSize = attributes[NSFileSize];
if (fileSize) {
NSLog(@"Size: %@ bytes", fileSize);
}
NSDate *modifiedDate = attributes[NSFileModificationDate];
if (modifiedDate) {
NSLog(@"Modified: %@", modifiedDate);
}
NSFileAttributeType fileType = attributes[NSFileType];
if (fileType) {
NSLog(@"Type: %@", fileType);
}
}
@end
// MARK: - 4. Advanced Text Operations
@interface AdvancedTextOperations : NSObject
// Search for text in file
+ (NSArray<NSDictionary *> *)searchInFile:(NSString *)path
forText:(NSString *)searchText
error:(NSError **)error {
NSArray *lines = [TextFileReader readLinesFromFile:path error:error];
if (!lines) return nil;
NSMutableArray *results = [NSMutableArray array];
[lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
NSRange range = [line rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
[results addObject:@{
@"line": line,
@"lineNumber": @(idx + 1)
}];
}
}];
return [results copy];
}
// Replace text in file
+ (BOOL)replaceInFile:(NSString *)path
text:(NSString *)searchText
withText:(NSString *)replaceWith
error:(NSError **)error {
NSString *content = [TextFileReader readTextFromFile:path error:error];
if (!content) return NO;
NSString *modified = [content stringByReplacingOccurrencesOfString:searchText
withString:replaceWith];
BOOL success = [TextFileWriter writeText:modified toFile:path error:error];
if (success) {
NSLog(@"Replaced occurrences of '%@' in: %@", searchText, path);
}
return success;
}
// Count words in file
+ (NSInteger)countWordsInFile:(NSString *)path error:(NSError **)error {
NSString *content = [TextFileReader readTextFromFile:path error:error];
if (!content) return 0;
NSArray *words = [content componentsSeparatedByCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"length > 0"];
NSArray *nonEmptyWords = [words filteredArrayUsingPredicate:predicate];
return nonEmptyWords.count;
}
// Read and parse CSV
+ (NSArray<NSArray<NSString *> *> *)readCSVFromFile:(NSString *)path error:(NSError **)error {
NSString *content = [TextFileReader readTextFromFile:path error:error];
if (!content) return nil;
NSArray *lines = [content componentsSeparatedByString:@"\n"];
NSMutableArray *csvData = [NSMutableArray array];
for (NSString *line in lines) {
if (line.length > 0) {
NSArray *fields = [line componentsSeparatedByString:@","];
[csvData addObject:fields];
}
}
return [csvData copy];
}
// Write JSON to file
+ (BOOL)writeJSON:(id)jsonObject
toFile:(NSString *)path
error:(NSError **)error {
if (![NSJSONSerialization isValidJSONObject:jsonObject]) {
if (error) {
*error = [NSError errorWithDomain:@"JSONError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Invalid JSON object"}];
}
return NO;
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject
options:NSJSONWritingPrettyPrinted
error:error];
if (!jsonData) return NO;
NSString *jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
BOOL success = [TextFileWriter writeText:jsonString toFile:path error:error];
if (success) {
NSLog(@"JSON written to: %@", path);
}
return success;
}
// Read JSON from file
+ (id)readJSONFromFile:(NSString *)path error:(NSError **)error {
NSString *content = [TextFileReader readTextFromFile:path error:error];
if (!content) return nil;
NSData *jsonData = [content dataUsingEncoding:NSUTF8StringEncoding];
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:error];
if (jsonObject) {
NSLog(@"JSON decoded from: %@", path);
}
return jsonObject;
}
@end
// MARK: - 5. Safe File Operations
@interface SafeFileOperations : NSObject
typedef NS_ENUM(NSInteger, FileError) {
FileErrorNotFound = 1,
FileErrorPermissionDenied = 2,
FileErrorInvalidEncoding = 3,
FileErrorWriteFailed = 4
};
// Safe read with comprehensive error handling
+ (NSString *)safeReadFromFile:(NSString *)path error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:FileErrorNotFound
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"File not found: %@", path]}];
}
return nil;
}
if (![fileManager isReadableFileAtPath:path]) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:FileErrorPermissionDenied
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Permission denied: %@", path]}];
}
return nil;
}
return [TextFileReader readTextFromFile:path error:error];
}
// Safe write with backup
+ (BOOL)safeWrite:(NSString *)text
toFile:(NSString *)path
createBackup:(BOOL)createBackup
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create backup if requested and file exists
if (createBackup && [fileManager fileExistsAtPath:path]) {
NSString *backupPath = [path stringByAppendingString:@".backup"];
if (![fileManager copyItemAtPath:path toPath:backupPath error:error]) {
return NO;
}
NSLog(@"Backup created at: %@", backupPath);
}
return [TextFileWriter writeText:text toFile:path error:error];
}
@end
// MARK: - 6. Encoding Handler
@interface EncodingHandler : NSObject
// Detect file encoding
+ (NSStringEncoding)detectEncodingForFile:(NSString *)path {
NSStringEncoding encodings[] = {
NSUTF8StringEncoding,
NSUTF16StringEncoding,
NSUTF16BigEndianStringEncoding,
NSUTF32StringEncoding,
NSASCIIStringEncoding
};
NSInteger encodingCount = sizeof(encodings) / sizeof(NSStringEncoding);
for (NSInteger i = 0; i < encodingCount; i++) {
NSString *content = [NSString stringWithContentsOfFile:path
encoding:encodings[i]
error:NULL];
if (content) {
NSLog(@"Detected encoding: %ld", (long)encodings[i]);
return encodings[i];
}
}
return NSUTF8StringEncoding; // Default
}
// Convert file encoding
+ (BOOL)convertEncodingForFile:(NSString *)path
toEncoding:(NSStringEncoding)targetEncoding
error:(NSError **)error {
NSStringEncoding sourceEncoding = [self detectEncodingForFile:path];
NSString *content = [NSString stringWithContentsOfFile:path
encoding:sourceEncoding
error:error];
if (!content) return NO;
BOOL success = [content writeToFile:path
atomically:YES
encoding:targetEncoding
error:error];
if (success) {
NSLog(@"Converted encoding from %ld to %ld",
(long)sourceEncoding, (long)targetEncoding);
}
return success;
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Text File Read/Write Examples ===\n");
NSString *testFile = @"/tmp/test_text_file.txt";
NSString *testContent = @"Hello, World!\nThis is a test file.\nCreated with Objective-C on macOS.";
// 1. Basic write
NSLog(@"--- 1. Basic Write ---");
NSError *error = nil;
BOOL success = [TextFileWriter writeText:testContent toFile:testFile error:&error];
if (!success) {
NSLog(@"Error writing file: %@", error.localizedDescription);
}
// 2. Basic read
NSLog(@"\n--- 2. Basic Read ---");
NSString *content = [TextFileReader readTextFromFile:testFile error:&error];
if (content) {
NSLog(@"Content:\n%@", content);
} else {
NSLog(@"Error reading file: %@", error.localizedDescription);
}
// 3. Read lines
NSLog(@"\n--- 3. Read Lines ---");
NSArray *lines = [TextFileReader readLinesFromFile:testFile error:&error];
if (lines) {
NSLog(@"%lu lines:", (unsigned long)lines.count);
[lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
NSLog(@" %lu: %@", (unsigned long)(idx + 1), line);
}];
}
// 4. Append text
NSLog(@"\n--- 4. Append Text ---");
success = [TextFileWriter appendText:@"\nAppended line!" toFile:testFile error:&error];
if (success) {
NSString *updated = [TextFileReader readTextFromFile:testFile error:&error];
NSArray *updatedLines = [updated componentsSeparatedByString:@"\n"];
NSLog(@"Updated content (last line): %@",
[updatedLines lastObject]);
}
// 5. File info
NSLog(@"\n--- 5. File Info ---");
[FileInfoHelper printFileInfoAtPath:testFile];
// 6. Word count
NSLog(@"\n--- 6. Word Count ---");
NSInteger wordCount = [AdvancedTextOperations countWordsInFile:testFile error:&error];
NSLog(@"Total words: %ld", (long)wordCount);
// 7. Search in file
NSLog(@"\n--- 7. Search in File ---");
NSArray *results = [AdvancedTextOperations searchInFile:testFile
forText:@"macOS"
error:&error];
NSLog(@"Found %lu occurrences of 'macOS':", (unsigned long)results.count);
for (NSDictionary *result in results) {
NSLog(@" Line %@: %@", result[@"lineNumber"], result[@"line"]);
}
// 8. JSON operations
NSLog(@"\n--- 8. JSON Operations ---");
NSDictionary *user = @{
@"name": @"John Doe",
@"email": @"[email protected]",
@"age": @30
};
NSString *jsonFile = @"/tmp/user.json";
success = [AdvancedTextOperations writeJSON:user toFile:jsonFile error:&error];
if (success) {
NSDictionary *decodedUser = [AdvancedTextOperations readJSONFromFile:jsonFile error:&error];
NSLog(@"Decoded: %@ - %@", decodedUser[@"name"], decodedUser[@"email"]);
}
// 9. Safe operations
NSLog(@"\n--- 9. Safe Operations ---");
NSString *safeRead = [SafeFileOperations safeReadFromFile:testFile error:&error];
if (safeRead) {
NSLog(@"Safe read successful: %@...",
[safeRead substringToIndex:MIN(50, safeRead.length)]);
}
// 10. Encoding detection
NSLog(@"\n--- 10. Encoding Detection ---");
NSStringEncoding encoding = [EncodingHandler detectEncodingForFile:testFile];
NSLog(@"Detected encoding: %ld", (long)encoding);
NSLog(@"\n=== All Text File Operations Completed ===");
}
return 0;
}
💻 Validación de Archivos objectivec
🟢 simple
⭐⭐⭐
Verificar existencia de archivos, obtener información de archivos, validar tipos de archivos y comparar archivos
⏱️ 20 min
🏷️ objectivec, macos, file operations, validation
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C File Validation Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
// MARK: - 1. Basic File Existence Check
@interface FileChecker : NSObject
// Check if file exists
+ (BOOL)fileExistsAtPath:(NSString *)path {
return [[NSFileManager defaultManager] fileExistsAtPath:path];
}
// Check if path is a file (not directory)
+ (BOOL)isFileAtPath:(NSString *)path {
BOOL isDirectory = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
return exists && !isDirectory;
}
// Check if path is a directory
+ (BOOL)isDirectoryAtPath:(NSString *)path {
BOOL isDirectory = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
return exists && isDirectory;
}
// Check if file is readable
+ (BOOL)isReadableAtPath:(NSString *)path {
return [[NSFileManager defaultManager] isReadableFileAtPath:path];
}
// Check if file is writable
+ (BOOL)isWritableAtPath:(NSString *)path {
return [[NSFileManager defaultManager] isWritableFileAtPath:path];
}
// Check if file is deletable
+ (BOOL)isDeletableAtPath:(NSString *)path {
return [[NSFileManager defaultManager] isDeletableFileAtPath:path];
}
// Comprehensive file check
+ (NSDictionary *)checkFileAtPath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSMutableDictionary *result = [NSMutableDictionary dictionary];
if (![fileManager fileExistsAtPath:path]) {
result[@"status"] = @"notFound";
result[@"isReadable"] = @NO;
result[@"isWritable"] = @NO;
result[@"isExecutable"] = @NO;
return [result copy];
}
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:path isDirectory:&isDirectory];
result[@"status"] = isDirectory ? @"directory" : @"file";
result[@"isReadable"] = @([fileManager isReadableFileAtPath:path]);
result[@"isWritable"] = @([fileManager isWritableFileAtPath:path]);
result[@"isExecutable"] = @([fileManager isExecutableFileAtPath:path]);
return [result copy];
}
@end
// MARK: - 2. File Information
@interface FileInfo : NSObject
// Get complete file attributes
+ (NSDictionary<NSFileAttributeKey, id> *)getAttributesAtPath:(NSString *)path {
return [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
}
// Get file size
+ (unsigned long long)getSizeAtPath:(NSString *)path {
NSDictionary *attributes = [self getAttributesAtPath:path];
return [attributes[NSFileSize] unsignedLongLongValue];
}
// Get creation date
+ (NSDate *)getCreationDateAtPath:(NSString *)path {
NSDictionary *attributes = [self getAttributesAtPath:path];
return attributes[NSFileCreationDate];
}
// Get modification date
+ (NSDate *)getModificationDateAtPath:(NSString *)path {
NSDictionary *attributes = [self getAttributesAtPath:path];
return attributes[NSFileModificationDate];
}
// Get file extension
+ (NSString *)getExtensionAtPath:(NSString *)path {
return [path pathExtension];
}
// Get file name without extension
+ (NSString *)getNameWithoutExtensionAtPath:(NSString *)path {
return [path stringByDeletingPathExtension];
}
// Get MIME type
+ (NSString *)getMIMETypeAtPath:(NSString *)path {
NSString *extension = [self getExtensionAtPath:path];
return [self MIMETypeForExtension:extension];
}
+ (NSString *)MIMETypeForExtension:(NSString *)extension {
NSDictionary *mimeTypes = @{
@"html": @"text/html",
@"htm": @"text/html",
@"css": @"text/css",
@"js": @"application/javascript",
@"json": @"application/json",
@"xml": @"application/xml",
@"txt": @"text/plain",
@"png": @"image/png",
@"jpg": @"image/jpeg",
@"jpeg": @"image/jpeg",
@"gif": @"image/gif",
@"pdf": @"application/pdf",
@"zip": @"application/zip"
};
return mimeTypes[extension.lowercaseString] ?: @"application/octet-stream";
}
@end
// MARK: - 3. File Type Validation
@interface FileTypeValidator : NSObject
// Validate by extension
+ (BOOL)isValidExtensionAtPath:(NSString *)path
validExtensions:(NSArray<NSString *> *)extensions {
NSString *ext = [[path pathExtension] lowercaseString];
return [extensions containsObject:ext];
}
// Validate image file
+ (BOOL)isImageFileAtPath:(NSString *)path {
NSArray *imageExtensions = @[@"jpg", @"jpeg", @"png", @"gif", @"bmp", @"tiff", @"webp", @"ico"];
return [self isValidExtensionAtPath:path validExtensions:imageExtensions];
}
// Validate text file
+ (BOOL)isTextFileAtPath:(NSString *)path {
NSArray *textExtensions = @[@"txt", @"md", @"html", @"css", @"js", @"json", @"xml", @"csv"];
return [self isValidExtensionAtPath:path validExtensions:textExtensions];
}
// Check if file is empty
+ (BOOL)isEmptyFileAtPath:(NSString *)path {
unsigned long long size = [FileInfo getSizeAtPath:path];
return size == 0;
}
// Validate file size constraints
+ (BOOL)isSizeValidAtPath:(NSString *)path
minSize:(unsigned long long)minSize
maxSize:(unsigned long long)maxSize {
unsigned long long size = [FileInfo getSizeAtPath:path];
return size >= minSize && size <= maxSize;
}
@end
// MARK: - 4. File Comparison
@interface FileComparator : NSObject
// Compare files by size
+ (NSComparisonResult)compareSizeAtPath:(NSString *)path1
andPath:(NSString *)path2 {
unsigned long long size1 = [FileInfo getSizeAtPath:path1];
unsigned long long size2 = [FileInfo getSizeAtPath:path2];
if (size1 < size2) {
return NSOrderedAscending;
} else if (size1 > size2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
// Compare files by content
+ (BOOL)compareContentAtPath:(NSString *)path1 andPath:(NSString *)path2 {
NSData *data1 = [NSData dataWithContentsOfFile:path1];
NSData *data2 = [NSData dataWithContentsOfFile:path2];
if (!data1 || !data2) return NO;
return [data1 isEqualToData:data2];
}
// Compare files by modification date
+ (NSComparisonResult)compareModificationDateAtPath:(NSString *)path1
andPath:(NSString *)path2 {
NSDate *date1 = [FileInfo getModificationDateAtPath:path1];
NSDate *date2 = [FileInfo getModificationDateAtPath:path2];
return [date1 compare:date2];
}
// Check if files are identical
+ (BOOL)areFilesIdenticalAtPath:(NSString *)path1 andPath:(NSString *)path2 {
NSComparisonResult sizeResult = [self compareSizeAtPath:path1 andPath:path2];
if (sizeResult != NSOrderedSame) {
return NO;
}
return [self compareContentAtPath:path1 andPath:path2];
}
// Calculate file checksum (SHA256)
+ (NSString *)calculateChecksumAtPath:(NSString *)path {
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data) return nil;
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *hash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", digest[i]];
}
return [hash copy];
}
// Compare using checksum
+ (BOOL)compareChecksumAtPath:(NSString *)path1 andPath:(NSString *)path2 {
NSString *hash1 = [self calculateChecksumAtPath:path1];
NSString *hash2 = [self calculateChecksumAtPath:path2];
return [hash1 isEqualToString:hash2];
}
@end
// MARK: - 5. Path Validation
@interface PathValidator : NSObject
// Validate path format
+ (BOOL)isValidPath:(NSString *)path {
return path.length > 0 && [path isAbsolutePath];
}
// Get absolute path from relative
+ (NSString *)getAbsolutePathForPath:(NSString *)path {
return [[NSFileManager defaultManager] currentDirectoryPath];
}
// Resolve path with tilde
+ (NSString *)resolveTildeInPath:(NSString *)path {
return [path stringByExpandingTildeInPath];
}
// Validate file name
+ (BOOL)isValidFileName:(NSString *)name {
NSCharacterSet *invalidChars = [NSCharacterSet characterSetWithCharactersInString:@"\\/:*?\"<>|"];
return [name rangeOfCharacterFromSet:invalidChars].location == NSNotFound && name.length > 0;
}
// Sanitize file name
+ (NSString *)sanitizeFileName:(NSString *)name {
NSCharacterSet *invalidChars = [NSCharacterSet characterSetWithCharactersInString:@"\\/:*?\"<>|"];
return [[name componentsSeparatedByCharactersInSet:invalidChars]
componentsJoinedByString:@"_"];
}
@end
// MARK: - 6. File Integrity Checker
@interface FileIntegrityChecker : NSObject
// Verify file hasn't been corrupted
+ (BOOL)verifyIntegrityAtPath:(NSString *)path
againstExpectedHash:(NSString *)expectedHash {
NSString *actualHash = [FileComparator calculateChecksumAtPath:path];
if (!actualHash) return NO;
return [actualHash caseInsensitiveCompare:expectedHash] == NSOrderedSame;
}
// Generate hash file for integrity checking
+ (NSString *)generateHashFileAtPath:(NSString *)path {
return [FileComparator calculateChecksumAtPath:path];
}
// Quick check (just size)
+ (BOOL)quickCheckAtPath:(NSString *)path expectedSize:(unsigned long long)expectedSize {
unsigned long long actualSize = [FileInfo getSizeAtPath:path];
return actualSize == expectedSize;
}
@end
// MARK: - Helper Functions
static NSString *formatBytes(unsigned long long bytes) {
double kb = bytes / 1024.0;
double mb = kb / 1024.0;
double gb = mb / 1024.0;
if (gb >= 1) {
return [NSString stringWithFormat:@"%.2f GB", gb];
} else if (mb >= 1) {
return [NSString stringWithFormat:@"%.2f MB", mb];
} else if (kb >= 1) {
return [NSString stringWithFormat:@"%.2f KB", kb];
} else {
return [NSString stringWithFormat:@"%llu B", bytes];
}
}
static NSString *formatDate(NSDate *date) {
static NSDateFormatter *formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
formatter = [[NSDateFormatter alloc] init];
formatter.dateStyle = NSDateFormatterMediumStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
});
return [formatter stringFromDate:date];
}
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C File Validation Examples ===\n");
NSString *testFile = @"/tmp/validation_test.txt";
NSString *testDir = @"/tmp/validation_test_dir";
// Create test file
NSFileManager *fileManager = [NSFileManager defaultManager];
[@"Test content for validation" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[fileManager createDirectoryAtPath:testDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
// 1. File existence checks
NSLog(@"--- 1. File Existence Checks ---");
NSLog(@"File exists: %@", [FileChecker fileExistsAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Is file: %@", [FileChecker isFileAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Is directory: %@", [FileChecker isDirectoryAtPath:testDir] ? @"YES" : @"NO");
NSLog(@"Is readable: %@", [FileChecker isReadableAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Is writable: %@", [FileChecker isWritableAtPath:testFile] ? @"YES" : @"NO");
// 2. Comprehensive file check
NSLog(@"\n--- 2. Comprehensive File Check ---");
NSDictionary *status = [FileChecker checkFileAtPath:testFile];
NSLog(@"Status: %@", status[@"status"]);
NSLog(@"Readable: %@", status[@"isReadable"]);
NSLog(@"Writable: %@", status[@"isWritable"]);
NSLog(@"Executable: %@", status[@"isExecutable"]);
// 3. File information
NSLog(@"\n--- 3. File Information ---");
unsigned long long size = [FileInfo getSizeAtPath:testFile];
NSLog(@"Size: %@ %@", formatBytes(size), @"bytes");
NSDate *modDate = [FileInfo getModificationDateAtPath:testFile];
NSLog(@"Modified: %@", formatDate(modDate));
NSLog(@"Extension: %@", [FileInfo getExtensionAtPath:testFile]);
NSLog(@"Name without ext: %@", [FileInfo getNameWithoutExtensionAtPath:testFile]);
// 4. File type validation
NSLog(@"\n--- 4. File Type Validation ---");
NSLog(@"Is text file: %@", [FileTypeValidator isTextFileAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Is image file: %@", [FileTypeValidator isImageFileAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Is empty: %@", [FileTypeValidator isEmptyFileAtPath:testFile] ? @"YES" : @"NO");
NSLog(@"Size valid (1-1000 bytes): %@",
[FileTypeValidator isSizeValidAtPath:testFile minSize:1 maxSize:1000] ? @"YES" : @"NO");
// 5. File comparison
NSLog(@"\n--- 5. File Comparison ---");
NSString *testFile2 = @"/tmp/validation_test2.txt";
[@"Different content" writeToFile:testFile2
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
NSComparisonResult sizeCompare = [FileComparator compareSizeAtPath:testFile andPath:testFile2];
NSLog(@"Size comparison: %@", sizeCompare == NSOrderedAscending ? @"less than" :
sizeCompare == NSOrderedDescending ? @"greater than" : @"equal");
BOOL contentEqual = [FileComparator compareContentAtPath:testFile andPath:testFile2];
NSLog(@"Content equal: %@", contentEqual ? @"YES" : @"NO");
// 6. Checksum
NSLog(@"\n--- 6. Checksum ---");
NSString *checksum = [FileComparator calculateChecksumAtPath:testFile];
NSLog(@"SHA256: %@", checksum);
BOOL valid = [FileIntegrityChecker verifyIntegrityAtPath:testFile
againstExpectedHash:checksum];
NSLog(@"Integrity check: %@", valid ? @"PASSED" : @"FAILED");
// 7. Path validation
NSLog(@"\n--- 7. Path Validation ---");
NSString *relativePath = @"./test.txt";
NSLog(@"Is absolute path: %@", [PathValidator isValidPath:testFile] ? @"YES" : @"NO");
NSLog(@"Valid filename 'test.txt': %@", [PathValidator isValidFileName:@"test.txt"] ? @"YES" : @"NO");
NSLog(@"Valid filename 'test?.txt': %@", [PathValidator isValidFileName:@"test?.txt"] ? @"YES" : @"NO");
NSLog(@"Sanitized name: %@", [PathValidator sanitizeFileName:@"test?.txt"]);
// Cleanup
[fileManager removeItemAtPath:testFile error:nil];
[fileManager removeItemAtPath:testFile2 error:nil];
[fileManager removeItemAtPath:testDir error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== All File Validation Examples Completed ===");
}
return 0;
}
💻 Copiar/Mover Archivos objectivec
🟡 intermediate
⭐⭐⭐
Copiar y mover archivos con opciones de sobrescritura, seguimiento de progreso y recuperación de errores
⏱️ 25 min
🏷️ objectivec, macos, file operations
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C File Copy/Move Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic File Copy
@interface FileCopier : NSObject
// Simple copy
+ (BOOL)copyFileFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager copyItemAtPath:source toPath:destination error:error];
if (success) {
NSLog(@"Copied: %@ -> %@", source, destination);
}
return success;
}
// Copy with overwrite option
+ (BOOL)copyFileFrom:(NSString *)source
to:(NSString *)destination
overwrite:(BOOL)overwrite
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if destination exists
if ([fileManager fileExistsAtPath:destination]) {
if (overwrite) {
// Remove existing file
[fileManager removeItemAtPath:destination error:nil];
NSLog(@"Removed existing file: %@", destination);
} else {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"File already exists: %@", destination]}];
}
return NO;
}
}
return [self copyFileFrom:source to:destination error:error];
}
// Copy to directory
+ (BOOL)copyFileFrom:(NSString *)source toDirectory:(NSString *)directory error:(NSError **)error {
NSString *fileName = [source lastPathComponent];
NSString *destination = [directory stringByAppendingPathComponent:fileName];
return [self copyFileFrom:source to:destination error:error];
}
// Copy with NSURL
+ (BOOL)copyFileFromURL:(NSURL *)sourceURL toURL:(NSURL *)destinationURL error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create destination directory if needed
NSString *destPath = [destinationURL path];
NSString *destDir = [destPath stringByDeletingLastPathComponent];
if (![fileManager fileExistsAtPath:destDir]) {
[fileManager createDirectoryAtPath:destDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
BOOL success = [fileManager copyItemAtURL:sourceURL toURL:destinationURL error:error];
if (success) {
NSLog(@"Copied: %@ -> %@", [sourceURL path], [destinationURL path]);
}
return success;
}
// Copy with progress callback
+ (BOOL)copyFileFrom:(NSString *)source
to:(NSString *)destination
progress:(void (^)(double progress))progressBlock
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:source]) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Source file not found: %@", source]}];
}
return NO;
}
NSDictionary *attributes = [fileManager attributesOfItemAtPath:source error:error];
if (!attributes) return NO;
unsigned long long fileSize = [attributes[NSFileSize] unsignedLongLongValue];
// Read source in chunks
NSFileHandle *sourceHandle = [NSFileHandle fileHandleForReadingAtPath:source];
if (!sourceHandle) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to open source file"}];
}
return NO;
}
// Create destination
[fileManager createFileAtPath:destination contents:nil attributes:nil];
NSFileHandle *destHandle = [NSFileHandle fileHandleForWritingAtPath:destination];
if (!destHandle) {
[sourceHandle closeFile];
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to create destination file"}];
}
return NO;
}
const NSUInteger chunkSize = 1024 * 1024; // 1MB chunks
unsigned long long bytesCopied = 0;
while (YES) {
@autoreleasepool {
NSData *data = [sourceHandle readDataOfLength:chunkSize];
if (data.length == 0) break;
[destHandle writeData:data];
bytesCopied += data.length;
// Report progress
if (progressBlock) {
double percent = (double)bytesCopied / (double)fileSize;
progressBlock(percent);
}
}
}
[sourceHandle closeFile];
[destHandle closeFile];
NSLog(@"Copy completed: %@", destination);
return YES;
}
@end
// MARK: - 2. Basic File Move
@interface FileMover : NSObject
// Simple move
+ (BOOL)moveFileFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager moveItemAtPath:source toPath:destination error:error];
if (success) {
NSLog(@"Moved: %@ -> %@", source, destination);
}
return success;
}
// Move with overwrite
+ (BOOL)moveFileFrom:(NSString *)source
to:(NSString *)destination
overwrite:(BOOL)overwrite
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:destination]) {
if (overwrite) {
[fileManager removeItemAtPath:destination error:nil];
NSLog(@"Removed existing file: %@", destination);
} else {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"File already exists"}];
}
return NO;
}
}
return [self moveFileFrom:source to:destination error:error];
}
// Move to directory
+ (BOOL)moveFileFrom:(NSString *)source toDirectory:(NSString *)directory error:(NSError **)error {
NSString *fileName = [source lastPathComponent];
NSString *destination = [directory stringByAppendingPathComponent:fileName];
return [self moveFileFrom:source to:destination error:error];
}
// Safe move with backup
+ (BOOL)moveFileFrom:(NSString *)source
to:(NSString *)destination
withBackup:(BOOL)createBackup
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create backup if destination exists
if (createBackup && [fileManager fileExistsAtPath:destination]) {
NSString *backupPath = [destination stringByAppendingString:@".backup"];
if (![fileManager moveItemAtPath:destination toPath:backupPath error:error]) {
return NO;
}
NSLog(@"Backup created: %@", backupPath);
}
return [self moveFileFrom:source to:destination error:error];
}
// Move with NSURL
+ (BOOL)moveFileFromURL:(NSURL *)sourceURL toURL:(NSURL *)destinationURL error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create destination directory if needed
NSString *destPath = [destinationURL path];
NSString *destDir = [destPath stringByDeletingLastPathComponent];
if (![fileManager fileExistsAtPath:destDir]) {
[fileManager createDirectoryAtPath:destDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
BOOL success = [fileManager moveItemAtURL:sourceURL toURL:destinationURL error:error];
if (success) {
NSLog(@"Moved: %@ -> %@", [sourceURL path], [destinationURL path]);
}
return success;
}
@end
// MARK: - 3. Batch Operations
@interface BatchFileOperations : NSObject
// Copy multiple files
+ (void)copyFiles:(NSArray<NSString *> *)sources
toDirectory:(NSString *)destinationDirectory
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
// Ensure destination directory exists
if (![fileManager fileExistsAtPath:destinationDirectory]) {
[fileManager createDirectoryAtPath:destinationDirectory
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
NSInteger successCount = 0;
NSInteger failureCount = 0;
for (NSString *source in sources) {
NSString *fileName = [source lastPathComponent];
NSString *destination = [destinationDirectory stringByAppendingPathComponent:fileName];
NSError *localError = nil;
if ([FileCopier copyFileFrom:source to:destination overwrite:YES error:&localError]) {
successCount++;
} else {
NSLog(@"Failed to copy %@: %@", source, localError.localizedDescription);
failureCount++;
}
}
NSLog(@"Batch copy completed: %ld succeeded, %ld failed",
(long)successCount, (long)failureCount);
}
// Move multiple files
+ (void)moveFiles:(NSArray<NSString *> *)sources
toDirectory:(NSString *)destinationDirectory
error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:destinationDirectory]) {
[fileManager createDirectoryAtPath:destinationDirectory
withIntermediateDirectories:YES
attributes:nil
error:nil];
}
NSInteger successCount = 0;
NSInteger failureCount = 0;
for (NSString *source in sources) {
NSString *fileName = [source lastPathComponent];
NSString *destination = [destinationDirectory stringByAppendingPathComponent:fileName];
NSError *localError = nil;
if ([FileMover moveFileFrom:source to:destination overwrite:YES error:&localError]) {
successCount++;
} else {
NSLog(@"Failed to move %@: %@", source, localError.localizedDescription);
failureCount++;
}
}
NSLog(@"Batch move completed: %ld succeeded, %ld failed",
(long)successCount, (long)failureCount);
}
// Copy directory recursively
+ (BOOL)copyDirectoryFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath:source isDirectory:&isDirectory] || !isDirectory) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Not a directory"}];
}
return NO;
}
BOOL success = [fileManager copyItemAtPath:source toPath:destination error:error];
if (success) {
NSLog(@"Directory copied: %@ -> %@", source, destination);
}
return success;
}
// Move directory
+ (BOOL)moveDirectoryFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath:source isDirectory:&isDirectory] || !isDirectory) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Not a directory"}];
}
return NO;
}
BOOL success = [fileManager moveItemAtPath:source toPath:destination error:error];
if (success) {
NSLog(@"Directory moved: %@ -> %@", source, destination);
}
return success;
}
@end
// MARK: - 4. Smart File Operations
@interface SmartFileOperations : NSObject
// Copy with duplicate handling
+ (BOOL)smartCopyFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:destination]) {
// Add number suffix
NSString *baseName = [destination stringByDeletingPathExtension];
NSString *extension = [destination pathExtension];
NSInteger counter = 1;
NSString *newPath = destination;
while ([fileManager fileExistsAtPath:newPath]) {
if (extension.length > 0) {
newPath = [NSString stringWithFormat:@"%@ %ld.%@",
baseName, (long)counter, extension];
} else {
newPath = [NSString stringWithFormat:@"%@ %ld",
baseName, (long)counter];
}
counter++;
}
NSLog(@"Destination exists, using: %@", newPath);
return [FileCopier copyFileFrom:source to:newPath error:error];
}
return [FileCopier copyFileFrom:source to:destination error:error];
}
// Verified copy
+ (BOOL)verifiedCopyFrom:(NSString *)source to:(NSString *)destination error:(NSError **)error {
NSDictionary *sourceAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:source error:error];
if (!sourceAttrs) return NO;
BOOL success = [FileCopier copyFileFrom:source to:destination overwrite:YES error:error];
if (!success) return NO;
// Verify by comparing file sizes
NSDictionary *destAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destination error:error];
if (!destAttrs) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"Failed to get destination attributes"}];
}
return NO;
}
unsigned long long sourceSize = [sourceAttrs[NSFileSize] unsignedLongLongValue];
unsigned long long destSize = [destAttrs[NSFileSize] unsignedLongLongValue];
if (sourceSize != destSize) {
if (error) {
*error = [NSError errorWithDomain:@"FileError"
code:1
userInfo:@{NSLocalizedDescriptionKey: @"File sizes don't match"}];
}
return NO;
}
NSLog(@"Verified copy: %llu bytes", sourceSize);
return YES;
}
@end
// MARK: - Helper Functions
static NSString *formatBytes(unsigned long long bytes) {
double kb = bytes / 1024.0;
double mb = kb / 1024.0;
double gb = mb / 1024.0;
if (gb >= 1) {
return [NSString stringWithFormat:@"%.2f GB", gb];
} else if (mb >= 1) {
return [NSString stringWithFormat:@"%.2f MB", mb];
} else if (kb >= 1) {
return [NSString stringWithFormat:@"%.2f KB", kb];
} else {
return [NSString stringWithFormat:@"%llu B", bytes];
}
}
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C File Copy/Move Examples ===\n");
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *tempDir = @"/tmp/file_operations_test";
// Create test directory
[fileManager createDirectoryAtPath:tempDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
// Create test file
NSString *sourceFile = @"/tmp/source_test.txt";
NSString *destFile1 = @"/tmp/dest_test1.txt";
NSString *destFile2 = @"/tmp/dest_test2.txt";
NSString *testContent = @"Test content for copy/move";
[testContent writeToFile:sourceFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
// 1. Simple copy
NSLog(@"--- 1. Simple Copy ---");
NSError *error = nil;
BOOL success = [FileCopier copyFileFrom:sourceFile to:destFile1 error:&error];
if (!success) {
NSLog(@"Error: %@", error.localizedDescription);
}
// 2. Copy with progress
NSLog(@"\n--- 2. Copy with Progress ---");
success = [FileCopier copyFileFrom:sourceFile
to:destFile2
progress:^(double progress) {
NSLog(@"Progress: %.0f%%", progress * 100);
} error:&error];
if (!success) {
NSLog(@"Error: %@", error.localizedDescription);
}
// 3. Simple move
NSLog(@"\n--- 3. Simple Move ---");
NSString *moveSource = @"/tmp/move_source.txt";
NSString *moveDest = @"/tmp/move_dest.txt";
[@"File to move" writeToFile:moveSource
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
success = [FileMover moveFileFrom:moveSource to:moveDest error:&error];
if (!success) {
NSLog(@"Error: %@", error.localizedDescription);
}
// 4. Smart copy (handle duplicates)
NSLog(@"\n--- 4. Smart Copy ---");
NSString *smartSource = @"/tmp/smart_source.txt";
NSString *smartDest = @"/tmp/smart_dest.txt";
[@"Smart copy test" writeToFile:smartSource
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
success = [SmartFileOperations smartCopyFrom:smartSource to:smartDest error:&error];
success = [SmartFileOperations smartCopyFrom:smartSource to:smartDest error:&error];
// 5. Batch copy
NSLog(@"\n--- 5. Batch Copy ---");
NSMutableArray *files = [NSMutableArray array];
for (int i = 1; i <= 3; i++) {
NSString *file = [NSString stringWithFormat:@"/tmp/batch_source%d.txt", i];
[NSString stringWithFormat:@"Batch file %d", i] writeToFile:file
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[files addObject:file];
}
[BatchFileOperations copyFiles:files toDirectory:tempDir error:&error];
// 6. Verified copy
NSLog(@"\n--- 6. Verified Copy ---");
NSString *verifySource = @"/tmp/verify_source.txt";
NSString *verifyDest = @"/tmp/verify_dest.txt";
[@"Verification test" writeToFile:verifySource
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
success = [SmartFileOperations verifiedCopyFrom:verifySource to:verifyDest error:&error];
if (!success) {
NSLog(@"Error: %@", error.localizedDescription);
}
// Cleanup
[fileManager removeItemAtPath:tempDir error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== All File Copy/Move Examples Completed ===");
}
return 0;
}
💻 Recorrido de Directorio objectivec
🟡 intermediate
⭐⭐⭐⭐
Recorrer directorios recursivamente, listar archivos con filtros y buscar tipos de archivo específicos
⏱️ 30 min
🏷️ objectivec, macos, file operations, directory
Prerequisites:
Intermediate Objective-C, Foundation framework
// macOS Objective-C Directory Traversal Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic Directory Listing
@interface DirectoryLister : NSObject
// List all items in directory
+ (NSArray<NSString *> *)listDirectoryAtPath:(NSString *)path error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:error];
if (contents) {
NSLog(@"Items in %@:", path);
for (NSString *item in contents) {
NSLog(@" - %@", item);
}
}
return contents;
}
// List with details
+ (NSArray<NSDictionary *> *)listDirectoryWithDetailsAtPath:(NSString *)path error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:error];
if (!contents) return nil;
NSMutableArray *items = [NSMutableArray array];
for (NSString *item in contents) {
NSString *itemPath = [path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
NSMutableDictionary *fileInfo = [NSMutableDictionary dictionary];
fileInfo[@"name"] = item;
fileInfo[@"path"] = itemPath;
fileInfo[@"isDirectory"] = @(isDirectory);
NSDictionary *attributes = [fileManager attributesOfItemAtPath:itemPath error:nil];
fileInfo[@"size"] = attributes[NSFileSize] ?: @(0);
fileInfo[@"modifiedDate"] = attributes[NSFileModificationDate] ?: [NSDate date];
[items addObject:fileInfo];
}
NSLog(@"Files in %@:", path);
for (NSDictionary *item in items) {
NSString *type = [item[@"isDirectory"] boolValue] ? @"DIR " : @"FILE";
NSLog(@" [%@] %@ - %@ bytes",
type, item[@"name"], item[@"size"]);
}
return [items copy];
}
// List only files
+ (NSArray<NSString *> *)listFilesAtPath:(NSString *)path error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:error];
if (!contents) return nil;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *item, NSDictionary *bindings) {
NSString *itemPath = [path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
return !isDirectory;
}];
return [contents filteredArrayUsingPredicate:predicate];
}
// List only subdirectories
+ (NSArray<NSString *> *)listSubdirectoriesAtPath:(NSString *)path error:(NSError **)error {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:error];
if (!contents) return nil;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *item, NSDictionary *bindings) {
NSString *itemPath = [path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
return isDirectory;
}];
return [contents filteredArrayUsingPredicate:predicate];
}
@end
// MARK: - 2. Recursive Directory Traversal
@interface DirectoryTraverser : NSObject
// Recursively find all files
+ (NSArray<NSString *> *)findAllFilesAtPath:(NSString *)path {
NSMutableArray *files = [NSMutableArray array];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:nil];
if (!contents) {
return [files copy];
}
for (NSString *item in contents) {
NSString *itemPath = [path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
if (isDirectory) {
// Recurse into subdirectory
[files addObjectsFromArray:[self findAllFilesAtPath:itemPath]];
} else {
[files addObject:itemPath];
}
}
return [files copy];
}
// Recursive traversal with callback
+ (void)traverseDirectoryAtPath:(NSString *)path
callback:(void (^)(NSString *path, BOOL isDirectory, NSInteger depth))callback {
[self traverseDirectoryAtPath:path depth:0 callback:callback];
}
+ (void)traverseDirectoryAtPath:(NSString *)path
depth:(NSInteger)depth
callback:(void (^)(NSString *path, BOOL isDirectory, NSInteger depth))callback {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:path error:nil];
if (!contents) return;
for (NSString *item in contents) {
NSString *itemPath = [path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
callback(itemPath, isDirectory, depth);
if (isDirectory) {
[self traverseDirectoryAtPath:itemPath
depth:depth + 1
callback:callback];
}
}
}
// Get directory tree
+ (DirectoryNode *)getDirectoryTreeAtPath:(NSString *)path maxDepth:(NSInteger)maxDepth {
DirectoryNode *root = [[DirectoryNode alloc] initWithName:[path lastPathComponent]
path:path
isDirectory:YES
depth:0];
[self buildTreeForNode:root maxDepth:maxDepth];
return root;
}
+ (void)buildTreeForNode:(DirectoryNode *)node maxDepth:(NSInteger)maxDepth {
if (node.depth >= maxDepth) return;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:node.path error:nil];
if (!contents) return;
NSArray *sortedContents = [contents sortedArrayUsingSelector:@selector(compare:)];
for (NSString *item in sortedContents) {
NSString *itemPath = [node.path stringByAppendingPathComponent:item];
BOOL isDirectory = NO;
[fileManager fileExistsAtPath:itemPath isDirectory:&isDirectory];
DirectoryNode *childNode = [[DirectoryNode alloc] initWithName:item
path:itemPath
isDirectory:isDirectory
depth:node.depth + 1];
[node addChild:childNode];
if (isDirectory) {
[self buildTreeForNode:childNode maxDepth:maxDepth];
}
}
}
@end
// Directory Node Class
@interface DirectoryNode : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *path;
@property (nonatomic, assign) BOOL isDirectory;
@property (nonatomic, assign) NSInteger depth;
@property (nonatomic, strong) NSMutableArray<DirectoryNode *> *children;
- (instancetype)initWithName:(NSString *)name
path:(NSString *)path
isDirectory:(BOOL)isDirectory
depth:(NSInteger)depth;
- (void)addChild:(DirectoryNode *)child;
- (void)printTree;
@end
@implementation DirectoryNode
- (instancetype)initWithName:(NSString *)name
path:(NSString *)path
isDirectory:(BOOL)isDirectory
depth:(NSInteger)depth {
self = [super init];
if (self) {
_name = name;
_path = path;
_isDirectory = isDirectory;
_depth = depth;
_children = [NSMutableArray array];
}
return self;
}
- (void)addChild:(DirectoryNode *)child {
[_children addObject:child];
}
- (void)printTree {
NSString *indent = [@"" stringByPaddingToLength:_depth * 2
withString:@" "
startingAtIndex:0];
NSString *prefix = _isDirectory ? @"📁" : @"📄";
NSLog(@"%@%@ %@", indent, prefix, _name);
for (DirectoryNode *child in _children) {
[child printTree];
}
}
@end
// MARK: - 3. File Filtering
@interface FileFilter : NSObject
// Filter by extension
+ (NSArray<NSString *> *)filterFilesAtPath:(NSString *)path
extensions:(NSArray<NSString *> *)extensions {
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *filePath, NSDictionary *bindings) {
NSString *ext = [[filePath pathExtension] lowercaseString];
return [extensions containsObject:ext];
}];
return [files filteredArrayUsingPredicate:predicate];
}
// Filter by name pattern
+ (NSArray<NSString *> *)filterFilesAtPath:(NSString *)path
namePattern:(NSString *)pattern {
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *filePath, NSDictionary *bindings) {
NSString *fileName = [filePath lastPathComponent];
NSRange range = [fileName rangeOfString:pattern
options:NSRegularExpressionSearch
range:NSMakeRange(0, fileName.length)];
return range.location != NSNotFound;
}];
return [files filteredArrayUsingPredicate:predicate];
}
// Filter by size
+ (NSArray<NSString *> *)filterFilesAtPath:(NSString *)path
minSize:(unsigned long long)minSize
maxSize:(unsigned long long)maxSize {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *filePath, NSDictionary *bindings) {
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath error:nil];
if (!attributes) return NO;
unsigned long long size = [attributes[NSFileSize] unsignedLongLongValue];
return size >= minSize && size <= maxSize;
}];
return [files filteredArrayUsingPredicate:predicate];
}
// Find duplicates by size
+ (NSArray<NSArray<NSString *> *> *)findPotentialDuplicatesAtPath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSMutableDictionary *sizeGroups = [NSMutableDictionary dictionary];
for (NSString *filePath in files) {
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath error:nil];
if (!attributes) continue;
unsigned long long size = [attributes[NSFileSize] unsignedLongLongValue];
NSString *key = [NSString stringWithFormat:@"%llu", size];
if (!sizeGroups[key]) {
sizeGroups[key] = [NSMutableArray array];
}
[sizeGroups[key] addObject:filePath];
}
// Filter groups with more than one file
NSMutableArray *duplicates = [NSMutableArray array];
for (NSMutableArray *group in [sizeGroups allValues]) {
if (group.count > 1) {
[duplicates addObject:[group copy]];
}
}
return [duplicates copy];
}
@end
// MARK: - 4. Directory Statistics
@interface DirectoryStatistics : NSObject
+ (NSDictionary *)calculateStatisticsForPath:(NSString *)path {
NSMutableDictionary *stats = [NSMutableDictionary dictionary];
stats[@"totalFiles"] = @0;
stats[@"totalDirectories"] = @0;
stats[@"totalSize"] = @0;
stats[@"extensionCounts"] = [NSMutableDictionary dictionary];
[DirectoryTraverser traverseDirectoryAtPath:path
callback:^(NSString *filePath, BOOL isDirectory, NSInteger depth) {
if (isDirectory) {
NSInteger count = [stats[@"totalDirectories"] integerValue];
stats[@"totalDirectories"] = @(count + 1);
} else {
NSInteger count = [stats[@"totalFiles"] integerValue];
stats[@"totalFiles"] = @(count + 1);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath error:nil];
if (attributes) {
unsigned long long size = [attributes[NSFileSize] unsignedLongLongValue];
unsigned long long currentSize = [stats[@"totalSize"] unsignedLongLongValue];
stats[@"totalSize"] = @(currentSize + size);
// Count extensions
NSString *ext = [[filePath pathExtension] lowercaseString];
NSString *extKey = ext.length > 0 ? ext : @"(no extension)";
NSMutableDictionary *extCounts = stats[@"extensionCounts"];
NSInteger extCount = [extCounts[extKey] integerValue];
extCounts[extKey] = @(extCount + 1);
}
}
}];
return [stats copy];
}
+ (void)printStatistics:(NSDictionary *)stats {
NSLog(@"\n=== Directory Statistics ===");
NSInteger totalFiles = [stats[@"totalFiles"] integerValue];
NSInteger totalDirectories = [stats[@"totalDirectories"] integerValue];
unsigned long long totalSize = [stats[@"totalSize"] unsignedLongLongValue];
NSLog(@"Total files: %ld", (long)totalFiles);
NSLog(@"Total directories: %ld", (long)totalDirectories);
NSLog(@"Total size: %@", formatBytes(totalSize));
NSLog(@"\nExtension counts:");
NSDictionary *extCounts = stats[@"extensionCounts"];
NSArray *sortedKeys = [extCounts keysSortedByValueUsingComparator:^NSComparisonResult(NSNumber *obj1, NSNumber *obj2) {
return [obj2 compare:obj1];
}];
for (NSString *ext in sortedKeys) {
NSInteger count = [extCounts[ext] integerValue];
NSLog(@" .%@: %ld", ext, (long)count);
}
}
static NSString *formatBytes(unsigned long long bytes) {
double kb = bytes / 1024.0;
double mb = kb / 1024.0;
double gb = mb / 1024.0;
if (gb >= 1) {
return [NSString stringWithFormat:@"%.2f GB", gb];
} else if (mb >= 1) {
return [NSString stringWithFormat:@"%.2f MB", mb];
} else if (kb >= 1) {
return [NSString stringWithFormat:@"%.2f KB", kb];
} else {
return [NSString stringWithFormat:@"%llu B", bytes];
}
}
@end
// MARK: - 5. File Searcher
@interface FileSearcher : NSObject
// Search files by name
+ (NSArray<NSString *> *)searchFilesAtPath:(NSString *)path forName:(NSString *)name {
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *filePath, NSDictionary *bindings) {
NSString *fileName = [filePath lastPathComponent];
NSRange range = [fileName rangeOfString:name
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, fileName.length)];
return range.location != NSNotFound;
}];
return [files filteredArrayUsingPredicate:predicate];
}
// Search files containing text
+ (NSArray<NSString *> *)searchFilesAtPath:(NSString *)path forText:(NSString *)searchText {
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSMutableArray *matches = [NSMutableArray array];
for (NSString *filePath in files) {
NSString *content = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:nil];
if (content) {
NSRange range = [content rangeOfString:searchText
options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
[matches addObject:filePath];
}
}
}
return [matches copy];
}
// Find recently modified files
+ (NSArray<NSString *> *)findRecentlyModifiedFilesAtPath:(NSString *)path
within:(NSTimeInterval)seconds {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *files = [DirectoryTraverser findAllFilesAtPath:path];
NSDate *cutoffDate = [NSDate dateWithTimeIntervalSinceNow:-seconds];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *filePath, NSDictionary *bindings) {
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath error:nil];
if (!attributes) return NO;
NSDate *modifiedDate = attributes[NSFileModificationDate];
return [modifiedDate compare:cutoffDate] == NSOrderedDescending;
}];
return [files filteredArrayUsingPredicate:predicate];
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Directory Traversal Examples ===\n");
NSString *testDir = @"/tmp/directory_traversal_test";
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create test directory structure
[fileManager createDirectoryAtPath:testDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
// Create test files
[@"" writeToFile:[testDir stringByAppendingPathComponent:@"file1.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[@"" writeToFile:[testDir stringByAppendingPathComponent:@"file2.md"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
// Create subdirectory
NSString *subDir = [testDir stringByAppendingPathComponent:@"subdir"];
[fileManager createDirectoryAtPath:subDir
withIntermediateDirectories:YES
attributes:nil
error:nil];
[@"" writeToFile:[subDir stringByAppendingPathComponent:@"subfile1.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
// 1. List directory
NSLog(@"--- 1. List Directory ---");
NSError *error = nil;
NSArray *items = [DirectoryLister listDirectoryAtPath:testDir error:&error];
// 2. List with details
NSLog(@"\n--- 2. List with Details ---");
NSArray *detailedItems = [DirectoryLister listDirectoryWithDetailsAtPath:testDir error:&error];
// 3. Recursive traversal
NSLog(@"\n--- 3. Recursive Traversal ---");
NSArray *allFiles = [DirectoryTraverser findAllFilesAtPath:testDir];
NSLog(@"All files:");
for (NSString *file in allFiles) {
NSLog(@" - %@", file);
}
// 4. Directory tree
NSLog(@"\n--- 4. Directory Tree ---");
DirectoryNode *tree = [DirectoryTraverser getDirectoryTreeAtPath:testDir maxDepth:2];
[tree printTree];
// 5. Filter by extension
NSLog(@"\n--- 5. Filter by Extension ---");
NSArray *txtFiles = [FileFilter filterFilesAtPath:testDir
extensions:@[@"txt"]];
NSLog(@"Text files:");
for (NSString *file in txtFiles) {
NSLog(@" - %@", file);
}
// 6. Directory statistics
NSLog(@"\n--- 6. Directory Statistics ---");
NSDictionary *stats = [DirectoryStatistics calculateStatisticsForPath:testDir];
[DirectoryStatistics printStatistics:stats];
// 7. Search by name
NSLog(@"\n--- 7. Search by Name ---");
NSArray *searchResults = [FileSearcher searchFilesAtPath:testDir forName:@"file"];
NSLog(@"Files containing 'file':");
for (NSString *result in searchResults) {
NSLog(@" - %@", result);
}
// Cleanup
[fileManager removeItemAtPath:testDir error:nil];
NSLog(@"\nCleanup completed");
NSLog(@"\n=== All Directory Traversal Examples Completed ===");
}
return 0;
}