ios - 在 iOS 中,在纯 C 中,这是获取本地文件路径的方法吗?
问题描述
我最终需要一个 cstring ... 作为包中文件的本地路径。
第一的,
#include <CoreFoundation/CoreFoundation.h>
(这是纯 C 对吗?.. 你不能使用 Foundation)
接着
CFBundleRef mb = CFBundleGetMainBundle();
CFURLRef ur = CFBundleCopyResourceURL(mb, CFSTR("blah"), CFSTR("txt"), NULL);
CFStringRef imagePath = CFURLCopyFileSystemPath(ur, kCFURLPOSIXPathStyle);
CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
const char *filename = CFStringGetCStringPtr(imagePath, encodingMethod);
printf( "\n we did it! .. %s \n", filename );
假设“blah.txt”在您的捆绑包中,它可以工作。
这是我知道的唯一方法 - 似乎很啰嗦。这是怎么回事?
我的代码是否冗长、三色堇、可悲?
这是从文件名中获取 cstring 路径的正确和最佳习惯用法吗?
(注意我不想让它成为 obj-c 或 obj-cpp 文件。纯 C。)
解决方案
您的代码实际上不够长,并且有一些小错误:
- 你必须
CFRelease
拥有你拥有的所有对象。您可能会在其他地方执行此操作,但这在代码中并不明显。 CFStringGetCStringPtr
不承诺返回值。如果字符串已经以您想要的格式在内部存储,它只会返回一个值。这可能在它可能实际运行的每个系统上的这段代码中都是正确的,但它不是安全的 CoreFoundation 实践。CFStringGetSystemEncoding
同样,传递to的结果也不安全CFStringGetCStringPtr
,因为后者需要 8 位编码。这不是承诺,但是......CFStringGetSystemEncoding
无论如何,几乎从不需要或不合适。您可能实际上并不想要 MacRoman(这可能是您得到的,除非您可能配置了 MacJapanese)。你可能想要 UTF8,所以你应该要求它。
所以你会这样做:
CFBundleRef mb = CFBundleGetMainBundle();
CFURLRef ur = CFBundleCopyResourceURL(mb, CFSTR("blah"), CFSTR("txt"), NULL);
CFStringRef imagePath = CFURLCopyFileSystemPath(ur, kCFURLPOSIXPathStyle);
// Now convert to a C-string
CFStringEncoding encoding = kCFStringEncodingUTF8;
CFIndex length = CFStringGetLength(imagePath);
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, encoding);
char *filename = (char *)malloc(maxSize + 1); // +1 for \0
// Technically this can fail, but it really, really can't.
CFStringGetCString(imagePath, filename, maxSize, encoding);
printf( "\n we did it! .. %s \n", filename );
// Cleanup
free(filename); filename = NULL;
CFRelease(imagePath); imagePath = NULL;
CFRelease(ur); ur = NULL;
您可能会发现MYStringConversion函数很有帮助。为您返回一个包含 cstringMYCFStringCopyUTF8String
的 malloc 缓冲区(即您需要它)。free
(这些来自 iOS 编程的第 10 章:挑战极限。)
关于字符串缓冲区的一个侧面说明。人们经常倾向于使用基于PATH_MAX
. 请记住,macOS 允许名称比PATH_MAX
. 我不知道对 macOS 路径字符串的长度有任何硬性限制。在实践中,很少有真正的路径超过PATH_MAX
,但是当你创建一个路径时,看看有多少软件中断是有趣的(实际上并不有趣)。
请注意,通常不需要此代码。在大多数 CoreFoundation 项目中,您只是ur
直接使用它,与使用原始 cstrings 相比,它非常好。
推荐阅读
- android - 应用程序后台模式下的Android BLE扫描,广告数据包未检测到信标正在检测
- angular - 循环依赖角度共享模块和索引
- c# - 将字符串转换为字符时的问题在它之前添加了一些数字
- css - 从循环使用css如何动态更改框颜色
- php - 如何在php中删除array_map中的特定值
- angular - 在构造函数中使用this在角度依赖注入
- matlab - 如何在 Matlab 中求解 XQ=0 类型的矩阵?
- ngx-bootstrap - 如何从 NGX-Bootstrap datepicker 获取自定义日期格式值
- excel - 返回我假设为 MailItem 的对象的 MailItem 属性时出现类型不匹配错误
- node.js - 将 ngx-admin 从 2.3.0 更新到 3.0.0