[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题...

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第1张图片


项目开始的准备工作

在上一篇文章中, 已经从Boost官网获取了Boost库的源码.

相关文章:
[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍…

接下来就要编写代码了. 不过还需要做一些准备工作.

  1. 创建项目目录

    所有的项目文件肯定要在一个目录下, 找一个位置执行下面这行指令

    mkdir Boost-Doc-Searcher
    
  2. 将文档html文件, 存放到项目中

    cd Boost-Doc-Searcher进入刚刚创建的项目目录下, 执行指令:

    mkdir -p data/input
    # 将Boost库中的文档目录下的所有文件, 拷贝到 Boost-Doc-Searcher/data/input/. 下
    # 我的Boost库源码, 与 项目目录Boost-Doc-Searcher, 在同一个目录下
    # ❯ pwd
    # /home/July/gitCode/gitHub/Boost-Doc-Searcher
    cp ../boost_1_82_0/doc/html/* data/input/.
    

    然后进入, data/input目录下执行ls -R |grep -E "*.html" |wc -l

    查看目录下(包括子目录)有多少个.html文件:

    |wide

    boost 1.82.0版本 一共有 8563个文档文件

上面两个步骤, 相当于将Boost文档网页爬取到项目中. 接下来要做的就是对所有的文档html文件进行解析.

这也是本篇文章需要做的内容.

此时, 项目的树形目录结构为:

# ❯ pwd
# /home/July/gitCode/gitHub/Boost-Doc-Searcher
# ❯ tree -d -L 2
# .
# └── data
#     └── input

安装boost

项目的实现, 需要用到boost库中的组件. 所以需要先安装boost

博主的平台是 CentOS 7

sudo yum install boost-devel

执行上面的命令, 就可以完成安装

文档 去标签-数据清洗模块 parser

项目中已经存储有文档. 要实现Boost文档站内搜索, 就需要用到这些文档的内容.

但是, 这些文档都是.html文件, 里边有许多的标签. 标签内的数据都是对搜索无用的无效数据.

所以需要进行 去标签 的操作. 还需要注意的是 尽量不要修改原文档文件内容, 所以需要把去除标签之后的文档内容在存储到一个文本文件中.

先来创建这个文本文件:

# ❯ pwd
# /home/July/gitCode/gitHub/Boost-Doc-Searcher
mkdir -p data/output
cd data/output
touch raw

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第2张图片

然后回到Boost-Doc-Searcher目录下, 创建第一个模块代码文件parser.cc

1. parser代码基本结构

要理清 此代码的基本结构, 就需要理清 此程序需要实现的功能.

此程序要实现的是 对所有文档去标签, 然后将去完标签的文档内容 存储到同一个文本文件中

不过, 结合上一篇文章中分析过的: 搜索之后, 页面会以多个不同的网页的跳转链接拼接而成.

网页的跳转链接大致又分3部分展示: title content url. 那么, 我们在实际处理文档时, 也要从文档中提取到title content url 然后再以这三部分进行存储. 这样方便后面的使用.

并且, 在存储的时候 针对每一个文档内容 是一定需要分隔开的.

那么, parser代码的实现思路就可能包括:

  1. 使用boost库提供的工具, 递归遍历 data/input 目录下(包括子目录)的所有文档html, 并保存其文件名到vector
  2. 通过 vector 中保存的 文档名, 找到文档 并对 所有文档的内容去标签
  3. 还是通过vector中保存的文档名, 读取所有文档的内容, 以每个文档的 title content url 构成一个docInfo结构体. 并以vector存储起来
  4. 将用vector存储起来的所有文档的docInfo存储到data/output/raw 文件中, 每个文档的info'\n'分割

Boost中提供了很方便的文件处理的组件.

那么, parser代码的的基本结构可以为:

#include 
#include 
#include 
#include 
#include 

// 此程序是一个文档解析器
// boost文档的html文件中, 有许多的各种<>标签. 这些都是对搜索无关的内容, 所以需要清除掉
//  为提高解析效率, 可以将 上面的 2 3 步骤合并为一个函数:
//  每对一个文档html文件去标签之后, 就直接获取文档内容构成docInfo结构体, 并存储到 vector 中

// 代码规范
//  const & 表示输入型参数: const std::string&
//  * 表示输出型参数: std::string*
//  & 表示输入输出型参数: std::string&

#define ENUM_ERROR 1
#define PARSEINFO_ERROR 2
#define SAVEINFO_ERROR 3

const std::string srcPath = "data/input";     // 存放所有文档的目录
const std::string output = "data/output/raw"; // 保存文档所有信息的文件

typedef struct docInfo {
    std::string _title;   // 文档的标题
    std::string _content; // 文档内容
    std::string _url;     // 该文档在官网中的url
} docInfo_t;

bool enumFile(const std::string& srcPath, std::vector<std::string>* filesList);
bool parseDocInfo(const std::vector<std::string>& filesList, std::vector<docInfo_t>* docResults);
bool saveDocInfo(const std::vector<docInfo_t>& docResults, const std::string& output);

int main() {
    std::vector<std::string> filesList;
    // 1. 递归式的把每个html文件名带路径,保存到filesList中,方便后期进行一个一个的文件进行读取
    if (!enumFile(srcPath, &filesList)) {
        // 获取文档html文件名失败
        std::cerr << "Failed to enum file name!" << std::endl;
        return ENUM_ERROR;
    }

    // 走到这里 获取所有文档html文件名成功
    // 2. 按照filesList读取每个文档的内容,并进行去标签解析
    // 3. 并获取文档的内容 以 标题 内容 url 构成docInfo结构体, 存储到vector中
    std::vector<docInfo_t> docResults;
    if (!parseDocInfo(filesList, &docResults)) {
        // 解析文档内容失败
        std::cerr << "Failed to parse document information!" << std::endl;
        return PARSEINFO_ERROR;
    }

    // 走到这里 获取所有文档内容 并以 docInfo 结构体形式存储到vector中成功
    // 4: 把解析完毕的各个文件内容,写入到output , 按照\3作为每个文档的分割符
    if (!saveDocInfo(docResults, output)) {
        std::cerr << "Failed to save document information!" << std::endl;
        return SAVEINFO_ERROR;
    }

    return 0;
}

基本结构是:

先规定了一个代码规范:

//  const & 表示输入型参数: const std::string&
//  * 表示输出型参数: std::string*
//  & 表示输入输出型参数: std::string&
  1. 首先

    const std::string srcPath = "data/input" 存储 项目中所有文档html文件所在的目录

    const std::string output = "data/output/raw" 存储 清理后文档内容的 存储文件的路径

  2. 然后定义结构体, 用于存储单个文档的 title content url

    typedef struct docInfo {
        std::string _title;   // 文档的标题
        std::string _content; // 文档内容
        std::string _url;     // 该文档在官网中的url
    } docInfo_t;
    
  3. 再然后, 就是主函数需要执行的内容:

    1. 首先, 获取srcPath目录下的所有.html文档文件名(包括相对路径), 并存储到vector

      所以, 先定义了一个std::vector filesList, 用于存储文件名

      然后执行enumFile(srcPath, &filesList), 并判断结果.

      [C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第3张图片

    2. 获取完所有文档的文件名之后, 就可以根据文件名找到文档. 然后对文档进行去标签处理, 并获取文档的 title content url. 并将其以docInfo结构体的形式存储到vector

      所以定义了一个std::vector docResults, 用于存储去标签之后的文档的信息

      然后执行parseDocInfo(filesList, &docResults), 并判断结果

      [C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第4张图片

    3. 最后就是, 将docResults中存储的每个文档的title content url信息, 都存储到output文件中.

      即, 执行saveDocInfo(docResults, output), 并判断结果

      [C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第5张图片

这些步骤, 就是parser模块的基本结构了. 之后只需要实现三个接口就可以了

2. enumFile()接口实现

enumFile()接口需要实现, 统计scrPath目录下(包括子目录下)的所有.html文件, 存储到输出型参数filesList

实现此函数, 需要使用到Boost库中的组件: filesystem

bool enumFile(const std::string& srcPath, std::vector<std::string>* filesList) {
    // 使用 boost库 来对路径下的文档html进行 递归遍历
    namespace bs_fs = boost::filesystem;

    // 根据 srcPath 构建一个path对象
    bs_fs::path rootPath(srcPath);
    if (!bs_fs::exists(rootPath)) {
        // 指定的路径不存在
        std::cerr << srcPath << " is not exists" << std::endl;
        return false;
    }

    // boost库中 可以递归遍历目录以及子目录中 文件的迭代器, 不初始化可看作空
    bs_fs::recursive_directory_iterator end;
    // 再从 rootPath 构建一个迭代器, 递归遍历目录下的所有文件
    for (bs_fs::recursive_directory_iterator iter(rootPath); iter != end; iter++) {
        // 目录下 有目录文件 也有普通文件, 普通文件不仅仅只有 .html文件, 所以还需要过滤掉目录文件和非.html文件
        if (!bs_fs::is_regular_file(*iter)) {
            // 不是普通文件
            continue;
        }
        if (iter->path().extension() != ".html") { // boost::path 对象的 extension()接口, 可以获取到所指文件的后缀
            // 不是 html 文件
            continue;
        }

        std::cout << "Debug:  " << iter->path().string() << std::endl;

        // 走到这里的都是 .html 文件
        // 将 文件名存储到 filesList 中
        filesList->push_back(iter->path().string());
    }

    return true;
}

使用了Boost库中的组件, 可以非常简单的实现遍历某目录下的所有文件.

  1. 首先是boost::filesystem::path类:

    path对象可以表示一条路径. boost库中 对它的描述是这样的:

    [C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第6张图片

  2. 其次recursive_directory_iterator迭代器:

    通过path对象可以实例化recursive_directory_iterator迭代器.

    此迭代器可以对目录下的所有文件进行迭代, 包括子目录下的文件. 该过程是递归的.

    [C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第7张图片

重要的就是这两个内容了.

我们使用srcPath实例化boost::filesystem::path rootPath对象.

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第8张图片

然后再使用rootPath实例化recursive_directory_iterator, 让迭代器可以从srcPath目录下开始递归迭代

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第9张图片

然后在迭代的过程中, 由于有目录文件和其他非html文件的存在

所以使用is_regular_file()判断是否为普通文件类型, 然后在使用path对象的extension()接口 获取扩展名.

再根据扩展名判断是否为html文件.

如果是, 就将迭代器所指的path对象 使用path对象的string()接口, 将path对象表示的路径名存储到filesList中:

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第10张图片

至此, enumFile()接口的功能就结束了, 我们可以在函数内 输出每次获取的文件名 来调试看是否正确:

通过wc -l命令可以看出, 确实输出了8563行. 也就表示确实获取到了8563.html文件名

注意, 因为使用了第三方库boost, 所以编译时 需要指明链接库

g++ -o parser parser.cc -std=c++11 -lboost_system -lboost_filesystem

3. parseDocInfo()接口实现

parseDocInfo()需要实现的功能是:

遍历filesList获取每个文档的文件名, 通过文件名访问并读取到文件内容. 然后对文件内容去标签, 并获取到 title content url 构成一个docInfo结构体, 并将每个文档的docInfo结构体存储到vector中.

所以, parseDocInfo()的实现框架是这样的:

bool parseDocInfo(const std::vector<std::string>& filesList, std::vector<docInfo_t>* docResults) {
    // parseDocInfo 是对文档html文件的内容做去标签化 并 获取 title content url 构成结构体
    // 文档的路径都在 filesList 中存储着, 所以需要遍历 filesList 处理文件
    for (const std::string& filePath : filesList) {
        // 获取到文档html的路径之后, 就需要对 html文件进行去标签化等一系列解析操作了
        // 1. 读取文件内容到 string 中
        std::string fileContent;
        if (!ns_util::fileUtil::readFile(filePath, &fileContent)) {
            // 读取文件内容失败
            continue;
        }

        docInfo_t doc;
        // 2. 解析并获取title, html文件中只有一个 title标签, 所以再去标签之前 获取title比较方便
        if (!parseTitle(fileContent, &doc._title)) {
            // 解析title失败
            continue;
        }

        // 3. 解析并获取文档有效内容, 去标签的操作实际就是在这一步进行的
        if (!parseContent(fileContent, &doc._content)) {
            // 解析文档有效内容失败
            continue;
        }

        // 4. 获取 官网的对应文档的 url
        if (!parseUrl(filePath, &doc._url)) {
            continue;
        }

        // 做完上面的一系列操作 走到这里时 如果没有不过 doc 应该已经被填充完毕了
        // doc出此次循环时就要被销毁了, 所以将doc 设置为将亡值 可以防止拷贝构造的发生 而使用移动语义来向 vector中添加元素
        // 这里发生拷贝构造是非常的消耗资源的 因为 doc._content 非常的大
        docResults->push_back(std::move(doc));
    }

    return true;
}

其中, ns_util::fileUtil::readFile()接口是一个可以通用的工具接口. 是用来将文件内容读取到指定string中的函数接口.

所以, 将函数写到util.hpp文件中.

parseDocInfo()接口的实现思路就是:

  1. 遍历filesList获取当前文件名
  2. 根据获取到的文件名, 将文件的内容读取到string fileContent
  3. 再分别根据fileContent, 获取文档的 title content url 并对它去标签
  4. 然后再将构成的docInfo对象结构体变量, 存储到vector中.

其中, 有四个接口需要完成:

readFile()接口实现

readFile()是读取文件内容到内存中的接口. 此接口可以公用, 因为其他模块中也会用到读取文件内容到内存中的功能.

所以可以把readFile()这个通用的工具接口, 写在util.hpp头文件中.

util.hpp一般用来定义通用的工具接口、宏等

util.hpp:

#pragma once

#include 
#include 
#include 
#include 

namespace ns_util {
    class fileUtil {
    public:
        // readFile 用于读取指定文本文件的内容, 到string输出型参数中
        static bool readFile(const std::string& filePath, std::string* out) {
            // 要读取文件内容, 就要先打开文件
            // 1. 以读取模式打开文件
            std::ifstream in(filePath, std::ios::in);
            if (!in.is_open()) {
                // 打卡文件失败
                std::cerr << "Failed to open " << filePath << "!" << std::endl;
                return false;
            }

            // 走到这里打开文件成功
            // 2. 读取文件内, 并存储到out中
            std::string line;
            while (std::getline(in, line)) {
                *out += line;
            }

            in.close();

            return true;
        }
    };
}

此函数接口以static修饰 定义在fileUtil类内, fileUtil表示文件操作通用类.

首先以文本文件读取的方式打开filePath路径的文件:

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第11张图片

然后, 使用std::getline()从打开的文件流中 按行读取数据到string line中. 每次读取成功就将line的内容添加到输出型参数out之后. 直到读取结束.

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第12张图片

std::getline()是按行读取的, 可以用来读取文本文件, 但是不能用来读取二进制数据文件

因为, std::getline()是通过'\n'来判断一行结束的位置的, 并且它会对一些字符过滤或转换. 这用来读取二进制文件是不合理的

因为二进制文件可能没有'\n'符, 并且二进制文件读取, 要求 取原始的字节而不改变.

使用std::getline()读取二进制文件会导致意外的行为或读取错误

执行完读取之后, 关闭打开的文件流. 接口实现完成, 也可以成功获取文档的内容.

接下来就是根据文档内容, 获取title content url, 并去标签化了

parseTitle()接口实现

执行完readFile()之后, fileContent的内容就是文档的原始内容了.

文档的原始内容是html格式的.

而一个完整的html文件中, 有且只能有一个标签对.

这个标签对之间的内容, 即为文档的title有效内容.

我们可以随便查看一个文档, 于官网的文档页面对比:

再去查看对应的网页:

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第13张图片

标签对, 就表示浏览器标签页上的标题

了解到 一个完整的html文件中, 有且只能有一个标签对

那么, 我们就可以直接根据来找到文档的标题:

bool parseTitle(const std::string& fileContent, std::string* title) {
    // 简单分析一个html文件, 可以发现 标签只有一对 格式是这样的: <title> , 并且内部不会有其他字段</span>
    <span class="token comment">// 在 > < 之间就是这个页面的 title , 所以我们想要获取 title 就只需要获取<title>和 之间的内容就可以了
    // 1. 先找 </span>
    std<span class="token double-colon punctuation">::</span>size_t begin <span class="token operator">=</span> fileContent<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">"<title>"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>begin <span class="token operator">==</span> std<span class="token double-colon punctuation">::</span>string<span class="token double-colon punctuation">::</span>npos<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 没找到</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// 2. 再找 
    std::size_t end = fileContent.find("");
    if (end == std::string::npos) {
        // 没找到
        return false;
    }

    // 走到这里就是都找到了, 然后就可以获取 > <之间的内容了
    begin += std::string(""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 让begin从>后一位开始</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>begin <span class="token operator">></span> end<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token operator">*</span>title <span class="token operator">=</span> fileContent<span class="token punctuation">.</span><span class="token function">substr</span><span class="token punctuation">(</span>begin<span class="token punctuation">,</span> end <span class="token operator">-</span> begin<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <p>直接在<code>fileContent</code>中找<code><title></code>和<code>的位置:

[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第14张图片

找到两个字符串的位置之后, 截取从begin + string("").size()</code> 到 <code>end - begin + string("<title>").size()</code>之间的内容就好了</p> <p>不过, 要注意<code>begin + string("<title>").size()</code> < <code>end</code> 成立</p> <p><a href="http://img.e-com-net.com/image/info8/c5b1e590d59043d59e6221528f9a87b2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c5b1e590d59043d59e6221528f9a87b2.jpg" alt="[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对文档文件去标签、如何获取文档标题..._第15张图片" width="650" height="209" style="border:1px solid black;"></a></p> <p>至此, 就已经获取的文档的<code>title</code>并存储到了<code>docInfo</code>结构体变量中.</p> <h3><code>parseContent()</code>接口实现</h3> <p><code>parseContent()</code>接口需要实现的功能是, 获取去掉标签的文档<code>html</code>内容.</p> <p>也就是说, 文档<code>html</code>内容 去标签是在此函数内部实现的.</p> <p>其实去标签的操作也很简单, 不需要改动<code>fileContent</code>的原内容.</p> <p>只需要按字节遍历<code>fileContent</code>, 如果是标签内的数据 就不做处理, 如果是标签外的有效数据, 就添加到输出型参数中就可以了</p> <pre><code class="prism language-cpp"><span class="token keyword">bool</span> <span class="token function">parseContent</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> fileContent<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> content<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// parseContent 需要实现的功能是, 清除标签</span> <span class="token comment">// html的语法都是有一定的格式的. 虽然标签可能会成对出现 <head></head>, 也可能会单独出现 <mate></span> <span class="token comment">// 但是 标签的的内容永远都是在相邻的 < 和 >之间的, 在 > 和 < 之间的则是是正文的内容</span> <span class="token comment">// 并且, html文件中的第一个字符永远都是 <, 并且之后还会有> 成对出现</span> <span class="token comment">// 可以根据这种语法特性来遍历整个文件内容 清除标签</span> <span class="token keyword">enum</span> <span class="token class-name">status</span> <span class="token punctuation">{</span> LABLE<span class="token punctuation">,</span> <span class="token comment">// 表示在标签内</span> CONTENT <span class="token comment">// 表示在正文内</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">enum</span> <span class="token class-name">status</span> s <span class="token operator">=</span> LABLE<span class="token punctuation">;</span> <span class="token comment">// 因为首先的状态一定是在标签内</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> c <span class="token operator">:</span> fileContent<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> LABLE<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 如果此时的c表示标签内的内容, 不做处理</span> <span class="token comment">// 除非 当c等于>时, 表示即将出标签, 此时需要切换状态</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'>'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> s <span class="token operator">=</span> CONTENT<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">case</span> CONTENT<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 此时 c 表示正文的内容, 所以需要存储在 content中, 但是为了后面存储以及分割不同文档, 所以也不要存储 \n, 将 \n 换成 ' '存储</span> <span class="token comment">// 并且, 当c表示<时, 也就不要存储了, 表示已经出了正文内容, 需要切换状态</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'<'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> s <span class="token operator">=</span> LABLE<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'\n'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> c <span class="token operator">=</span> <span class="token char">' '</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">*</span>content <span class="token operator">+=</span> c<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><code>html</code>文件中的标签, 总是以<code><</code>开始 以<code>></code>结尾, 即 在一对<code><></code>内的是标签的内容. 在此之外的是有效内容.</p> <p>并且, <code>html</code>文件内容的开头的第一个字符 一定是<code><</code>符号.</p> <p>我们可以根据<code>html</code>文件 这样的内容格式 来设置 <strong>一个简单的状态机</strong></p> <p>即, 在遍历<code>fileContent</code>过程中 所表示的字符 分为在标签内和在标签外 两个状态. 根据情况切换</p> <p>如果在标签内, 就不做处理 直接进入下一个循环. 如果在标签内, 就将当前字符 添加到输出型参数<code>content</code>之后.</p> <p>不过, 需要注意的是 <strong>如果存在字符在标签外, 但这个字符是<code>'\n'</code> 则考虑将此字符转换为<code>' '</code> 然后再添加到参数中</strong>. 这是为了在最后一个操作中添加不同文档信息的分隔符.</p> <h3><code>parseUrl()</code>接口实现</h3> <p><code>paeseUrl()</code>接口需要实现的功能是 获取 <strong>当前文档 对应的在官网中的<code>url</code></strong></p> <p>比如: <code>BOOST_PROTO_typename_A.html</code>, 在官网中的地址是 <code>https://www.boost.org/doc/libs/1_82_0/doc/html/BOOST_PROTO_typename_A.html</code></p> <p>这时候, 就要对比 源码中文档路径 和 项目中文档路径 以及 官网中文档的<code>url</code> 之间的关系了</p> <p>源码中, 文档的路径是: <code>boost_1_82_0/doc/html/xxxxxx.html</code> 或 <code>boost_1_82_0/doc/html/xxxxxx/xxxxxx.html</code></p> <p>项目的<code>parser</code>程序中, <code>filesList</code>中记录的文档路径是: <code>data/input/xxxxxx.html</code> 或 <code>data/input/xxxxxx/xxxxxx.html</code></p> <p>而官网对应的文档<code>url</code>是: <code>https://www.boost.org/doc/libs/1_82_0/doc/html/xxxxxx.html</code> 或 <code>https://www.boost.org/doc/libs/1_82_0/doc/html/xxxxxx/xxxxxx.html</code></p> <p>那么, <code>parser</code>程序中 当前文档在官网中对应的<code>url</code>就可以是:</p> <p><strong><code>https://www.boost.org/doc/libs/1_82_0/doc/html</code> + <code>data/input</code>之后的内容</strong></p> <p>所以, <code>parseUrl()</code>接口的实现是:</p> <pre><code class="prism language-cpp"><span class="token keyword">bool</span> <span class="token function">parseUrl</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> filePath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> url<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 先去官网看一看 官网的url是怎么分配的: https://www.boost.org/doc/libs/1_82_0/doc/html/function/reference.html</span> <span class="token comment">// 我们本地下载的boost库的html路径又是怎么分配的: boost_1_82_0/doc/html/function/reference.html</span> <span class="token comment">// 我们在程序中获取的文件路径 即项目中文件的路径 又是什么: data/input/function/reference.html</span> <span class="token comment">// 已经很明显了, url 的获取就是 https://www.boost.org/doc/libs/1_82_0/doc/html + /function/reference.html</span> <span class="token comment">// 其中, 如果版本不变的话, https://www.boost.org/doc/libs/1_82_0/doc/html 是固定的</span> <span class="token comment">// 而后半部分, 则是 filePath 除去 data/input, 也就是 const std::string srcPath = "data/input" 部分</span> <span class="token comment">// 所以, url的获取也很简单</span> std<span class="token double-colon punctuation">::</span>string urlHead <span class="token operator">=</span> <span class="token string">"https://www.boost.org/doc/libs/1_82_0/doc/html"</span><span class="token punctuation">;</span> std<span class="token double-colon punctuation">::</span>string urlTail <span class="token operator">=</span> filePath<span class="token punctuation">.</span><span class="token function">substr</span><span class="token punctuation">(</span>srcPath<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 从srcPath长度处向后截取</span> <span class="token operator">*</span>url <span class="token operator">=</span> urlHead <span class="token operator">+</span> urlTail<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <hr> <p>实现了 <code>parseTitle()</code> <code>parseContent()</code> <code>parseUrl()</code></p> <p>并在<code>parseDocInfo()</code>接口内 执行 <code>parseTitle(fileContent, &doc._title)</code> <code>parseContent(fileContent, &doc._content)</code> 和 <code>parseUrl(filePath, &doc._url)</code> 之后</p> <p><code>docInfo_t doc</code>变量内, 已经存储了 <strong>该文档的<code>title</code> 去标签后的<code>content</code> 以及该文档在官网中的<code>url</code></strong></p> <p><code>parseDocInfo()</code>的最后一步, 即为 将<code>doc</code>变量存储到输出型参数<code>docResults(一个vector)</code>中</p> <hr> <p>至此, <code>parseDocInfo()</code>接口完成.</p> <h2>4. <code>saveDocInfo()</code>接口实现</h2> <p>之前的两个接口, 分别完成了:</p> <ol> <li><code>enumFile()</code>: 获取<code>data/input/</code>目录下所有<code>.html</code>文档文件名(携带相对路径), 存储到<code>filesList(一个vector)</code>中</li> <li><code>parseDocInfo()</code>: 通过遍历<code>filesList</code>, 获取每个文档文件的路径, 读取文档内容. 并根据文档内容获取 <code>title</code> <code>去标签的content</code>, 再根据文档文件路径获取 文档对应在官网中<code>url</code>, 并构成一个<code>docInfo</code>变量 存储到<code>docResult(一个vector)</code>中</li> </ol> <p>也就是, 已经将 每个文档的<code>title</code> <code>去标签content</code> <code>官网对应url</code>以一个结构体变量的形式存储在了<code>docResult(一个vector)</code>中</p> <p>那么, <code>saveDocInfo()</code>要做的就是, 将<code>docResult</code>中存储的每个文档的信息, 以一定的格式写入到 全局<code>output</code>所表示的文本文件<code>(raw)</code>中.</p> <blockquote> <p><strong><code>const std::string output = "data/output/raw"; // 保存文档所有信息的文件</code></strong></p> </blockquote> <p>该以什么样的格式写入呢?</p> <p><strong>写入, 不应该只考虑写入格式是否方便. 还需要考虑, 在之后的使用时 从文本文件中获取文档内容, 对文档内容的读取、区分、分割是否方便.</strong></p> <p>在项目中, 我们采用这种方案写入:</p> <p><code>title\3content\3url\ntitle\3content\3url\ntitle\3content\3url\n...</code></p> <p>即, 每个文档的信息以这样的格式写入文本文件中: <code>title\3content\3url\n</code></p> <p>以<code>'\3'</code>将不同的字段分隔开: <code>"title"</code> <code>'\3'</code> <code>"去标签的content"</code> <code>'\3'</code> <code>"官网对应的url"</code></p> <p>并在每个文档内容字段的结尾使用<code>'\n'</code>, 以分割不同的文档: <code>title1\3content1\3url1\n title2\3content2\3url2\n...</code></p> <pre><code class="prism language-cpp"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">SEP</span> <span class="token char">'\3'</span></span> <span class="token keyword">bool</span> <span class="token function">saveDocInfo</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span><span class="token operator">&</span> docResults<span class="token punctuation">,</span> <span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> output<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 最后就是将 已经结构化的所有的文档数据, 以一定的格式存储在指定的文件中.</span> <span class="token comment">// 以什么格式存储呢? 每个文档都是结构化的数据: _title _content _url.</span> <span class="token comment">// 我们可以将 三个字段以'\3'分割, 不过 _url后不用'\3' 而是用'\n'</span> <span class="token comment">// 因为, 像文件中写入不能只关心写入, 还要考虑读取时的问题. 方便的 读取文本文件, 通常可以用 getline 来获取一行数据</span> <span class="token comment">// 所以, 当以这种格式 (_title\3_content\3_url\n) 将 文档数据存储到文件中时, getline() 成功读取一次文件内容, 获取的就是一个文档的所有有效内容.</span> <span class="token comment">// 按照二进制方式进行写入, 二进制写入, 写入什么就是什么 转义字符也不会出现被优化改变的现象</span> std<span class="token double-colon punctuation">::</span>ofstream <span class="token function">out</span><span class="token punctuation">(</span>output<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>ios<span class="token double-colon punctuation">::</span>out <span class="token operator">|</span> std<span class="token double-colon punctuation">::</span>ios<span class="token double-colon punctuation">::</span>binary<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>out<span class="token punctuation">.</span><span class="token function">is_open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 文件打开失败</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"open "</span> <span class="token operator"><<</span> output <span class="token operator"><<</span> <span class="token string">" failed!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 就可以进行文件内容的写入了</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token operator">&</span> item <span class="token operator">:</span> docResults<span class="token punctuation">)</span> <span class="token punctuation">{</span> std<span class="token double-colon punctuation">::</span>string outStr<span class="token punctuation">;</span> outStr <span class="token operator">=</span> item<span class="token punctuation">.</span>_title<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> SEP<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> item<span class="token punctuation">.</span>_content<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> SEP<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> item<span class="token punctuation">.</span>_url<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> <span class="token char">'\n'</span><span class="token punctuation">;</span> out<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>outStr<span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> outStr<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> out<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>使用<code>'\n'</code>分隔不同的文档信息 的优点就是, 一次<code>std::getline()</code>获取到的就是一个文档的信息. 因为<code>std::getline()</code>就是按照<code>'\n'</code>来获取一行内容的.</p> <p>这样也就可以直接使用<code>ns_util::fileUtil::readFile()</code>接口, 读取文档信息.</p> <p>而使用<code>'\3'</code>分隔一个文档的不同字段, 是因为<code>'\3'</code>属于控制字符, 是不显示的. 当然也可以用其他不显示字符<code>'\4'</code>之类的.</p> <p>至此, <code>parser</code>模块的代码就全部完成了</p> <h2><code>parser</code>模块代码整合 及 演示</h2> <p><strong><code>util.hpp</code>:</strong></p> <pre><code class="prism language-cpp"><span class="token comment">// util.hpp 一般定义一些通用的宏定义、工具函数等</span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">pragma</span> <span class="token expression">once</span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><iostream></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><vector></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><string></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><fstream></span></span> <span class="token keyword">namespace</span> ns_util <span class="token punctuation">{</span> <span class="token keyword">class</span> <span class="token class-name">fileUtil</span> <span class="token punctuation">{</span> <span class="token keyword">public</span><span class="token operator">:</span> <span class="token comment">// readFile 用于读取指定文本文件的内容, 到string输出型参数中</span> <span class="token keyword">static</span> <span class="token keyword">bool</span> <span class="token function">readFile</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> filePath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> out<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 要读取文件内容, 就要先打开文件</span> <span class="token comment">// 1. 以读取模式打开文件</span> std<span class="token double-colon punctuation">::</span>ifstream <span class="token function">in</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>ios<span class="token double-colon punctuation">::</span>in<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>in<span class="token punctuation">.</span><span class="token function">is_open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 打卡文件失败</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"Failed to open "</span> <span class="token operator"><<</span> filePath <span class="token operator"><<</span> <span class="token string">"!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 走到这里打开文件成功</span> <span class="token comment">// 2. 读取文件内, 并存储到out中</span> std<span class="token double-colon punctuation">::</span>string line<span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span><span class="token function">getline</span><span class="token punctuation">(</span>in<span class="token punctuation">,</span> line<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">*</span>out <span class="token operator">+=</span> line<span class="token punctuation">;</span> <span class="token punctuation">}</span> in<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><strong><code>parser.cc</code>:</strong></p> <pre><code class="prism language-cpp"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><iostream></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><string></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><utility></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><vector></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><boost/filesystem.hpp></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"util.hpp"</span></span> <span class="token comment">// 此程序是一个文档解析器</span> <span class="token comment">// boost文档的html文件中, 有许多的各种<>标签. 这些都是对搜索无关的内容, 所以需要清除掉</span> <span class="token comment">// 本程序实现以下功能:</span> <span class="token comment">// 1. 使用boost库提供的容器, 递归遍历 ./data/input 目录下(包括子目录)的所有文档html, 并保存其文件名到 vector中</span> <span class="token comment">// 2. 通过 vector 中保存的 文档名, 找到文档 并对 所有文档的内容去标签</span> <span class="token comment">// 3. 还是通过 vector中保存的文档名</span> <span class="token comment">// 读取所有文档的内容, 以每个文档 标题 内容 url 结构构成一个docInfo结构体. 并以 vector 存储起来</span> <span class="token comment">// 4. 将用vector 存储起来的所有文档的docInfo 存储到 ./data/output/raw 文件中, 每个文档的info用 \n 分割</span> <span class="token comment">// 至此 完成对所有文档的 解析</span> <span class="token comment">// 为提高解析效率, 可以将 2 3 步骤合并为一个函数:</span> <span class="token comment">// 每对一个文档html文件去标签之后, 就获取文档内容构成docInfo结构体, 并存储到 vector 中</span> <span class="token comment">// 代码规范</span> <span class="token comment">// const & 表示输入型参数: const std::string&</span> <span class="token comment">// * 表示输出型参数: std::string*</span> <span class="token comment">// & 表示输入输出型参数: std::string&</span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">ENUM_ERROR</span> <span class="token expression"><span class="token number">1</span></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">PARSEINFO_ERROR</span> <span class="token expression"><span class="token number">2</span></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">SAVEINFO_ERROR</span> <span class="token expression"><span class="token number">3</span></span></span> <span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">SEP</span> <span class="token char">'\3'</span></span> <span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string srcPath <span class="token operator">=</span> <span class="token string">"data/input"</span><span class="token punctuation">;</span> <span class="token comment">// 存放所有文档的目录</span> <span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string output <span class="token operator">=</span> <span class="token string">"data/output/raw"</span><span class="token punctuation">;</span> <span class="token comment">// 保存文档所有信息的文件</span> <span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">docInfo</span> <span class="token punctuation">{</span> std<span class="token double-colon punctuation">::</span>string _title<span class="token punctuation">;</span> <span class="token comment">// 文档的标题</span> std<span class="token double-colon punctuation">::</span>string _content<span class="token punctuation">;</span> <span class="token comment">// 文档内容</span> std<span class="token double-colon punctuation">::</span>string _url<span class="token punctuation">;</span> <span class="token comment">// 该文档在官网中的url</span> <span class="token punctuation">}</span> docInfo_t<span class="token punctuation">;</span> <span class="token keyword">bool</span> <span class="token function">enumFile</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> srcPath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>string<span class="token operator">></span><span class="token operator">*</span> filesList<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">bool</span> <span class="token function">parseDocInfo</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>string<span class="token operator">></span><span class="token operator">&</span> filesList<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span><span class="token operator">*</span> docResults<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">bool</span> <span class="token function">saveDocInfo</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span><span class="token operator">&</span> docResults<span class="token punctuation">,</span> <span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> output<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>string<span class="token operator">></span> filesList<span class="token punctuation">;</span> <span class="token comment">// 1. 递归式的把每个html文件名带路径,保存到filesList中,方便后期进行一个一个的文件进行读取</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">enumFile</span><span class="token punctuation">(</span>srcPath<span class="token punctuation">,</span> <span class="token operator">&</span>filesList<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 获取文档html文件名失败</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"Failed to enum file name!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> ENUM_ERROR<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 走到这里 获取所有文档html文件名成功</span> <span class="token comment">// 2. 按照filesList读取每个文档的内容,并进行去标签解析</span> <span class="token comment">// 3. 并获取文档的内容 以 标题 内容 url 构成docInfo结构体, 存储到vector中</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span> docResults<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">parseDocInfo</span><span class="token punctuation">(</span>filesList<span class="token punctuation">,</span> <span class="token operator">&</span>docResults<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 解析文档内容失败</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"Failed to parse document information!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> PARSEINFO_ERROR<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 走到这里 获取所有文档内容 并以 docInfo 结构体形式存储到vector中成功</span> <span class="token comment">// 4: 把解析完毕的各个文件内容,写入到output , 按照\3作为每个文档的分割符</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">saveDocInfo</span><span class="token punctuation">(</span>docResults<span class="token punctuation">,</span> output<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"Failed to save document information!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> SAVEINFO_ERROR<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">enumFile</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> srcPath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>string<span class="token operator">></span><span class="token operator">*</span> filesList<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 使用 boost库 来对路径下的文档html进行 递归遍历</span> <span class="token keyword">namespace</span> bs_fs <span class="token operator">=</span> boost<span class="token double-colon punctuation">::</span>filesystem<span class="token punctuation">;</span> <span class="token comment">// 根据 srcPath 构建一个path对象</span> bs_fs<span class="token double-colon punctuation">::</span>path <span class="token function">rootPath</span><span class="token punctuation">(</span>srcPath<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>bs_fs<span class="token double-colon punctuation">::</span><span class="token function">exists</span><span class="token punctuation">(</span>rootPath<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 指定的路径不存在</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> srcPath <span class="token operator"><<</span> <span class="token string">" is not exists"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// boost库中 可以递归遍历目录以及子目录中 文件的迭代器, 不初始化可看作空</span> bs_fs<span class="token double-colon punctuation">::</span>recursive_directory_iterator end<span class="token punctuation">;</span> <span class="token comment">// 再从 rootPath 构建一个迭代器, 递归遍历目录下的所有文件</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>bs_fs<span class="token double-colon punctuation">::</span>recursive_directory_iterator <span class="token function">iter</span><span class="token punctuation">(</span>rootPath<span class="token punctuation">)</span><span class="token punctuation">;</span> iter <span class="token operator">!=</span> end<span class="token punctuation">;</span> iter<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 目录下 有目录文件 也有普通文件, 普通文件不仅仅只有 .html文件, 所以还需要过滤掉目录文件和非.html文件</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>bs_fs<span class="token double-colon punctuation">::</span><span class="token function">is_regular_file</span><span class="token punctuation">(</span><span class="token operator">*</span>iter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 不是普通文件</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>iter<span class="token operator">-></span><span class="token function">path</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">extension</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token string">".html"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// boost::path 对象的 extension()接口, 可以获取到所指文件的后缀</span> <span class="token comment">// 不是 html 文件</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 走到这里的都是 .html 文件</span> <span class="token comment">// 将 文件名存储到 filesList 中</span> filesList<span class="token operator">-></span><span class="token function">push_back</span><span class="token punctuation">(</span>iter<span class="token operator">-></span><span class="token function">path</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">parseTitle</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> fileContent<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> title<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 简单分析一个html文件, 可以发现 <title>标签只有一对 格式是这样的: <title> , 并且内部不会有其他字段</span> <span class="token comment">// 在 > < 之间就是这个页面的 title , 所以我们想要获取 title 就只需要获取<title>和 之间的内容就可以了 // 1. 先找 </span> std<span class="token double-colon punctuation">::</span>size_t begin <span class="token operator">=</span> fileContent<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">"<title>"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>begin <span class="token operator">==</span> std<span class="token double-colon punctuation">::</span>string<span class="token double-colon punctuation">::</span>npos<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 没找到</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> std<span class="token double-colon punctuation">::</span>size_t end <span class="token operator">=</span> fileContent<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">""); if (end == std::string::npos) { // 没找到 return false; } // 走到这里就是都找到了, 然后就可以获取 > <之间的内容了 begin += std::string(""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 让begin从>后一位开始</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>begin <span class="token operator">></span> end<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">*</span>title <span class="token operator">=</span> fileContent<span class="token punctuation">.</span><span class="token function">substr</span><span class="token punctuation">(</span>begin<span class="token punctuation">,</span> end <span class="token operator">-</span> begin<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">parseContent</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> fileContent<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> content<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// parseContent 需要实现的功能是, 清除标签</span> <span class="token comment">// html的语法都是有一定的格式的. 虽然标签可能会成对出现 <head></head>, 也可能会单独出现 <mate></span> <span class="token comment">// 但是 标签的的内容永远都是在相邻的 < 和 >之间的, 在 > 和 < 之间的则是是正文的内容</span> <span class="token comment">// 并且, html文件中的第一个字符永远都是 <, 并且之后还会有> 成对出现</span> <span class="token comment">// 可以根据这种语法特性来遍历整个文件内容 清除标签</span> <span class="token keyword">enum</span> <span class="token class-name">status</span> <span class="token punctuation">{</span> LABLE<span class="token punctuation">,</span> <span class="token comment">// 表示在标签内</span> CONTENT <span class="token comment">// 表示在正文内</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">enum</span> <span class="token class-name">status</span> s <span class="token operator">=</span> LABLE<span class="token punctuation">;</span> <span class="token comment">// 因为首先的状态一定是在标签内</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> c <span class="token operator">:</span> fileContent<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> LABLE<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 如果此时的c表示标签内的内容, 不做处理</span> <span class="token comment">// 除非 当c等于>时, 表示即将出标签, 此时需要切换状态</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'>'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> s <span class="token operator">=</span> CONTENT<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">case</span> CONTENT<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 此时 c 表示正文的内容, 所以需要存储在 content中, 但是为了后面存储以及分割不同文档, 所以也不要存储 \n, 将 \n 换成 ' '存储</span> <span class="token comment">// 并且, 当c表示<时, 也就不要存储了, 表示已经出了正文内容, 需要切换状态</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'<'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> s <span class="token operator">=</span> LABLE<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token char">'\n'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> c <span class="token operator">=</span> <span class="token char">' '</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">*</span>content <span class="token operator">+=</span> c<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">parseUrl</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> filePath<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">*</span> url<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 先去官网看一看 官网的url是怎么分配的: https://www.boost.org/doc/libs/1_82_0/doc/html/function/reference.html</span> <span class="token comment">// 我们本地下载的boost库的html路径又是怎么分配的: boost_1_82_0/doc/html/function/reference.html</span> <span class="token comment">// 我们在程序中获取的文件路径 即项目中文件的路径 又是什么: data/input/function/reference.html</span> <span class="token comment">// 已经很明显了, url 的获取就是 https://www.boost.org/doc/libs/1_82_0/doc/html + /function/reference.html</span> <span class="token comment">// 其中, 如果版本不变的话, https://www.boost.org/doc/libs/1_82_0/doc/html 是固定的</span> <span class="token comment">// 而后半部分, 则是 filePath 除去 data/input, 也就是 const std::string srcPath = "data/input" 部分</span> <span class="token comment">// 所以, url的获取也很简单</span> std<span class="token double-colon punctuation">::</span>string urlHead <span class="token operator">=</span> <span class="token string">"https://www.boost.org/doc/libs/1_82_0/doc/html"</span><span class="token punctuation">;</span> std<span class="token double-colon punctuation">::</span>string urlTail <span class="token operator">=</span> filePath<span class="token punctuation">.</span><span class="token function">substr</span><span class="token punctuation">(</span>srcPath<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 从srcPath长度处向后截取</span> <span class="token operator">*</span>url <span class="token operator">=</span> urlHead <span class="token operator">+</span> urlTail<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">parseDocInfo</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>string<span class="token operator">></span><span class="token operator">&</span> filesList<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span><span class="token operator">*</span> docResults<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// parseDocInfo 是对文档html文件的内容做去标签化 并 获取 title content url 构成结构体</span> <span class="token comment">// 文档的路径都在 filesList 中存储着, 所以需要遍历 filesList 处理文件</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> filePath <span class="token operator">:</span> filesList<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 获取到文档html的路径之后, 就需要对 html文件进行去标签化等一系列解析操作了</span> <span class="token comment">// 1. 读取文件内容到 string 中</span> std<span class="token double-colon punctuation">::</span>string fileContent<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>ns_util<span class="token double-colon punctuation">::</span>fileUtil<span class="token double-colon punctuation">::</span><span class="token function">readFile</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> <span class="token operator">&</span>fileContent<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 读取文件内容失败</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 读取到文档html文件内容之后, 就可以去标签 并且 获取 title content 和 url了</span> docInfo_t doc<span class="token punctuation">;</span> <span class="token comment">// 2. 解析并获取title, html文件中只有一个 title标签, 所以再去标签之前 获取title比较方便</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">parseTitle</span><span class="token punctuation">(</span>fileContent<span class="token punctuation">,</span> <span class="token operator">&</span>doc<span class="token punctuation">.</span>_title<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 解析title失败</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 3. 解析并获取文档有效内容, 去标签的操作实际就是在这一步进行的</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">parseContent</span><span class="token punctuation">(</span>fileContent<span class="token punctuation">,</span> <span class="token operator">&</span>doc<span class="token punctuation">.</span>_content<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 解析文档有效内容失败</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 4. 获取 官网的对应文档的 url</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">parseUrl</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> <span class="token operator">&</span>doc<span class="token punctuation">.</span>_url<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 做完上面的一系列操作 走到这里时 如果没有不过 doc 应该已经被填充完毕了</span> <span class="token comment">// doc出此次循环时就要被销毁了, 所以将doc 设置为将亡值 可以防止拷贝构造的发生 而使用移动语义来向 vector中添加元素</span> <span class="token comment">// 这里发生拷贝构造是非常的消耗资源的 因为 doc._content 非常的大</span> docResults<span class="token operator">-></span><span class="token function">push_back</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span><span class="token function">move</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">bool</span> <span class="token function">saveDocInfo</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>docInfo_t<span class="token operator">></span><span class="token operator">&</span> docResults<span class="token punctuation">,</span> <span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> output<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 最后就是将 已经结构化的所有的文档数据, 以一定的格式存储在指定的文件中.</span> <span class="token comment">// 以什么格式存储呢? 每个文档都是结构化的数据: _title _content _url.</span> <span class="token comment">// 我们可以将 三个字段以'\3'分割, 不过 _url后不用'\3' 而是用'\n'</span> <span class="token comment">// 因为, 像文件中写入不能只关心写入, 还要考虑读取时的问题. 方便的 读取文本文件, 通常可以用 getline 来获取一行数据</span> <span class="token comment">// 所以, 当以这种格式 (_title\3_content\3_url\n) 将 文档数据存储到文件中时, getline() 成功读取一次文件内容, 获取的就是一个文档的所有有效内容.</span> <span class="token comment">// 按照二进制方式进行写入, 二进制写入, 写入什么就是什么 转义字符也不会出现被优化改变的现象</span> std<span class="token double-colon punctuation">::</span>ofstream <span class="token function">out</span><span class="token punctuation">(</span>output<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>ios<span class="token double-colon punctuation">::</span>out <span class="token operator">|</span> std<span class="token double-colon punctuation">::</span>ios<span class="token double-colon punctuation">::</span>binary<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>out<span class="token punctuation">.</span><span class="token function">is_open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 文件打开失败</span> std<span class="token double-colon punctuation">::</span>cerr <span class="token operator"><<</span> <span class="token string">"open "</span> <span class="token operator"><<</span> output <span class="token operator"><<</span> <span class="token string">" failed!"</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 就可以进行文件内容的写入了</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token operator">&</span> item <span class="token operator">:</span> docResults<span class="token punctuation">)</span> <span class="token punctuation">{</span> std<span class="token double-colon punctuation">::</span>string outStr<span class="token punctuation">;</span> outStr <span class="token operator">=</span> item<span class="token punctuation">.</span>_title<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> SEP<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> item<span class="token punctuation">.</span>_content<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> SEP<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> item<span class="token punctuation">.</span>_url<span class="token punctuation">;</span> outStr <span class="token operator">+=</span> <span class="token char">'\n'</span><span class="token punctuation">;</span> out<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>outStr<span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> outStr<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> out<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>上面就是项目中 <code>parser</code>模块的全部代码了.</p> <p>编译代码, 并运行可执行程序:</p> <p></p> <p>可以看到, <code>raw</code>文件中, 每行都是一个文档的<code>docInfo</code>信息数据.</p> <h1><code>parser</code>模块的作用</h1> <p>在上一篇介绍<code>Boost文档站内搜索引擎 项目背景</code>文章中, 就提到过:</p> <blockquote> <p>搜索引擎索引的建立步骤一般是这样的:</p> <ol> <li>爬虫程序爬取网络上的内容, 获取网页等数据</li> <li>对爬取的内容进行解析、去标签, 提取文本、链接、媒体内容等信息</li> <li>对提取的文本进行分词、处理, 得到词条</li> <li>根据词条生成索引, 包括正排索引、倒排索引等</li> </ol> </blockquote> <p>爬取网页数据我们不需要做, 可以直接从官网下载源码.</p> <p>但是, 后面的步骤就需要自己动手做了.</p> <p>而<code>parser</code>解析器 模块做的 就是建立索引的第2个步骤: <strong>对爬取的内容进行解析、去标签, 提取文本、链接、媒体内容等信息</strong></p> <p>我们实现的<code>parser</code>解析器, 就是对 所有文档<code>html</code>文件的内容, 进行去标签, 提取文本, 链接等操作, 并将所有内汇总在一个文件中.</p> <hr> <p>OK, 本篇文章到这里就结束了~</p> <p>感谢阅读~</p> </div> </div>���� </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1687333576191848448"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(c++,搜索引擎,服务器,项目,Boost)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1892551831830196224.htm" title="“深入浅出”系列之QT:(10)Qt接入Deepseek" target="_blank">“深入浅出”系列之QT:(10)Qt接入Deepseek</a> <span class="text-muted">我真不会起名字啊</span> <a class="tag" taget="_blank" href="/search/qt/1.htm">qt</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>项目配置:在.pro文件中添加网络模块:QT+=corenetworkAPI配置:将apiUrl替换为实际的DeepSeekAPI端点将apiKey替换为你的有效API密钥根据API文档调整请求参数(模型名称、温度值等)功能说明:使用QNetworkAccessManager处理HTTP请求自动处理JSON序列化/反序列化支持异步请求处理包含基本的错误处理扩展建议:添加更完善的错误处理(HTTP状</div> </li> <li><a href="/article/1892549561214365696.htm" title="PHP 网络编程介绍" target="_blank">PHP 网络编程介绍</a> <span class="text-muted">来恩1003</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/1.htm">从入门到精通</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>PHP学习资料PHP学习资料PHP学习资料在当今数字化时代,网络编程是开发各类应用必不可少的技能。PHP作为一门广泛应用于Web开发的编程语言,同样具备强大的网络编程能力。接下来,我们将深入探讨PHP中网络连接的建立、Socket编程、HTTP请求与响应等网络相关的操作。一、网络连接的建立在PHP中建立网络连接,主要是通过使用内置的函数来实现与远程服务器的通信。最常见的是使用fsockopen函数</div> </li> <li><a href="/article/1892549562233581568.htm" title="PHP 安全与加密:守护 Web 应用的基石" target="_blank">PHP 安全与加密:守护 Web 应用的基石</a> <span class="text-muted">来恩1003</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A/1.htm">从入门到精通</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>PHP学习资料PHP学习资料PHP学习资料在当今数字化时代,Web应用无处不在,而PHP作为一种广泛使用的服务器端脚本语言,承载着无数网站和应用的核心逻辑。然而,随着网络攻击手段日益复杂,PHP应用面临着诸多安全威胁,如SQL注入、XSS攻击等,同时,数据的加密保护也至关重要。本文将深入探讨PHP中的安全问题及加密算法的应用,帮助开发者构建更安全可靠的Web应用。一、PHP安全之殇——SQL注入攻</div> </li> <li><a href="/article/1892549182993002496.htm" title="C++ 一篇读懂“值传递”和“地址传递”" target="_blank">C++ 一篇读懂“值传递”和“地址传递”</a> <span class="text-muted">xzal12</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a> <div>让我们通过一个简单的、形象的比喻来帮助你理解“值传递”和“地址传递”是如何影响实参的。1.值传递想象你有一个**信封**(代表变量),里面放着一张纸条(代表数据)。你决定把这个信封寄给一个朋友,让他们看一下纸条的内容。-**过程**:你把信封寄给朋友,但你实际上给朋友的是一个**副本**,也就是你将信封和纸条的内容完全复制了一份。-**结果**:你的朋友可以看到纸条上的内容,但他们修改纸条内容时,</div> </li> <li><a href="/article/1892549055603601408.htm" title="C++ 给数组整体(批量)赋值" target="_blank">C++ 给数组整体(批量)赋值</a> <span class="text-muted">xzal12</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a> <div>1、memset函数给数组按字节赋值为内存做初始化工作需要头文件#include(1)给char类型数组按字节赋值,其中char占一个字节(2)int类型数组按字节赋值0和1,其中int占4个字节=4*8位eg1:memset(a,0,sizeof(a));//将a数组所有元素均赋值为0eg2:memset(b,1,sizeof(b));//将b数组所有元素均赋值为二进制数2^0+2^8+2^16</div> </li> <li><a href="/article/1892547290195881984.htm" title="第26篇:pFedLoRA: Model-Heterogeneous Personalized Federated Learning with LoRA使用lora微调的模型异构个性化联邦学习" target="_blank">第26篇:pFedLoRA: Model-Heterogeneous Personalized Federated Learning with LoRA使用lora微调的模型异构个性化联邦学习</a> <span class="text-muted">还不秃顶的计科生</span> <a class="tag" taget="_blank" href="/search/%E8%81%94%E9%82%A6%E5%AD%A6%E4%B9%A0/1.htm">联邦学习</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>第一部分:解决的问题联邦学习(FederatedLearning,FL)是一种分布式机器学习方法,允许客户端在本地数据上训练模型,同时通过中心服务器共享学习成果。传统FL框架假设客户端使用相同的模型结构(模型同构),但在实际中可能面对:统计异质性:客户端的数据分布不均(non-IID)。资源异质性:客户端硬件资源有限。模型异质性:客户端可能拥有不同的模型结构。模型异构的个性化联邦学习(MHPFL)</div> </li> <li><a href="/article/1892547038088851456.htm" title="零基础学会asp.net做AI大模型网站/小程序十六:专栏总结" target="_blank">零基础学会asp.net做AI大模型网站/小程序十六:专栏总结</a> <span class="text-muted">借雨醉东风</span> <a class="tag" taget="_blank" href="/search/asp.net/1.htm">asp.net</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>本专栏以实战为主,轻理论。如果哪里有不太懂的,可关注博主后加个人微信(平台规定文章中不能贴联系方式,需先关注博主,再加微信),后续一起交流学习。-------------------------------------正文----------------------------------------目录本专栏总结后续方向项目简介项目结构使用方法项目地址关键特点LLaMA机器学习简介使用LLaMA</div> </li> <li><a href="/article/1892544892337451008.htm" title="vue中原生表格的使用" target="_blank">vue中原生表格的使用</a> <span class="text-muted">今天吃了嘛o</span> <a class="tag" taget="_blank" href="/search/table%E5%8E%9F%E7%94%9F/1.htm">table原生</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a> <div>因项目中需要大量的合并,而且表格左右布局,所以采用了原生table。colspan和rowspan分别代表合并多少行多少列。代码如下:线路名称{{item.lineName}}巡检区段{{item.scope}}运维管理单位{{item.operationAndMaintenanceCompany}}运检作业单位{{item.insWorkCompany}}巡检员{{item.droneWorkU</div> </li> <li><a href="/article/1892543883510870016.htm" title="自适应键盘,自带隐藏键盘的输入框(UITextField)" target="_blank">自适应键盘,自带隐藏键盘的输入框(UITextField)</a> <span class="text-muted">胖虎1</span> <a class="tag" taget="_blank" href="/search/UI%E5%B0%8F%E7%BB%84%E4%BB%B6/1.htm">UI小组件</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%BE%93%E5%85%A5%E6%A1%86/1.htm">自定义输入框</a><a class="tag" taget="_blank" href="/search/%E9%94%AE%E7%9B%98/1.htm">键盘</a><a class="tag" taget="_blank" href="/search/UITextField/1.htm">UITextField</a> <div>引言在iOS开发中,输入框占据着举足轻重的地位。与安卓不同,iOS输入框经常面临键盘遮挡的问题,或者无法方便地取消键盘。为了解决这些问题,有许多针对iOS键盘管理的库,如IQKeyboardManager、TPKeyboardAvoiding和KeyboardManager等等。然而,一些库可能对整个项目的侵入性较大,可能会影响到其他功能。有时,我们可能不希望某些输入框被这些库管理,虽然它们通常也</div> </li> <li><a href="/article/1892543379292614656.htm" title="vue中使用ueditor上传到服务器_vue+Ueditor集成 [前后端分离项目][图片、文件上传][富文本编辑]..." target="_blank">vue中使用ueditor上传到服务器_vue+Ueditor集成 [前后端分离项目][图片、文件上传][富文本编辑]...</a> <span class="text-muted">小西超人</span> <div>写在最前面的话:鉴于近期很多的博友讨论,说我按照文章的一步一步来,弄好之后,怎么会提示后端配置项http错误,文件上传会提示上传错误。这里提别申明一点,ueditor在前端配置好后,需要与后端部分配合进行,后端部分的项目代码git地址:https://github.com/coderliguoqing/UeditorSpringboot,然后将配置ueditor.config.js里的server</div> </li> <li><a href="/article/1892541989010862080.htm" title="基于Linux平台的多实例RTSP|RTMP直播播放器深度解析与技术实现" target="_blank">基于Linux平台的多实例RTSP|RTMP直播播放器深度解析与技术实现</a> <span class="text-muted">音视频牛哥</span> <a class="tag" taget="_blank" href="/search/RTSP%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">RTSP播放器</a><a class="tag" taget="_blank" href="/search/RTMP%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">RTMP播放器</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E7%89%9B%E7%9B%B4%E6%92%ADSDK/1.htm">大牛直播SDK</a><a class="tag" taget="_blank" href="/search/%E9%9F%B3%E8%A7%86%E9%A2%91/1.htm">音视频</a><a class="tag" taget="_blank" href="/search/%E5%AE%9E%E6%97%B6%E9%9F%B3%E8%A7%86%E9%A2%91/1.htm">实时音视频</a><a class="tag" taget="_blank" href="/search/%E8%A7%86%E9%A2%91%E7%BC%96%E8%A7%A3%E7%A0%81/1.htm">视频编解码</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/rtsp%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">rtsp播放器</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/rtmp%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">rtmp播放器</a><a class="tag" taget="_blank" href="/search/linux%E5%9B%BD%E4%BA%A7rtmp%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">linux国产rtmp播放器</a><a class="tag" taget="_blank" href="/search/linux%E5%9B%BD%E4%BA%A7rtsp%E6%92%AD%E6%94%BE%E5%99%A8/1.htm">linux国产rtsp播放器</a> <div>一、引言在Linux平台上实现一个高性能、高并发的多实例播放器,是许多流媒体应用的核心需求。本文将结合大牛直播SDK的Linux平台RTSP/RTMP播放器功能,深入解析其实现原理、关键技术点以及优化策略。通过对代码的详细分析和实际应用的结合,帮助开发者更好地理解和应用该技术。二、项目概述本文基于以下代码实现了一个多实例播放器:multi_player_demo.cpp:主程序,负责初始化SDK、</div> </li> <li><a href="/article/1892541358825074688.htm" title="uniapp开发APP,主动连接mqtt,订阅消息" target="_blank">uniapp开发APP,主动连接mqtt,订阅消息</a> <span class="text-muted">路痴先森</span> <a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a> <div>一、安装依赖通过查阅资料,了解到现在mqtt.js库的最新版本已经是5,但是目前应该mqtt@3.0.0版本最为稳定,我项目开发中使用的也是mqtt@3.0.0版本npminstallmqtt@3.0.0参考插件:MQTT使用-模板项目-DCloud插件市场参考文档:GitHub-mqttjs/MQTT.js:TheMQTTclientforNode.jsandthebrowser二、封装一个工具</div> </li> <li><a href="/article/1892540980872146944.htm" title="深入解析 C++ STL中的 std::map 容器" target="_blank">深入解析 C++ STL中的 std::map 容器</a> <span class="text-muted">金外飞176</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a> <div>深入解析C++中的std::map容器在C++标准模板库(STL)中,std::map是一种非常强大且常用的关联式容器。它通过键值对(key-value)的方式存储数据,并且基于红黑树实现,能够高效地进行插入、删除和查找操作。本文将通过一个实际的项目代码,深入探讨std::map的各种特性,包括构造、插入、删除、查找、排序以及与其他容器的交互。1.std::map的基本概念std::map是一个关</div> </li> <li><a href="/article/1892540853390471168.htm" title="vuecli项目实战--管理系统" target="_blank">vuecli项目实战--管理系统</a> <span class="text-muted">团团kobebryant</span> <a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE/1.htm">项目</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>一、项目搭建HBuider直接:新建--项目--填项目名称、选地址、下拉选vue项目(2.6.10)项目结构这个样子:二、前端配置1.路由配置(地址)在src文件夹下创建router文件夹在router文件夹下面创建js文件index.js---配置组件的地址还有导航守卫、路由嵌套也配在这里1.组件路由2.组件路由嵌套3.路由导航记得跟vue对象关联还有导出路由嗷importVuefrom'vue</div> </li> <li><a href="/article/1892540346982789120.htm" title="【vue 后台管理模板 ranAdmin 支持ant-design/ant-design/electron-plus/electron-plus-electron】" target="_blank">【vue 后台管理模板 ranAdmin 支持ant-design/ant-design/electron-plus/electron-plus-electron】</a> <span class="text-muted">RanShakaLove</span> <a class="tag" taget="_blank" href="/search/ranAdmin/1.htm">ranAdmin</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/electron/1.htm">electron</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/electron/1.htm">electron</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>【vue后台管理模板支持ant-design/ant-design/electron-plus/electron-plus-electron】个性化功能项目主要功能项目演示github地址vue-ant-designgitee地址vue-ant-design项目地址项目4个分支ant-designant-dessign-electronelement-pluselement-plus-electr</div> </li> <li><a href="/article/1892539968312635392.htm" title="基于若依和flowable6.7.2的ruoyi-nbcio流程管理系统正式发布" target="_blank">基于若依和flowable6.7.2的ruoyi-nbcio流程管理系统正式发布</a> <span class="text-muted">宁波阿成</span> <a class="tag" taget="_blank" href="/search/ruoyi-nbcio/1.htm">ruoyi-nbcio</a><a class="tag" taget="_blank" href="/search/%E8%8B%A5%E4%BE%9D/1.htm">若依</a><a class="tag" taget="_blank" href="/search/flowable/1.htm">flowable</a><a class="tag" taget="_blank" href="/search/flowable/1.htm">flowable</a><a class="tag" taget="_blank" href="/search/%E8%8B%A5%E4%BE%9D/1.htm">若依</a><a class="tag" taget="_blank" href="/search/ruoyi-nbcio/1.htm">ruoyi-nbcio</a><a class="tag" taget="_blank" href="/search/ruoyi/1.htm">ruoyi</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a> <div>更多ruoyi-nbcio功能请看演示系统gitee源代码地址前后端代码:https://gitee.com/nbacheng/ruoyi-nbcio演示地址:RuoYi-Nbcio后台管理系统项目概要本项目基于RuoYi-Flowable-Plus进行二次开发,从nbcio-boot(https://gitee.com/nbacheng/nbcio-boot)项目</</div> </li> <li><a href="/article/1892539085134819328.htm" title="记录App中加入Mqtt实现过程" target="_blank">记录App中加入Mqtt实现过程</a> <span class="text-muted">街角的小菜鸟</span> <a class="tag" taget="_blank" href="/search/Android%E5%BC%80%E5%8F%91/1.htm">Android开发</a> <div>前言因为公司项目里因为功能的修改,移除了关于无人机飞控控制的代码部分,软件中无人机信息变更为通过mqtt获取,通过翻阅网上资料后,终于实现了该功能。现在写下来,以免再次用到要重新查找资料。MQTT的相关了解Topic:订阅的主题。URI:MQTT服务器的地址例如:"tcp://"+MQTT_HOST+":"+MQTT_PORTusername&password:账户与密码ClientId:客户端的</div> </li> <li><a href="/article/1892538578999767040.htm" title="基于Transformer的YOLOv8检测头架构改进:提升目标检测精度的全新突破(YOLOv8)" target="_blank">基于Transformer的YOLOv8检测头架构改进:提升目标检测精度的全新突破(YOLOv8)</a> <span class="text-muted">步入烟尘</span> <a class="tag" taget="_blank" href="/search/transformer/1.htm">transformer</a><a class="tag" taget="_blank" href="/search/YOLO/1.htm">YOLO</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/1.htm">目标检测</a> <div>本专栏专为AI视觉领域的爱好者和从业者打造。涵盖分类、检测、分割、追踪等多项技术,带你从入门到精通!后续更有实战项目,助你轻松应对面试挑战!立即订阅,开启你的YOLOv8之旅!专栏订阅地址:https://blog.csdn.net/mrdeam/category_12804295.html文章目录基于Transformer的YOLOv8检测头架构改进:提升目标检测精度的全新突破什么是DAtten</div> </li> <li><a href="/article/1892538580790734848.htm" title="vscode保存自动将CRLF 转换成 LF" target="_blank">vscode保存自动将CRLF 转换成 LF</a> <span class="text-muted">沐歌丨丶</span> <a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>1、下载vscode插件:EditorConfigforVSCode2、在项目根目录新建.editorconfigroot=true[*]charset=utf-8indent_style=spaceindent_size=2end_of_line=lfinsert_final_newline=truetrim_trailing_whitespace=true</div> </li> <li><a href="/article/1892536182668062720.htm" title="前后端分离跨域问题解决方案" target="_blank">前后端分离跨域问题解决方案</a> <span class="text-muted">慕容屠苏</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%89%8D%E7%AB%AF%E7%88%AC%E5%9D%91%E4%B9%8B%E8%B7%AF/1.htm">大前端爬坑之路</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E5%90%8E%E7%AB%AF%E5%88%86%E7%A6%BB/1.htm">前后端分离</a><a class="tag" taget="_blank" href="/search/%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/1.htm">跨域问题解决方案</a> <div>前后端分离跨域问题解决方案现在的web开发中经常会用到前后分离技术,前后端分解技术,都会涉及到跨域问题。解决跨域问题的方法:第一种解决方案jsonp(不推荐使用)这种方案其实我是不赞同的,第一,在编码上jsonp会单独因为回调的关系,在传入传出还有定义回调函数上都会有编码的”不整洁”.简单阐述jsonp能够跨域是因为javascript的script标签,通过服务器返回script标签的code,</div> </li> <li><a href="/article/1892529999513186304.htm" title="AJAX使用和固定格式" target="_blank">AJAX使用和固定格式</a> <span class="text-muted">乐多_L</span> <a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>ajax的全称AsynchronousJavaScriptandXML(异步JavaScript和XML)。ajax是一种创建交互式网页应用的网页开发技术。其中最核心的依赖是浏览器提供的XMLHttpRequest对象,是这个对象使得浏览器可以发出HTTP请求与接收HTTP响应。实现了在页面不刷新的情况下和服务器进行交互。方法描述newXMLHttpRequest()生成一个XMLHttpRequ</div> </li> <li><a href="/article/1892529746508574720.htm" title="基于java新闻管理系统,推荐一款开源cms内容管理系统ruoyi-fast-cms" target="_blank">基于java新闻管理系统,推荐一款开源cms内容管理系统ruoyi-fast-cms</a> <span class="text-muted">xnqys</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E6%BA%90/1.htm">开源</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E6%BA%90/1.htm">开源</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>一、项目概述1.1项目背景在信息高速流通的当下,新闻媒体行业每天都要处理和传播海量信息。传统的新闻管理模式依赖人工操作,在新闻采集、编辑、发布以及后续管理等环节中,不仅效率低下,而且容易出现人为失误。同时,面对用户日益多样化的信息获取需求,传统方式也难以实现个性化、精准化的内容推送。而Java语言凭借其跨平台性、安全性、稳定性以及丰富的类库和强大的开发框架,成为开发新闻管理系统的理想选择。通过基于</div> </li> <li><a href="/article/1892528359695511552.htm" title="详细介绍:封装简易的 Axios 函数获取省份列表" target="_blank">详细介绍:封装简易的 Axios 函数获取省份列表</a> <span class="text-muted">还是鼠鼠</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/vscode/1.htm">vscode</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a> <div>目录关键步骤:完整代码(html):代码解析:程序运行结果:本示例展示了如何通过封装一个简易的myAxios函数来模拟axios的功能,使用原生的XMLHttpRequest(XHR)对象来发起HTTP请求。我们将实现一个简单的功能,通过该封装函数从服务器获取省份列表数据,并在网页上显示这些省份。关键步骤:封装myAxios函数:myAxios函数接收一个配置对象(如请求的URL和方法),并返回一</div> </li> <li><a href="/article/1892525332959916032.htm" title="mysql 最大连接数超时_MySQL连接数过大导致连接超时的问题" target="_blank">mysql 最大连接数超时_MySQL连接数过大导致连接超时的问题</a> <span class="text-muted">你认识小鲍鱼吗</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E6%9C%80%E5%A4%A7%E8%BF%9E%E6%8E%A5%E6%95%B0%E8%B6%85%E6%97%B6/1.htm">最大连接数超时</a> <div>春节访问量激增,负载压力很大,程序处理较慢,然后就调整项目中的线程池和数据库连接数。可是还是没有太好的提高,追根溯源,发现数据库连接受到限制。虽然是做了读写分离,但是还是没抗住高峰。所以会有报错:“MySQL:ERROR1040:Toomanyconnections”。查看最大连接数上限,默认的是151mysql>showvariableslike'max_connections';+------</div> </li> <li><a href="/article/1892523567237623808.htm" title="Java 中的包(Package)与导入(Import)详解" target="_blank">Java 中的包(Package)与导入(Import)详解</a> <span class="text-muted">小刘|</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>目录一、引言二、包的概念(一)包的定义与作用(二)JDK中主要的包三、导入的概念(一)导入的目的与用法(二)特殊情况的导入四、补充知识点(一)静态导入(二)包的访问权限(三)包的命名规范五、总结一、引言在Java编程中,包(Package)和导入(Import)是非常重要的概念。它们帮助我们更好地组织代码、管理项目结构、解决命名冲突以及控制访问权限。本文将详细介绍Java中的包和导入的相关知识,通</div> </li> <li><a href="/article/1892523315201896448.htm" title="手把手教你怎么用QT进行TCP数据通信" target="_blank">手把手教你怎么用QT进行TCP数据通信</a> <span class="text-muted">JackRedWind</span> <a class="tag" taget="_blank" href="/search/QT%E5%9F%BA%E7%A1%80%E6%95%99%E5%AD%A6/1.htm">QT基础教学</a><a class="tag" taget="_blank" href="/search/qt/1.htm">qt</a><a class="tag" taget="_blank" href="/search/tcp%2Fip/1.htm">tcp/ip</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a> <div>在前面两篇我们已经构建了最基础的网络连接手把手教你们怎么在QT中使用TCP-CSDN博客手把手教你怎么用QT写Tcp客户端-CSDN博客接下来我要让服务器和客户端之间进行网络通信,所谓通信其实很简单,就是发送和接受。由于qt有信号槽机制,我们可以用信号来通知程序处理收到的数据。1.这里我们先给服务器加入接受数据的槽函数,如下图2.这里我们只要触发readyRead的信号,就会通过qDebug()打</div> </li> <li><a href="/article/1892521550163275776.htm" title="快速提升网站收录率的10个步骤" target="_blank">快速提升网站收录率的10个步骤</a> <span class="text-muted">百度网站快速收录</span> <a class="tag" taget="_blank" href="/search/%E7%99%BE%E5%BA%A6%E7%BD%91%E7%AB%99%E5%BF%AB%E9%80%9F%E6%94%B6%E5%BD%95/1.htm">百度网站快速收录</a><a class="tag" taget="_blank" href="/search/%E7%99%BE%E5%BA%A6%E5%BF%AB%E9%80%9F%E6%94%B6%E5%BD%95/1.htm">百度快速收录</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%AB%99%E5%BF%AB%E9%80%9F%E6%94%B6%E5%BD%95/1.htm">网站快速收录</a><a class="tag" taget="_blank" href="/search/%E7%99%BE%E5%BA%A6%E6%94%B6%E5%BD%95/1.htm">百度收录</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%AB%99%E6%94%B6%E5%BD%95/1.htm">网站收录</a> <div>快速提升网站收录率需要综合考虑多个方面,以下是10个具体步骤,旨在帮助网站更快地获得搜索引擎的收录:1.提交网站地图制作并提交XML站点地图:站点地图是一个包含网站所有页面链接的文件,有助于搜索引擎快速发现和抓取网站内容。通过提交站点地图给搜索引擎,可以显著提高网站的收录速度。2.保持内容更新定期发布高质量内容:搜索引擎喜欢更新频繁的网站,因此保持网站内容的定期更新是提高收录率的关键。确保内容原创</div> </li> <li><a href="/article/1892520036933890048.htm" title="如何解决分布式应用数量庞大而导致数据库连接数满的问题?" target="_blank">如何解决分布式应用数量庞大而导致数据库连接数满的问题?</a> <span class="text-muted">纵然间</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>修改数据库服务器的配置文件或参数来增加最大连接数限制。例如,在MySQL中,可以通过修改my.cnf(Linux)或my.ini(Windows)文件中的max_connections参数来增加最大连接数。具体的操作方法可以参考数据库服务器的官方文档或相关技术支持。检查应用程序代码,确保在使用完数据库连接后及时释放连接资源,避免长时间占用连接而导致连接数不足。可以使用连接池技术来管理数据库连接,提</div> </li> <li><a href="/article/1892519910530150400.htm" title="基于立创·天空星开发板-GD32F407VET6-青春版,开发一款手持热成像仪。该设备将采集热红外传感器的数据,经过处理后在LCD屏幕上显示热图像,并提供用户交互界面。" target="_blank">基于立创·天空星开发板-GD32F407VET6-青春版,开发一款手持热成像仪。该设备将采集热红外传感器的数据,经过处理后在LCD屏幕上显示热图像,并提供用户交互界面。</a> <span class="text-muted">嵌入式程序员小刘</span> <a class="tag" taget="_blank" href="/search/%E7%89%A9%E8%81%94%E7%BD%91/1.htm">物联网</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E6%BA%90/1.htm">开源</a> <div>本项目基于立创·天空星开发板-GD32F407VET6-青春版,开发一款手持热成像仪。该设备将采集热红外传感器的数据,经过处理后在LCD屏幕上显示热图像,并提供用户交互界面。关注微信公众号,提前获取相关推文一、需求分析核心功能:热图像采集:读取热红外传感器数据。图像处理:将原始传感器数据转换为可显示的彩色或灰度热图像。图像显示:在LCD屏幕上实时显示热图像。温度测量:计算并显示图像中特定点的温度值</div> </li> <li><a href="/article/1892519279048323072.htm" title="GUI编程(window系统→Linux系统)" target="_blank">GUI编程(window系统→Linux系统)</a> <span class="text-muted">诚信爱国敬业友善</span> <a class="tag" taget="_blank" href="/search/%E5%BF%83%E5%BE%97/1.htm">心得</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/gui/1.htm">gui</a> <div>最近有个项目需要将windows系统的程序往Linux系统上面移植,由于之前程序没有考虑过多平台兼容的问题,导致部分功能不可用以下是对近期遇到的问题的总结,以及相应的解决方案和经验分享。1.Python模块安装与管理在Linux系统中,安装和管理Python模块时可能会遇到权限问题或依赖冲突。安装模块:使用pip安装模块时,建议使用--user选项,避免需要管理员权限:bash复制pipinsta</div> </li> <li><a href="/article/116.htm" title="ViewController添加button按钮解析。(翻译)" target="_blank">ViewController添加button按钮解析。(翻译)</a> <span class="text-muted">张亚雄</span> <a class="tag" taget="_blank" href="/search/c/1.htm">c</a> <div><div class="it610-blog-content-contain" style="font-size: 14px"></div>//  ViewController.m //  Reservation software // //  Created by 张亚雄 on 15/6/2. </div> </li> <li><a href="/article/243.htm" title="mongoDB 简单的增删改查" target="_blank">mongoDB 简单的增删改查</a> <span class="text-muted">开窍的石头</span> <a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a> <div>   在上一篇文章中我们已经讲了mongodb怎么安装和数据库/表的创建。在这里我们讲mongoDB的数据库操作       在mongo中对于不存在的表当你用db.表名 他会自动统计 下边用到的user是表明,db代表的是数据库       添加(insert): </div> </li> <li><a href="/article/370.htm" title="log4j配置" target="_blank">log4j配置</a> <span class="text-muted">0624chenhong</span> <a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a> <div>1) 新建java项目 2) 导入jar包,项目右击,properties—java build path—libraries—Add External jar,加入log4j.jar包。 3) 新建一个类com.hand.Log4jTest package com.hand; import org.apache.log4j.Logger; public class </div> </li> <li><a href="/article/497.htm" title="多点触摸(图片缩放为例)" target="_blank">多点触摸(图片缩放为例)</a> <span class="text-muted">不懂事的小屁孩</span> <a class="tag" taget="_blank" href="/search/%E5%A4%9A%E7%82%B9%E8%A7%A6%E6%91%B8/1.htm">多点触摸</a> <div>多点触摸的事件跟单点是大同小异的,上个图片缩放的代码,供大家参考一下 import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener</div> </li> <li><a href="/article/624.htm" title="有关浏览器窗口宽度高度几个值的解析" target="_blank">有关浏览器窗口宽度高度几个值的解析</a> <span class="text-muted">换个号韩国红果果</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>1 元素的 offsetWidth 包括border padding  content  整体的宽度。 clientWidth  只包括内容区 padding 不包括border。 clientLeft =  offsetWidth -clientWidth  即这个元素border的值 offsetLeft  若无已定位的包裹元素</div> </li> <li><a href="/article/751.htm" title="数据库产品巡礼:IBM DB2概览" target="_blank">数据库产品巡礼:IBM DB2概览</a> <span class="text-muted">蓝儿唯美</span> <a class="tag" taget="_blank" href="/search/db2/1.htm">db2</a> <div>IBM DB2是一个支持了NoSQL功能的关系数据库管理系统,其包含了对XML,图像存储和Java脚本对象表示(JSON)的支持。DB2可被各种类型的企 业使用,它提供了一个数据平台,同时支持事务和分析操作,通过提供持续的数据流来保持事务工作流和分析操作的高效性。 DB2支持的操作系统 DB2可应用于以下三个主要的平台:   工作站,DB2可在Linus、Unix、Windo</div> </li> <li><a href="/article/878.htm" title="java笔记5" target="_blank">java笔记5</a> <span class="text-muted">a-john</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>控制执行流程: 1,true和false    利用条件表达式的真或假来决定执行路径。例:(a==b)。它利用条件操作符“==”来判断a值是否等于b值,返回true或false。java不允许我们将一个数字作为布尔值使用,虽然这在C和C++里是允许的。如果想在布尔测试中使用一个非布尔值,那么首先必须用一个条件表达式将其转化成布尔值,例如if(a!=0)。 2,if-els</div> </li> <li><a href="/article/1005.htm" title="Web开发常用手册汇总" target="_blank">Web开发常用手册汇总</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a> <div>一门技术,如果没有好的参考手册指导,很难普及大众。这其实就是为什么很多技术,非常好,却得不到普遍运用的原因。 正如我们学习一门技术,过程大概是这个样子: ①我们日常工作中,遇到了问题,困难。寻找解决方案,即寻找新的技术; ②为什么要学习这门技术?这门技术是不是很好的解决了我们遇到的难题,困惑。这个问题,非常重要,我们不是为了学习技术而学习技术,而是为了更好的处理我们遇到的问题,才需要学习新的</div> </li> <li><a href="/article/1132.htm" title="今天帮助人解决的一个sql问题" target="_blank">今天帮助人解决的一个sql问题</a> <span class="text-muted">asialee</span> <a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a> <div>            今天有个人问了一个问题,如下: type     AD      value          A  </div> </li> <li><a href="/article/1259.htm" title="意图对象传递数据" target="_blank">意图对象传递数据</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E6%84%8F%E5%9B%BEIntent/1.htm">意图Intent</a><a class="tag" taget="_blank" href="/search/Bundle%E5%AF%B9%E8%B1%A1%E6%95%B0%E6%8D%AE%E7%9A%84%E4%BC%A0%E9%80%92/1.htm">Bundle对象数据的传递</a> <div>学习意图将数据传递给目标活动; 初学者需要好好研究的       1,将下面的代码添加到main.xml中    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http:/</div> </li> <li><a href="/article/1386.htm" title="oracle查询锁表解锁语句" target="_blank">oracle查询锁表解锁语句</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/object/1.htm">object</a><a class="tag" taget="_blank" href="/search/session/1.htm">session</a><a class="tag" taget="_blank" href="/search/kill/1.htm">kill</a> <div>一.查询锁定的表 如下语句,都可以查询锁定的表 语句一: select a.sid, a.serial#, p.spid, c.object_name, b.session_id, b.oracle_username, b.os_user_name from v$process p, v$s</div> </li> <li><a href="/article/1513.htm" title="mac osx 10.10 下安装 mysql 5.6 二进制文件[tar.gz]" target="_blank">mac osx 10.10 下安装 mysql 5.6 二进制文件[tar.gz]</a> <span class="text-muted">征客丶</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/osx/1.htm">osx</a> <div>场景:在 mac osx 10.10 下安装 mysql 5.6 的二进制文件。 环境:mac osx 10.10、mysql 5.6 的二进制文件 步骤:[所有目录请从根“/”目录开始取,以免层级弄错导致找不到目录] 1、下载 mysql 5.6 的二进制文件,下载目录下面称之为 mysql5.6SourceDir; 下载地址:http://dev.mysql.com/downl</div> </li> <li><a href="/article/1640.htm" title="分布式系统与框架" target="_blank">分布式系统与框架</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a> <div>RPC框架 Dubbo 什么是Dubbo   Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其核心部分包含:    远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。    集群容错: 提供基于接</div> </li> <li><a href="/article/1767.htm" title="那些令人蛋痛的专业术语" target="_blank">那些令人蛋痛的专业术语</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/SSO/1.htm">SSO</a><a class="tag" taget="_blank" href="/search/IOC/1.htm">IOC</a> <div> spring 【控制反转(IOC)/依赖注入(DI)】: 由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。 简单的说:对象的创建又容器(比如spring容器)来执行,程序里不直接new对象。 Web 【单点登录(SSO)】:SSO的定义是在多个应用系统中,用户</div> </li> <li><a href="/article/1894.htm" title="《给大忙人看的java8》摘抄" target="_blank">《给大忙人看的java8》摘抄</a> <span class="text-muted">braveCS</span> <a class="tag" taget="_blank" href="/search/java8/1.htm">java8</a> <div>函数式接口:只包含一个抽象方法的接口 lambda表达式:是一段可以传递的代码       你最好将一个lambda表达式想象成一个函数,而不是一个对象,并记住它可以被转换为一个函数式接口。 事实上,函数式接口的转换是你在Java中使用lambda表达式能做的唯一一件事。   方法引用:又是要传递给其他代码的操作已经有实现的方法了,这时可以使</div> </li> <li><a href="/article/2021.htm" title="编程之美-计算字符串的相似度" target="_blank">编程之美-计算字符串的相似度</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BE%8E/1.htm">编程之美</a> <div> public class StringDistance { /** * 编程之美 计算字符串的相似度 * 我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为: * 1.修改一个字符(如把“a”替换为“b”); * 2.增加一个字符(如把“abdd”变为“aebdd”); * 3.删除一个字符(如把“travelling”变为“trav</div> </li> <li><a href="/article/2148.htm" title="上传、下载压缩图片" target="_blank">上传、下载压缩图片</a> <span class="text-muted">chengxuyuancsdn</span> <a class="tag" taget="_blank" href="/search/%E4%B8%8B%E8%BD%BD/1.htm">下载</a> <div>/** * * @param uploadImage --本地路径(tomacat路径) * @param serverDir --服务器路径 * @param imageType --文件或图片类型 * 此方法可以上传文件或图片.txt,.jpg,.gif等 */ public void upload(String uploadImage,Str</div> </li> <li><a href="/article/2275.htm" title="bellman-ford(贝尔曼-福特)算法" target="_blank">bellman-ford(贝尔曼-福特)算法</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/F%23/1.htm">F#</a> <div>Bellman-Ford算法(根据发明者 Richard Bellman 和 Lester Ford 命名)是求解单源最短路径问题的一种算法。单源点的最短路径问题是指:给定一个加权有向图G和源点s,对于图G中的任意一点v,求从s到v的最短路径。有时候这种算法也被称为 Moore-Bellman-Ford 算法,因为 Edward F. Moore zu 也为这个算法的发展做出了贡献。 与迪科</div> </li> <li><a href="/article/2402.htm" title="oracle ASM中ASM_POWER_LIMIT参数" target="_blank">oracle ASM中ASM_POWER_LIMIT参数</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/ASM/1.htm">ASM</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/ASM_POWER_LIMIT/1.htm">ASM_POWER_LIMIT</a><a class="tag" taget="_blank" href="/search/%E7%A3%81%E7%9B%98%E5%B9%B3%E8%A1%A1/1.htm">磁盘平衡</a> <div>ASM_POWER_LIMIT 该初始化参数用于指定ASM例程平衡磁盘所用的最大权值,其数值范围为0~11,默认值为1。该初始化参数是动态参数,可以使用ALTER  SESSION或ALTER  SYSTEM命令进行修改。示例如下: SQL>ALTER  SESSION  SET   Asm_power_limit=2; </div> </li> <li><a href="/article/2529.htm" title="高级排序:快速排序" target="_blank">高级排序:快速排序</a> <span class="text-muted">dieslrae</span> <a class="tag" taget="_blank" href="/search/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F/1.htm">快速排序</a> <div> public void quickSort(int[] array){ this.quickSort(array, 0, array.length - 1); } public void quickSort(int[] array,int left,int right){ if(right - left <= 0</div> </li> <li><a href="/article/2656.htm" title="C语言学习六指针_何谓变量的地址 一个指针变量到底占几个字节" target="_blank">C语言学习六指针_何谓变量的地址 一个指针变量到底占几个字节</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/C%E8%AF%AD%E8%A8%80/1.htm">C语言</a> <div># include <stdio.h> int main(void) { /* 1、一个变量的地址只用第一个字节表示 2、虽然他只使用了第一个字节表示,但是他本身指针变量类型就可以确定出他指向的指针变量占几个字节了 3、他都只存了第一个字节地址,为什么只需要存一个字节的地址,却占了4个字节,虽然只有一个字节, 但是这些字节比较多,所以编号就比较大, </div> </li> <li><a href="/article/2783.htm" title="phpize使用方法" target="_blank">phpize使用方法</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a> <div>phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块,下面介绍一个它的使用方法,需要的朋友可以参考下 安装(fastcgi模式)的时候,常常有这样一句命令: 代码如下: /usr/local/webserver/php/bin/phpize   一、phpize是干嘛的? phpize是什么? phpize是用来扩展php扩展模块的,通过phpi</div> </li> <li><a href="/article/2910.htm" title="Java虚拟机学习 - 对象引用强度" target="_blank">Java虚拟机学习 - 对象引用强度</a> <span class="text-muted">shuizhaosi888</span> <a class="tag" taget="_blank" href="/search/JAVA%E8%99%9A%E6%8B%9F%E6%9C%BA/1.htm">JAVA虚拟机</a> <div> 本文原文链接:http://blog.csdn.net/java2000_wl/article/details/8090276 转载请注明出处! 无论是通过计数算法判断对象的引用数量,还是通过根搜索算法判断对象引用链是否可达,判定对象是否存活都与“引用”相关。 引用主要分为 :强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Wea</div> </li> <li><a href="/article/3037.htm" title=".NET Framework 3.5 Service Pack 1(完整软件包)下载地址" target="_blank">.NET Framework 3.5 Service Pack 1(完整软件包)下载地址</a> <span class="text-muted">happyqing</span> <a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/%E4%B8%8B%E8%BD%BD/1.htm">下载</a><a class="tag" taget="_blank" href="/search/framework/1.htm">framework</a> <div>  Microsoft .NET Framework 3.5 Service Pack 1(完整软件包)  http://www.microsoft.com/zh-cn/download/details.aspx?id=25150 Microsoft .NET Framework 3.5 Service Pack 1 是一个累积更新,包含很多基于 .NET Framewo</div> </li> <li><a href="/article/3164.htm" title="JAVA定时器的使用" target="_blank">JAVA定时器的使用</a> <span class="text-muted">jingjing0907</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/timer/1.htm">timer</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a><a class="tag" taget="_blank" href="/search/%E5%AE%9A%E6%97%B6%E5%99%A8/1.htm">定时器</a> <div>1、在应用开发中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。 对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。 privatejava.util.Timer timer; timer = newTimer(true); timer.schedule( newjava.util.TimerTask() { public void run() </div> </li> <li><a href="/article/3291.htm" title="Webbench" target="_blank">Webbench</a> <span class="text-muted">流浪鱼</span> <a class="tag" taget="_blank" href="/search/webbench/1.htm">webbench</a> <div>首页下载地址 http://home.tiscali.cz/~cz210552/webbench.html Webbench是知名的网站压力测试工具,它是由Lionbridge公司(http://www.lionbridge.com)开发。 Webbench能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。webbench的标准测试可以向我们展示服务器的两项内容:每秒钟相</div> </li> <li><a href="/article/3418.htm" title="第11章 动画效果(中)" target="_blank">第11章 动画效果(中)</a> <span class="text-muted">onestopweb</span> <a class="tag" taget="_blank" href="/search/%E5%8A%A8%E7%94%BB/1.htm">动画</a> <div>index.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/</div> </li> <li><a href="/article/3545.htm" title="windows下制作bat启动脚本." target="_blank">windows下制作bat启动脚本.</a> <span class="text-muted">sanyecao2314</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/cmd/1.htm">cmd</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a><a class="tag" taget="_blank" href="/search/bat/1.htm">bat</a> <div>java -classpath C:\dwjj\commons-dbcp.jar;C:\dwjj\commons-pool.jar;C:\dwjj\log4j-1.2.16.jar;C:\dwjj\poi-3.9-20121203.jar;C:\dwjj\sqljdbc4.jar;C:\dwjj\voucherimp.jar com.citsamex.core.startup.MainStart </div> </li> <li><a href="/article/3672.htm" title="Java进行RSA加解密的例子" target="_blank">Java进行RSA加解密的例子</a> <span class="text-muted">tomcat_oracle</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>加密是保证数据安全的手段之一。加密是将纯文本数据转换为难以理解的密文;解密是将密文转换回纯文本。   数据的加解密属于密码学的范畴。通常,加密和解密都需要使用一些秘密信息,这些秘密信息叫做密钥,将纯文本转为密文或者转回的时候都要用到这些密钥。   对称加密指的是发送者和接收者共用同一个密钥的加解密方法。   非对称加密(又称公钥加密)指的是需要一个私有密钥一个公开密钥,两个不同的密钥的</div> </li> <li><a href="/article/3799.htm" title="Android_ViewStub" target="_blank">Android_ViewStub</a> <span class="text-muted">阿尔萨斯</span> <a class="tag" taget="_blank" href="/search/ViewStub/1.htm">ViewStub</a> <div>public final class ViewStub extends View java.lang.Object android.view.View android.view.ViewStub 类摘要: ViewStub 是一个隐藏的,不占用内存空间的视图对象,它可以在运行时延迟加载布局资源文件。当 ViewSt</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>