JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。
优点JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。
JNA描述JNA类库使用一个很小的本地类库sub 动态的调用本地代码。程序员只需要使用一个特定的java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。
目标JNA是为了程序员调用本地代码更方便,跑的更快以及减少出错。
其他JNA中还包括了一些已经和某些特定平台的常用方法映射好的接口以及一些有用的可以简化本地代码访问的方法。
JNA编程基本语法解析
1. 自定义一个接口,该接口继承(扩展)自com.sun.jna.Library接口,
上面示例代码中的CLibrary接口。
2 .在自定义的接口中声明将要调用的函数原型,这些函数原型必须要在即将
加载的动态库中有对应的实例。如上面示例代码中的printf函数声明。如果是在微软的Windows环境下,
该函数存放在msvcrt.dll动态库中;如果是在Linux环境下,该函数存放在libc.so动态库中。
3. 在调用函数之前,先将接口实例化,并调用Native.loadLibrary对接口的实例初始化。
如上面示例代码中的Instance实例初始化。
4. 在上面的操作都正常完成后,即可在有需要的地方调用对应的C/C++函数。
package com.etrip.jna.win; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; /** * * @Title: TODO * @Description: 实现TODO * @Copyright:Copyright (c) 2011 * @Company: * @Date:2012-12-14 * @author longgangbai * @version 1.0 */ public class HelloJNA { //定义接口CLibrary,继承自com.sun.jna.Library public interface CLibrary extends Library { //定义并初始化接口的静态变量 CLibrary Instance=(CLibrary)Native.loadLibrary((Platform.isWindows()?"msvcrt":"c"),CLibrary.class); //printf函数声明 void printf(String format, Object... args); } public static void main(String[] args) { CLibrary.Instance.printf("Hello, World/n"); for (int i=0;i < args.length;i++) { CLibrary.Instance.printf("Argument %d: %s/n", i, args[i]); } } }
应用都要遇到一个很头疼的问题:文字编码,汉字的 GBK 和 国际通用的 UTF-8 的互相转化稍一不慎,
就会满屏乱码。下面介绍 UTF-8 和 GBK 的 NSString 相互转化的方法
从 GBK 转到 UTF-8
用 NSStringEncoding enc =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000) ,
然后就可以用initWithData:encoding来实现。
从 UTF-8 转到 GBK
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000),
得到的enc却是kCFStringEncodingInvalidId。
没关系,试试 NSData *data=[nsstring dataUsingEncoding:-2147482063];
转换字符编码主要用到CFStringConvertEncodingToNSStringEncoding函数,具体的大家可以看看这个函数的用法
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000);
完整代码如下:
NSURL *url = [NSURL URLWithString:urlStr];
NSData *data = [NSData dataWithContentsOfURL:url];
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString *retStr = [[NSString alloc] initWithData:data encoding:enc];
一个比较方便的转换NSString为UTF8编码的函数,大家可以试试
头文件:
@interface NSString (OAURLEncodingAdditions)
- (NSString *)URLEncodedString;
- (NSString *)URLDecodedString;
@end
m文件:
@implementation
NSString (OAURLEncodingAdditions)
- (NSString *)URLEncodedString
{
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)self,NULL,CFSTR("!*'();:@&=+$,/?%#[]"),kCFStringEncodingUTF8);
[result autorelease];
return result;
}
- (NSString*)URLDecodedString
{
NSString *result = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,(CFStringRef)self, CFSTR(""),kCFStringEncodingUTF8);CFSTR(""),kCFStringEncodingUTF8);
[result autorelease];
return result;
}
@end
如果需要转换一个NSString, 只需要
NSString *temp = [@"测试utf8" URLEncodedString];
NSString *decoded = [temp URLDecodedString];
枚举相同格式的文件:
You can achieve this pretty easily with the help of NSPredicate, like so:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; NSFileManager *fm = [NSFileManager defaultManager]; NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil]; NSPredicate *fltr = [NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"]; NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];
Checking for file existence:
+(BOOL)fileExistsAtAbsolutePath:(NSString*)filename { BOOL isDirectory; BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDirectory]; return fileExistsAtPath && !isDirectory; }
Checking for directory existence:
+(BOOL)directoryExistsAtAbsolutePath:(NSString*)filename { BOOL isDirectory; BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDirectory]; return fileExistsAtPath && isDirectory; }