对于一个阅读器而言,用户传入的文件千变万化,但总体来说也就那么几种,能支持30几种编码格式算是了不得的事情了。
最近,在测试用户传入一些特定格式的txt文件的时候,发现无法解析,追踪日志发现是编码格式的问题。最开始解决方法是加一个if判断,加上之后完美的解决了问题。但今天来的时候review了这一段代码之后,发现这样写有点猥琐。所以想到了怎么样自动判断编码格式。
Google之后,发现了一个C++库,可以解决这一问题:大体思路是获取传进来的文件一定量的样本进行判定来得到正确的编码格式。
uchardet传送门
使用的简单事例
#import "uchardet.h"
@interface WWHReaderManager : NSObject
@property(nonatomic, copy) NSString *encodeTypeStr;
@end
/**
当前txt文件编码格式
@param strTxtPath 路径
@return 是否检测出编码格式 0:检测出 其余:发生错误无法检测出编码格式
*/
- (int)txtEncoding:(const char *)strTxtPath {
FILE *file;
char buf[NUMBER_OF_SAMPLES];
size_t len;
uchardet_t ud;
/* 打开被检测文本文件,并读取一定数量的样本字符 */
file = fopen(strTxtPath, "rt");
if (file==NULL) {
printf("文件打开失败!\n");
return 1;
}
len = fread(buf, sizeof(char), NUMBER_OF_SAMPLES, file);
fclose(file);
ud = uchardet_new();
if (uchardet_handle_data(ud, buf, len) != 0) {
printf("分析编码失败!\n");
return -1;
}
uchardet_data_end(ud);
NSString *str = [[NSString alloc] initWithCString:uchardet_get_charset(ud) encoding:NSUTF8StringEncoding];
self.encodeTypeStr = str;
encode = uchardet_get_charset(ud);
uchardet_delete(ud);
return 0;
}
- (NSString *)encodeWithPath:(NSString *)path {
int result = [self txtEncoding:[path UTF8String]];
CFStringEncoding cfEncoding = 0;
if (result == 0) {
NSLog(@"文本的编码方式是%@", self.encodeTypeStr);
if ([self.encodeTypeStr isEqualToString:@"GB18030"]) {
cfEncoding = kCFStringEncodingGB_18030_2000;
} else if ([self.encodeTypeStr isEqualToString:@"ASCII"]) {
cfEncoding = kCFStringEncodingASCII;
} else if ([self.encodeTypeStr isEqualToString:@"UTF-8"]) {
cfEncoding = kCFStringEncodingUTF8;
} else if ([self.encodeTypeStr isEqualToString:@"UTF-16"]) {
cfEncoding = kCFStringEncodingUTF16;
} else if([self.encodeTypeStr isEqualToString:@"Shift_JIS"]) {
cfEncoding = kCFStringEncodingShiftJIS;
} else if([self.encodeTypeStr isEqualToString:@"windows-1252"]) {
cfEncoding = kCFStringEncodingWindowsLatin1;
} else if([self.encodeTypeStr isEqualToString:@"x-euc-tw"]) {
cfEncoding = kCFStringEncodingEUC_TW;
} else if([self.encodeTypeStr isEqualToString:@"EUC-KR"]) {
cfEncoding = kCFStringEncodingEUC_KR;
} else if([self.encodeTypeStr isEqualToString:@"EUC-JP"]) {
cfEncoding = kCFStringEncodingEUC_JP;
} else {
// ..根据需求自己➕
}
}
NSError *error = nil;
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
NSString *content = [NSString stringWithContentsOfFile:path encoding:encoding error:&error];
if (!content) {
NSLog(@"txt文件解析错误%@", error);
return [NSString stringWithFormat:@"无法识别的编码格式-%@", self.encodeTypeStr];
}
return content;
}
网友评论