1. 关键词

C++ 文件系统操作 读取纯文本文件 写入纯文本文件 跨平台

2. fileutil.h


#pragma once

#include <string>
#include <cstdio>
#include <cstdint>
#include "filetype.h"
#include "filepath.h"

namespace cutl
{

    /**
     * @brief The file guard class to manage the FILE pointer automatically.
     * file_guard object can close the FILE pointer automatically when his scope is exit.
     */
    class file_guard
    {
    public:
        /**
         * @brief Construct a new file guard object
         *
         * @param file the pointer of the FILE object
         */
        explicit file_guard(FILE *file);

        /**
         * @brief Destroy the file guard object
         *
         */
        ~file_guard();

        /**
         * @brief Get the FILE pointer.
         *
         * @return FILE*
         */
        FILE *getfd() const;

    private:
        FILE *file_;
    };

    /**
     * @brief Read the text content of a file.
     *
     * @param path the filepath of the file to be read
     * @param max_read_size the maximum size to be read, default is 4096 bytes.
     *
     * If the file size is larger than max_read_size, only the first max_read_size bytes will be read. otherwise, the whole file will be read.
     *
     * @return text content of the file
     */
    std::string readtext(const filepath &path, uint64_t max_read_size = 4096);

    /**
     * @brief Write the text content to a file.
     *
     * @param path the filepath of the file to be written
     * @param content text content to be written to the file
     * @return true if the content is written successfully, false otherwise.
     */
    bool writetext(const filepath &path, const std::string &content);

} // namespace cutl
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.

3. fileutil.cpp

#include <cstdio>
#include <map>
#include <iostream>
#include <cstring>
#include <sys/stat.h>
#include "fileutil.h"
#include "inner/logger.h"
#include "inner/filesystem.h"
#include "strutil.h"

namespace cutl
{
    file_guard::file_guard(FILE *file)
        : file_(file)
    {
    }

    file_guard::~file_guard()
    {
        if (file_)
        {
            // CUTL_DEBUG("close file");
            int ret = fclose(file_);
            if (ret != 0)
            {
                CUTL_ERROR("fail to close file, ret" + std::to_string(ret));
            }
            file_ = nullptr;
        }
        // ROBOLOG_DCHECK(file_ == nullptr);
    }

    FILE *file_guard::getfd() const
    {
        return file_;
    }

    std::string readtext(const filepath &path, uint64_t max_read_size)
    {
        file_guard fg(fopen(path.str().c_str(), "r"));
        if (fg.getfd() == nullptr)
        {
            CUTL_ERROR("open file failed for " + path.str());
            return "";
        }

        // 从文件系统的文档信息里读取文件大小,性能更高
        auto data_len = filesize(path, true);
        // 公国文件操作的方式和获取文件大小
        // fseek(fg.getfd(), 0, SEEK_END);
        // size_t data_len = static_cast<size_t>(ftell(fg.getfd()));
        // rewind(fg.getfd());
        CUTL_DEBUG("file size: " + std::to_string(data_len) + ", file: " + path.str());

        // get read size
        if (data_len > max_read_size)
        {
            data_len = max_read_size;
            CUTL_WARN("file size is large than " + std::to_string(max_read_size) + ", file:" + path.str());
        }

        char *buffer = new char[data_len + 1];
        if (buffer == nullptr)
        {
            CUTL_ERROR("buffer alloc failed, data_len:" + std::to_string(data_len));
            return "";
        }
        size_t read_len = static_cast<size_t>(fread(buffer, 1, data_len, fg.getfd()));
        if (read_len < data_len)
        {
            CUTL_ERROR("read file failed, only read " + std::to_string(read_len) + " bytes for " + path.str());
        }

        buffer[read_len] = '\0';
        auto text = std::string(buffer);
        delete[] buffer;

        return text;
    }

    // https://en.cppreference.com/w/cpp/header/cstdio
    bool writetext(const filepath &path, const std::string &content)
    {
        // std::lock_guard
        file_guard fg(fopen(path.str().c_str(), "w"));
        if (fg.getfd() == nullptr)
        {
            CUTL_ERROR("open file failed for " + path.str() + ", error: " + strerror(errno));
            return false;
        }

        size_t written_size = fwrite(content.c_str(), 1, content.length(), fg.getfd());
        if (written_size != content.length())
        {
            CUTL_ERROR("written size is not equal to content size for " + path.str());
            return false;
        }

        int ret = fflush(fg.getfd());
        if (0 != ret)
        {
            CUTL_ERROR("fail to flush file:" + path.str());
            return false;
        }

        if (!file_sync(fg.getfd()))
        {
            CUTL_ERROR("file_sync failed for " + path.str());
            return false;
        }

        return true;
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.

4. 源码地址

更多详细代码,请查看本人写的C++ 通用工具库:  common_util, 本项目已开源,代码简洁,且有详细的文档和Demo。


【SunLogging】

C++文件系统操作3 - 跨平台实现读取|写入纯文本文件_开发工具

扫码二维码,关注微信公众号,阅读更多精彩内容