ios解析txt電子書

昨天上線新版本因?yàn)镺ther-Other賬號(hào)審核被拒了,估計(jì)要等待幾天了侈询,正好抽時(shí)間把最近寫的東西整理一下。

附上APP地址: 一閱閱讀有想看小說的小伙伴可以試下 支持換源 支持自定義書源

言歸正傳,TXT電子書解析主要靠正則牡昆,篩選出文件內(nèi)所有章節(jié),并劃分range摊欠,對(duì)于正則表達(dá)式的基礎(chǔ)內(nèi)容我不做過多描述丢烘,各位有興趣可以去 菜鳥教程正則表達(dá)式自己去看下一下。

正則

(\\s+?)([#☆些椒、【0-9]{0,10})(第[0-9零一二兩三四五六七八九十百千萬(wàn)壹貳叁肆伍陸柒捌玖拾佰仟\\s]{1,10}[章節(jié)回集卷])(.*)

用法


+ (void)parseLocalBookWithFilePath:(NSString *)filePath bookId:(NSString *)bookId success:(void (^)(NSArray<TJChapterModel *> * _Nonnull chapters))success failure:(TJFailureHandler)failure {
    if (!filePath) {
        !failure ?: failure([NSError errorWithDomain:NSCocoaErrorDomain code:-1 userInfo:@{NSUnderlyingErrorKey : @"文件路徑為空"}]);
        return;
    }
    
    if (![filePath hasSuffix:@"txt"]) {
        !failure ?: failure([NSError errorWithDomain:NSCocoaErrorDomain code:-1 userInfo:@{NSUnderlyingErrorKey : @"文件格式不正確"}]);
        return;
    }
    
    NSString *content = [self contentWithFilePath:filePath];
    if (TJIsEmptyObject(content)) {
        !failure ?: failure([NSError errorWithDomain:NSCocoaErrorDomain code:-1 userInfo:@{NSUnderlyingErrorKey : @"書籍內(nèi)容為空或者書籍格式錯(cuò)誤"}]);
        return;
    }
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:kParseLocalBookPattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray *matches = [expression matchesInString:content options:NSMatchingReportCompletion range:NSMakeRange(0, content.length)];
    NSMutableArray *chapters = [[NSMutableArray alloc] init];
    if (matches.count == 0) {
        // 全書分為一章
        TJChapterModel *chapter = [[TJChapterModel alloc] init];
        chapter.chapterId = [bookId stringByAppendingFormat: @"1000000"];
        chapter.chapterIndex = 1;
        chapter.chapterName = @"開始";
        chapter.content = content;
        [chapters addObject:chapter];
    } else {
        // 當(dāng)前標(biāo)題在全文中的位置
        NSRange currentRange = NSMakeRange(0, 0);
        // 當(dāng)前章節(jié)編號(hào)
        NSInteger chapterIndex = 1;
        // 循環(huán)處理章節(jié)
        for (NSInteger i = 0; i < matches.count; i++) {
            @autoreleasepool {  // 自動(dòng)釋放池保證瞬時(shí)內(nèi)存不會(huì)過高
                NSTextCheckingResult *result = matches[i];
                // 下一個(gè)標(biāo)題在全文中的位置
                NSRange resultRange = result.range;
                // 截取兩個(gè)標(biāo)題之間內(nèi)容為當(dāng)前章節(jié)內(nèi)容
                NSString *chapterContent = [content substringWithRange:NSMakeRange(currentRange.location + currentRange.length, resultRange.location - currentRange.location - currentRange.length)];
                if (!TJIsEmptyObject(chapterContent) && resultRange.length <= 70) {
                    // 章節(jié)內(nèi)容不為空并且章節(jié)標(biāo)題長(zhǎng)度不超過70
                    TJChapterModel *chapterModel = [[TJChapterModel alloc] init];
                    chapterModel.chapterIndex = chapterIndex;
                    chapterModel.chapterId = [bookId stringByAppendingFormat: [NSString stringWithFormat:@"%@", @(1000000 + chapterIndex)]];
                    chapterModel.chapterName = (chapterIndex == 1) ? @"開始" : [[content substringWithRange:currentRange] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                    chapterModel.content = [self resetContent:chapterContent];
                    [chapters addObject:chapterModel];
                    chapterIndex += 1;
                    currentRange = resultRange;
                }
            };
        }
        NSString *endChapterContent = [content substringWithRange:NSMakeRange(currentRange.location + currentRange.length, content.length - currentRange.location - currentRange.length)];
        if (!TJIsEmptyObject(endChapterContent)) {
            // 最后一章
            TJChapterModel *endChapterModel = [[TJChapterModel alloc] init];
            endChapterModel.chapterIndex = chapterIndex;
            endChapterModel.chapterId = [bookId stringByAppendingFormat: [NSString stringWithFormat:@"%@", @(1000000 + chapterIndex)]];
            endChapterModel.chapterName = [[content substringWithRange:currentRange] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            endChapterModel.content = [self resetContent:endChapterContent];
            [chapters addObject:endChapterModel];
        }
    }
    if (chapters.count > 0 && success) {
        success(chapters);
    }
}

/// 處理章節(jié)內(nèi)容
/// @param content 內(nèi)容
+ (NSString *)resetContent:(NSString *)content {
    if (!content || content.length == 0) {
        return @"";
    }
    // 替換單換行
    content = [content stringByReplacingOccurrencesOfString:@"r" withString:@""];
    
    // 替換換行和多個(gè)換行(換行加空格)
    NSRegularExpression *regularExpression = [[NSRegularExpression alloc] initWithPattern:@"\\s*\\n+\\s*" options:NSRegularExpressionCaseInsensitive error:nil];
    content = [regularExpression stringByReplacingMatchesInString:content options:NSMatchingReportProgress range:NSMakeRange(0, content.length) withTemplate:@"\n  "];
    
    // 去掉首尾空格和換行
    content = [content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
    // 章節(jié)開頭添加空格
    content = [@"  " stringByAppendingString:content];
    
    return content;
}


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末播瞳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子免糕,更是在濱河造成了極大的恐慌赢乓,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件石窑,死亡現(xiàn)場(chǎng)離奇詭異牌芋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)松逊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門躺屁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人经宏,你說我怎么就攤上這事犀暑∠ê矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵母怜,是天一觀的道長(zhǎng)余耽。 經(jīng)常有香客問我,道長(zhǎng)苹熏,這世上最難降的妖魔是什么碟贾? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮轨域,結(jié)果婚禮上袱耽,老公的妹妹穿的比我還像新娘。我一直安慰自己干发,他們只是感情好朱巨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著枉长,像睡著了一般冀续。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上必峰,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天洪唐,我揣著相機(jī)與錄音,去河邊找鬼吼蚁。 笑死凭需,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肝匆。 我是一名探鬼主播粒蜈,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼旗国!你這毒婦竟也來了枯怖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤粗仓,失蹤者是張志新(化名)和其女友劉穎嫁怀,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體借浊,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年萝招,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蚂斤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡槐沼,死狀恐怖曙蒸,靈堂內(nèi)的尸體忽然破棺而出捌治,到底是詐尸還是另有隱情,我是刑警寧澤纽窟,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布肖油,位于F島的核電站,受9級(jí)特大地震影響臂港,放射性物質(zhì)發(fā)生泄漏森枪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一审孽、第九天 我趴在偏房一處隱蔽的房頂上張望县袱。 院中可真熱鬧,春花似錦佑力、人聲如沸式散。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)暴拄。三九已至,卻和暖如春编饺,著一層夾襖步出監(jiān)牢的瞬間揍移,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工反肋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留那伐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓石蔗,卻偏偏與公主長(zhǎng)得像罕邀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子养距,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容