数组和文件大小的数据类型

时间:2018-01-07 12:20:39

标签: c++ types fstream

我应该使用哪种数据类型来定义文件大小以在动态数组中存储文件数据?请考虑以下代码段:

#include <cstdint>
#include <string>
#include <fstream>

typedef uint64_t file_size_t;
typedef uint64_t file_pos_t;

int32_t ReadBytes(const std::wstring& file, file_pos_t pos, file_size_t numBytes, char*& readDataBuffer,
                file_size_t& bufferLen)
{
    using namespace std;

    bufferLen = 0;
    readDataBuffer = nullptr;
    ifstream is(file, ifstream::binary);
    if (!is)
        return -1;

    is.seekg(pos);
    if (!is)
    {
        is.close();
        return -2;
    }

    // Compiler warning in the following code line:
    readDataBuffer = new char[numBytes]();
    is.read(readDataBuffer, numBytes);
    bufferLen = is.gcount();
    is.close();

    return 0;
}

使用我已定义的类型,我的编译器(MS Visual C ++ 2017)在构建32位体系结构时发出警告:'initializing': conversion from 'file_size_t' to 'unsigned int', possible loss of data。我使用了uint64_t,因为它与tellgseekg等流功能兼容,可以接收或返回streamsize(在{{1}中定义为using streamoff = long long; })和等效类型。

如何定义删除此警告的iosfwd.h?使用file_size_t也会给出我在评论中指出的警告。

2 个答案:

答案 0 :(得分:2)

size_t是由sizeof()返回的传统类型,它指定某个对象的大小,可以是数组,也可以是单个对象。

您的数据来自文件这一事实无关紧要。它仍然以数组结尾,size_t是指定数组所谓大小的类型。

您的操作系统完全有可能允许创建大于size_t可以表示的值范围的文件。据推测,如果您希望将此类文件读入阵列,则由于操作系统的限制,您将无法读取其全部内容。您显然会有一些处理这种情况的方法,但在所有情况下,size_t始终为size_t

答案 1 :(得分:1)

您无法修复该警告,因为它会在您的代码中展示一个简单的缺陷。在32位系统上,您仍然可以使文件大小超过32位整数的范围。你必须处理这个案子。

因此,简而言之,以下步骤是必要的:

  1. 查找文件的大小。这将使用用于表示相应系统的文件大小的任何类型。
  2. 然后,检查您是否可能将其放入您的存储空间,即是否可以将其存储在size_t中。我建议使用简单的static_cast来转换价值,然后将简单的static_cast转换回原值,以确保它不会丢失任何信息。确保您不会超过有符号整数扩展语义!
  3. 然后,使用该大小分配相应的内存量。使用new是一种(不好)方式,但它主要起作用。
  4. 最后,从流中读取先前确定的数据量。请注意,文件的大小可以多于或少于您最初确定的大小,因为对它的写入可以同时发生。考虑当发生这种情况时你想做什么以及你想如何检测它。
  5. 顺便说一句:根据文件的大小以及你想用它做什么,最简单的方法就是内存映射它。特别是简单的只读访问既简单又快于复制数据。我不认为C ++附带了内置库,因此您可能必须在此处编写特定于操作系统的代码。使用现有代码作为后备,但这应该是相对简单的。