IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 实现将递归遍历文件,并将文件路径存储到map中且可以进行不同形式的查询,增加,删除等操作 -> 正文阅读

[C++知识库]实现将递归遍历文件,并将文件路径存储到map中且可以进行不同形式的查询,增加,删除等操作

目录

1.MD5值获取

2.文件递归遍历操作

3.文件的不同查询操作

4.mian函数就可以自己进行来写了


在进行文件递归查询的时候要注意权限以及重定向问题,否则无法将C盘下面的所有文件查询到。在我的每月记录里面记录了以上的一些问题,还有注册服务问题,在这里有兴趣可以去瞅瞅,我附上链接:

解决问题icon-default.png?t=M276https://blog.csdn.net/qq_43287694/article/details/123233267

1.MD5值获取

MD5值这里就不多说了,这个内容网上的知识特别多,这个代码是我在网上找到可以使用的,我就直接贴代码:

//MD5.h   
#ifndef BZF_MD5_H  
#define BZF_MD5_H  

#include <string>  
#include <iostream>  


// a small class for calculating MD5 hashes of strings or byte arrays  
// it is not meant to be fast or secure  
//  
// usage: 1) feed it blocks of uchars with update()  
//      2) finalize()  
//      3) get hexdigest() string  
//      or  
//      MD5(std::string).hexdigest()  
//  
// assumes that char is 8 bit and int is 32 bit  
class MD5
{
public:
    typedef unsigned int size_type; // must be 32bit  

    MD5();
    MD5(const std::string& text);
    void update(const unsigned char* buf, size_type length);
    void update(const char* buf, size_type length);
    MD5& finalize();
    std::string hexdigest() const;
    friend std::ostream& operator<<(std::ostream&, MD5 md5);

private:
    void init();
    typedef unsigned char uint1; //  8bit  
    typedef unsigned int uint4;  // 32bit  
    enum { blocksize = 64 }; // VC6 won't eat a const static int here  

    void transform(const uint1 block[blocksize]);
    static void decode(uint4 output[], const uint1 input[], size_type len);
    static void encode(uint1 output[], const uint4 input[], size_type len);

    bool finalized;
    uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk  
    uint4 count[2];   // 64bit counter for number of bits (lo, hi)  
    uint4 state[4];   // digest so far  
    uint1 digest[16]; // the result  

    // low level logic operations  
    static inline uint4 F(uint4 x, uint4 y, uint4 z);
    static inline uint4 G(uint4 x, uint4 y, uint4 z);
    static inline uint4 H(uint4 x, uint4 y, uint4 z);
    static inline uint4 I(uint4 x, uint4 y, uint4 z);
    static inline uint4 rotate_left(uint4 x, int n);
    static inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
    static inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
    static inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
    static inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};

std::string md5(const std::string str);

#endif  
//MD5.cpp  
/* MD5
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
for bzflag (http://www.bzflag.org)

based on:

md5.h and md5.c
reference implemantion of RFC 1321

Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.

License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.

License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.

RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.

These notices must be retained in any copies of any part of this
documentation and/or software.

*/

/* interface header */
#include "md5.h"  

/* system implementation headers */
#include <stdio.h>  


// Constants for MD5Transform routine.  
#define S11 7  
#define S12 12  
#define S13 17  
#define S14 22  
#define S21 5  
#define S22 9  
#define S23 14  
#define S24 20  
#define S31 4  
#define S32 11  
#define S33 16  
#define S34 23  
#define S41 6  
#define S42 10  
#define S43 15  
#define S44 21  

///  

// F, G, H and I are basic MD5 functions.  
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
    return x & y | ~x & z;
}

inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
    return x & z | y & ~z;
}

inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
    return x ^ y ^ z;
}

inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
    return y ^ (x | ~z);
}

// rotate_left rotates x left n bits.  
inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
    return (x << n) | (x >> (32 - n));
}

// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.  
// Rotation is separate from addition to prevent recomputation.  
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
    a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
}

inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
    a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
}

inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
    a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
}

inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
    a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
}

//  

// default ctor, just initailize  
MD5::MD5()
{
    init();
}

//  

// nifty shortcut ctor, compute MD5 for string and finalize it right away  
MD5::MD5(const std::string& text)
{
    init();
    update(text.c_str(), text.length());
    finalize();
}

//  

void MD5::init()
{
    finalized = false;

    count[0] = 0;
    count[1] = 0;

    // load magic initialization constants.  
    state[0] = 0x67452301;
    state[1] = 0xefcdab89;
    state[2] = 0x98badcfe;
    state[3] = 0x10325476;
}

//  

// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.  
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
{
    for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
        output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
        (((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
}

//  

// encodes input (uint4) into output (unsigned char). Assumes len is  
// a multiple of 4.  
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
{
    for (size_type i = 0, j = 0; j < len; i++, j += 4) {
        output[j] = input[i] & 0xff;
        output[j + 1] = (input[i] >> 8) & 0xff;
        output[j + 2] = (input[i] >> 16) & 0xff;
        output[j + 3] = (input[i] >> 24) & 0xff;
    }
}

//  

// apply MD5 algo on a block  
void MD5::transform(const uint1 block[blocksize])
{
    uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    decode(x, block, blocksize);

    /* Round 1 */
    FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
    FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
    FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
    FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
    FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
    FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
    FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
    FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
    FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
    FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

    /* Round 2 */
    GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
    GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
    GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
    GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
    GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
    GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
    GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

    /* Round 3 */
    HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
    HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
    HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
    HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
    HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
    HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
    HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */

    /* Round 4 */
    II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
    II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
    II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
    II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;

    // Zeroize sensitive information.  
    memset(x, 0, sizeof x);
}

//  

// MD5 block update operation. Continues an MD5 message-digest  
// operation, processing another message block  
void MD5::update(const unsigned char input[], size_type length)
{
    // compute number of bytes mod 64  
    size_type index = count[0] / 8 % blocksize;

    // Update number of bits  
    if ((count[0] += (length << 3)) < (length << 3))
        count[1]++;
    count[1] += (length >> 29);

    // number of bytes we need to fill in buffer  
    size_type firstpart = 64 - index;

    size_type i;

    // transform as many times as possible.  
    if (length >= firstpart)
    {
        // fill buffer first, transform  
        memcpy(&buffer[index], input, firstpart);
        transform(buffer);

        // transform chunks of blocksize (64 bytes)  
        for (i = firstpart; i + blocksize <= length; i += blocksize)
            transform(&input[i]);

        index = 0;
    }
    else
        i = 0;

    // buffer remaining input  
    memcpy(&buffer[index], &input[i], length - i);
}

//  

// for convenience provide a verson with signed char  
void MD5::update(const char input[], size_type length)
{
    update((const unsigned char*)input, length);
}

//  

// MD5 finalization. Ends an MD5 message-digest operation, writing the  
// the message digest and zeroizing the context.  
MD5& MD5::finalize()
{
    static unsigned char padding[64] = {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };

    if (!finalized) {
        // Save number of bits  
        unsigned char bits[8];
        encode(bits, count, 8);

        // pad out to 56 mod 64.  
        size_type index = count[0] / 8 % 64;
        size_type padLen = (index < 56) ? (56 - index) : (120 - index);
        update(padding, padLen);

        // Append length (before padding)  
        update(bits, 8);

        // Store state in digest  
        encode(digest, state, 16);

        // Zeroize sensitive information.  
        memset(buffer, 0, sizeof buffer);
        memset(count, 0, sizeof count);

        finalized = true;
    }

    return *this;
}

//  

// return hex representation of digest as string  
std::string MD5::hexdigest() const
{
    if (!finalized)
        return "";

    char buf[33];
    for (int i = 0; i < 16; i++)
        sprintf(buf + i * 2, "%02x", digest[i]);
    buf[32] = 0;

    return std::string(buf);
}


std::ostream& operator<<(std::ostream& out, MD5 md5)
{
    return out << md5.hexdigest();
}

//  

std::string md5(const std::string str)
{
    MD5 md5 = MD5(str);

    return md5.hexdigest();
}

2.文件递归遍历操作

//filepath.h
#pragma once
#include <stdio.h>
#include <windows.h>
#include<string.h>
#include<iostream>
#include<map>
#include<sstream>
#pragma warning(disable:4996)
using namespace std;
int SearchFile(string path, int* num, map<string, string>* _path);
void find_path(map<string, string> _path, string path);
void find_name(map<string, string> _path, string path);
void _find_md5(map<string, string> _path, string md5_file);
#pragma comment(lib, "winmm.lib ")

#include"filepath.h"
#include"md5.h"

//搜索文件函数
int SearchFile(string path ,int* num, map<string,string>* _path)
{
    string buffer = "";
    buffer = path + "\\*.*";
    WIN32_FIND_DATA pNextInfo;//保存文件信息
    //PVOID OldValue;
    HANDLE hFile = 0;
    PVOID OldValue = NULL;
    //临时解除重定向
    if (Wow64DisableWow64FsRedirection(&OldValue)) {
        //查找指定路径
        hFile = FindFirstFileA(buffer.c_str(), &pNextInfo);
        if (FALSE == Wow64RevertWow64FsRedirection(OldValue))
            return NULL;
    }
    hFile = FindFirstFile(buffer.c_str(), &pNextInfo);
    
    if (hFile != INVALID_HANDLE_VALUE)//
    {
        do
        {
            if (pNextInfo.cFileName[0] == '.' || pNextInfo.cFileName[0] == '..')//过滤.和..
                continue;
            //dwFileAttributes值是可以一位或多位的,不好直接使用"=="来判断
            if (pNextInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)//判断是否为文件夹
            {
                buffer = path + "\\" + pNextInfo.cFileName;//将文件夹追加到目录,成为下一级要搜索目录
                SearchFile(buffer,num , _path);//递归
            }
            ULARGE_INTEGER ulFileSize;
            //求得文件的大小
            ulFileSize.LowPart = GetCompressedFileSize((pNextInfo.cFileName), &(pNextInfo.nFileSizeHigh));
            __int64 creattime = *(__int64*)&(pNextInfo.ftCreationTime);//将FILETIME转换成
            __int64 writetime = *(__int64*)&(pNextInfo.ftLastWriteTime);
            //将文件绝对路径,创建时间,修改时间,文件大小拼接
            string str = path + "\\" + pNextInfo.cFileName + to_string(creattime) + to_string(writetime) + to_string(ulFileSize.LowPart);
            //遍历结束一个文件路径进行++
            //将文件的属性全部存到map中
           // string _md5 = md5(str);
           // buffer = path + "\\" + pNextInfo.cFileName;
           // (*num)++;
           // (*_path).insert(pair<string, string>(buffer, _md5));//存储到map中
            //求出exe,dll文件
            string str_ed = pNextInfo.cFileName;
            int size = str_ed.size();
            if (size > 3) {
                string str_1 = str_ed.substr(size - 3);
                //|| strcmp(str_1.c_str(), "exe") == 0
                //|| strcmp(str_1.c_str(), "exe") == 0 || strcmp(str_1.c_str(), "bat") == 0
                if (stricmp(str_1.c_str(), "dll") == 0 ) {
                    string _md5 = md5(str);
                    buffer = path + "\\" + pNextInfo.cFileName;
                    (*num)++;
                    (*_path).insert(pair<string, string>(buffer , _md5));//存储到map中
                }
            }
            
        } while (FindNextFile(hFile, &pNextInfo));//遍历文件
    }
    FindClose(hFile);
    return 0;
}

3.文件的不同查询操作

void find_path(map<string,string> _path,string path) {
    //按文件绝对路径查询
    map<string, string>::iterator it;
    it = _path.find(path);
    if (it != _path.end())
        cout << "find the file!!"<<":" << path << endl;
    else
        cout << "not find!!" << endl;
}


void find_name(map<string, string> _path, string path) {
    //按文件名查询
    map<string, string>::iterator it;
    int num = 0;
    it = _path.begin();
    while (it != _path.end()) {//当没有遍历到最后
        string str_ed = it->first;//先得到文件路径
        string file_name = str_ed.substr(str_ed.rfind("\\")+1);
        if(strcmp(file_name.c_str(),path.c_str()) ==0){
            cout << path << " : " << it->first << endl;
            num++;
        }
        it++;
    }
    if (num > 0)
        cout << "find the file!!!" << endl;
    else
        cout << "not find" << endl;
    return;
}
void _find_md5(map<string, string> _path, string md5_file) {
    map<string, string>::iterator it;
    int num = 0;
    it = _path.begin();
    while (it != _path.end()) {//当没有遍历到最后
        if (strcmp((it->second).c_str(),md5_file.c_str()) == 0) {
            cout<< " find the file : " << it->first << endl;
            return;
        }
        it++;
    }
    cout << "not find!!" << endl;
}


4.mian函数就可以自己进行来写了

#include"filepath.h"

int main(void)
{
    cout << "请输入需要扫描的的文件路径:" << endl;
    char str[MAX_PATH] = "C:\\Windows\\System32";
   // cin >> str;
    map<string, string> _path;
    int num = 0;
    cout << "存储文件路径到map中......" << endl;
    SearchFile(str, &num, &(_path));//存储文件路径到map中
    cout << "all文件的个数为:" << num << endl;
   //DWORD dwStart = GetTickCount();
   //find_path(_path,"");
   //DWORD dwEnd = GetTickCount();
   //cout << dwEnd - dwStart << endl;
   //map<string, string>::iterator it;
   //it = _path.begin();
   //while (it != _path.end()) {
   //    cout << it->first << ":" << it->second << endl;
   //    Sleep(100);
   //    it++;
   //}
    
    // cout << "按照文件名进行查询:" << endl;
     //find_name(_path, find_nap);//按照文件名进行查询
     //out << "按照文件md5值进行查询:" << endl;
     //find_md5(_path, find_md5);//按照md5值进行查找


    return 0;
}

??在这里一些细节问题在之前的每月记录问题里面已经解决,等有时间将之前的所有问题在这里在进行整理一遍,就先这样了,嘿嘿。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:08:08  更:2022-04-01 23:09:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:45:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码