如何使用C ++中的文件流将正确无符号的__int8数组读取和写入二进制文件

时间:2016-08-05 11:45:02

标签: c++ filestream

我正在使用生成器来创建无符号__int8'的随机序列,然后使用ofstream.write()使用此方法将它们写入文件;

void CDataGenerator::GenerateRandom(std::string outputFileName, int length, bool UseEntireRange, int max) {
    std::ofstream file;
    file.open(outputFileName, std::ifstream::out | std::ifstream::binary);
    int count = 0;
    unsigned __int8* buf = new unsigned __int8[length];
    while (count < length-1) {
        int number = 0;
        if (UseEntireRange)
            number = rand();
        else {
            int rnd = rand();
            number = (int)((double)rnd / RAND_MAX * max);
        }
        int capacity = 0;
        if (number == 0)
            capacity = 1;
        else
            capacity = (int)(floor(log10(number)) + 1);
        for (int i = 0; i < capacity; ++i) {
            if (count >= length - 2)
                break;
            buf[count] = ((unsigned __int8)(number / (int)pow(10, capacity - i - 1)));
            number %= (int)pow(10, capacity - i - 1);
            ++count;            
        }       
        ++count;
        buf[count] = BCD_SEPARATOR;
    }
    file.write((__int8*)&buf[0], length);
    delete[] buf;
    file.close();   
}

const static unsigned __int8 BCD_SEPARATOR = 0xff;

然后我尝试用以下方法读取文件

unsigned __int8* CModel::GetRawData(std::string inputFileName, int &length) {
    std::ifstream file(inputFileName, std::ifstream::ate | std::ifstream::binary);
    length = file.tellg();
    file.close();
    file.open(inputFileName, std::ifstream::in | std::ifstream::binary);
    unsigned __int8* result = new unsigned __int8[length];
    file.read((__int8*)&result[0], length);
    file.close();
    return result;
}

我的测试生成器创建了这样的序列 0x0 0xFF 0x5 0x6 0xFF 0x1 0x9 0xFF 0x8 0xFF 但从阅读流我得到 0x0 0xCD 0x5 0x6 0xCD 0x1 0x9 0xCD 0x8 0xCD 序列。 很明显,所有0xff都替换为0xcd。是否与(__int8 *)演员表相关联,如何解决?

1 个答案:

答案 0 :(得分:3)

了解Visual Studio使用的CRT调试堆(我只是假设你使用的是Visual Studio),这是一个很好的猜测,0xCD值来自未初始化的堆内存。那么问题就变成了:你为什么在输出中看到这个?要找出原因,您可以使用调试器/读取代码简单地逐步执行GenerateRandom函数。

从中可以看出问题出在哪里:

for (int i = 0; i < capacity; ++i) {
    if (count >= length - 2)
        break;
    buf[count] = ((unsigned __int8)(number / (int)pow(10, capacity - i - 1)));
    number %= (int)pow(10, capacity - i - 1);
    ++count; //Increment count ONCE
}

++count; //Increment count a SECOND time
buf[count] = BCD_SEPARATOR;

问题在于,当程序离开此处显示的for循环时,count已经增加了一次,所以你的“count”已经在缓冲区中的下一个未初始化的__int8。然后在将BCD_SEPARATOR写入缓冲区中的“count”位置之前再次递增“count”。这导致程序跳过您实际需要BCD_SEPARATOR的位置。

接下来的问题就是,因为在将BCD_SEPARATOR写入缓冲区之后不会增加“count”,下次进入上面显示的for循环时,会立即覆盖BCD_SEPARATOR。

问题的解决方案可能是简单地交换周围的东西:

buf[count] = BCD_SEPARATOR;
++count;