美文网首页
使用C++17 标准库处理文件系统文件

使用C++17 标准库处理文件系统文件

作者: FredricZhu | 来源:发表于2021-06-13 06:22 被阅读0次

C++ 17 std::filesystem库还是挺顺滑的,使用前需要注意把Visual Studio的默认Cpp标准设置为 C++17,如图所示。


image.png

否则自动提示会比较难受。

这个库需要注意的一点是,std::filesystem::path类重载了类型转换运算符
operator string_type() const,
这个意思就是,凡是需要传std::filesystem::path的地方,都可以直接传 std::string,标准库会帮你处理这一切的。

程序代码如下,
CMakeList.txt


cmake_minimum_required(VERSION 2.6)
project(chat_room)

add_definitions(-std=c++17)


find_package(Boost REQUIRED COMPONENTS
    system
    filesystem
    serialization
    program_options
    thread
    )

include_directories(${Boost_INCLUDE_DIRS})

file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
foreach( sourcefile ${APP_SOURCES} )
        file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile})
    if( "${filename}" STREQUAL "main.cpp")
        string(REPLACE ".cpp" "" file ${filename})
        add_executable(${file}  ${APP_SOURCES})
        target_link_libraries(${file} ${Boost_LIBRARIES})
        target_link_libraries(${file} pthread)
    endif()
endforeach( sourcefile ${APP_SOURCES})

main.cpp

#include "f_copy.h"
#include <filesystem>
#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char* argv[]) {
    std::filesystem::path cur_path = std::filesystem::current_path().parent_path();
    std::filesystem::path textSrcF {cur_path};
    std::filesystem::path textDstF {cur_path};
    textSrcF /= "main.cpp";
    textDstF /= "dst.cpp";
    TextFileCopy(textSrcF, textDstF);

    std::filesystem::path binSrcF {R"(/Users/aabjfzhu/spark-snowflake_2.11-2.8.5-spark_2.4.jar)"};
    std::filesystem::path binDstF {cur_path};
    binDstF /= "spark-snowflake.jar";
    BinaryFileCopy(binSrcF, binDstF);
    return 0;
}

f_copy.h

#ifndef _FREDRIC_F_COPY_H_
#define _FREDRIC_F_COPY_H_

#include <string>

void TextFileCopy(const std::string& srcF, const std::string& dstF); 
void BinaryFileCopy(const std::string& srcF, const std::string& dstF);

#endif

f_copy.cpp

#include "f_copy.h"

#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>

void TextFileCopy(const std::string& srcF, const std::string& dstF) {
    std::ifstream input{srcF};
    if (!input) {
        std::cout << "Source File not found" << std::endl;
        return;
    }

    std::filesystem::path destPath{dstF};
    if (std::filesystem::exists(destPath)) {
        std::cout << "File already exists, will override the exist file: "
                  << dstF << std::endl;
    }

    std::ofstream output{dstF};
    if (!output) {
        std::cout << "Could not open the dest file" << std::endl;
        return;
    }

    std::string line;
    while (std::getline(input, line)) {
        output << line << std::endl;
    }

    input.close();
    output.close();
}

void BinaryFileCopy(const std::string& srcF, const std::string& dstF) {
    std::ifstream input{srcF, std::ios::in | std::ios::binary};
    if (!input) {
        std::cout << "Could not open the source file" << std::endl;
        return;
    }

    if (std::filesystem::exists(dstF)) {
        std::cout << "File Already exists, will override the exists file: "
                  << dstF << std::endl;
    }

    std::ofstream output{dstF, std::ios::out | std::ios::binary};
    if (!output) {
        std::cout << "Could not open the destination file" << std::endl;
        return;
    }

    auto file_size = std::filesystem::file_size(srcF);
    const unsigned BufferSize = 512;
    char buffer[BufferSize]{};

    std::cout << "Copying: " << srcF;
    // 文件不到一个Buffer大
    if (file_size < BufferSize) {
        if (!input.read(buffer, file_size)) {
            throw std::runtime_error("Error occurred during read operation");
        }
        if (!output.write(buffer, file_size)) {
            throw std::runtime_error("Error occurred during write operation");
        }
    } else {
        // 大文件分为多个块来拷,并打印进度,进度乘10,是为了不让结果看起来都是0,一直不打印
        auto chunks = file_size / BufferSize;
        // 这里用int是因为 剩余大小小于 512,用int就可以了,不需要 std::size_t
        int remaining = file_size % BufferSize;
        int progress{}, oldProgress{};
        for (int i = 0; i < chunks; ++i) {
            if (!input.read(buffer, BufferSize)) {
                throw std::runtime_error(
                    "Error occurred during read operation");
            }

            if (!output.write(buffer, BufferSize)) {
                throw std::runtime_error(
                    "Error occurred during write operation");
            }

            // 先转浮点避免全零,再转整型便于比较
            // 类型转换建议使用 static_cast,不要直接强转
            // 因为static_cast会做类型检查
            progress = static_cast<int>((10 * static_cast<float>(i) / chunks));
            if (progress != oldProgress) {
                std::cout << '.';
            }
            oldProgress = progress;
        }

        // 下一次的读取将会小于 BufferSize
        // 但是buffer 里面可能还有上次读取的残存数据,
        // 所以需要使用memset清空
        // 比较底层的C操作,但是没办法,因为读写二进制必须按char* [byte]处理
        memset(buffer, '\0', BufferSize);

        if (remaining > 0) {
            if (!input.read(buffer, remaining)) {
                throw std::runtime_error(
                    "Error occurred during read operation");
            }
            if (!output.write(buffer, remaining)) {
                throw std::runtime_error(
                    "Error occurred during write operation");
            }
            std::cout << '.';
        }

        std::cout << "Done! " << std::endl;

        input.close();
        output.close();
    }
}

相关文章

  • 使用C++17标准库递归拷贝文件目录

    相关注意事项可以参考前一篇,《使用C++17 标准库处理文件系统文件》,直接上代码,CMakeLists.txt ...

  • 使用C++17 标准库处理文件系统文件

    C++ 17 std::filesystem库还是挺顺滑的,使用前需要注意把Visual Studio的默认Cpp...

  • 获取特定文件类型的关联图标

    文件系统相关类 要处理文件系统相关功能,一般直接使用Python 标准库中的函数,Qt 包含的以下几个类,只需要简...

  • Python基础-18目录与文件

    18.目录与文件 18.1 os和shutil     日常使用过程中,难免需要使用跟文件系统相关的标准库。在使用...

  • 熟悉Ubuntu环境

    1. 文件系统(filesystem) 文件系统层次结构标准 2. 软件包管理(apt) apt 使用事项: 使用...

  • 数据库优化一

    分公司CCDB数据库的优化 查看数据库归档空间的使用率,发现使用率过高 查看文件系统使用情况 根据文件系统使用情况...

  • python标准库pathlib常见操作

    pathlib—— 面向对象的文件系统路径它是python3.4新增的一个标准库,提供了不同操作系统下文件系统路径...

  • 使用C++标准库和nlohmann::json库将Zepplin

    本文使用的C++标准是C++17,使用了两个知识点, 一个是使用std::filesystem遍历文件目录 第二个...

  • webpack与脚本中

    安装软件 简单使用 编器对象 执行回调 监控文件 状态对象 多个编译 错误处理 文件系统可以指定文件系统 参考文献...

  • C++ Primer 笔记

    P19:包含头文件的语法包含来自标准库的头文件时,使用< >,而对于非标准库头文件,使用“ ”。如: P19:文件...

网友评论

      本文标题:使用C++17 标准库处理文件系统文件

      本文链接:https://www.haomeiwen.com/subject/axuweltx.html