我用C ++编写的文件中包含更多字符

时间:2018-11-01 11:03:52

标签: c++ ifstream ofstream

我正在使用C ++中的ofstream写入文件。每行必须有一个相对时间,一个逗号和我要写的值。值是std::vector<unsigned char>,以便写入所需的任何值并以其他方法回读。我的测试是写3个值。即使我使用\0\n,第一个值最后也会连接到一个奇怪的字节。但是其他两个值都可以。

这是输出文件:

0,BAC�
1000,DEF
2000,GHI

第二个问题是当我读取值时。我不知道如何动态地设置一个数组,使其仅读取写在该行上的值,并与我之前编写的上一个char向量进行比较。

头文件:

class SensorRecorder {
private:
    std::ofstream outFile;
    std::ifstream infile;
    std::string path;
    long duration = -1;
public:
    const std::string OUTPUT_DIR = "out";
    const std::string EXTENSION = ".out";
    const char SEPARATOR = ',';
    SensorRecorder(const char *classNameType);
    ~SensorRecorder();
    int write(std::vector<unsigned char> value);
    std::vector<unsigned char> read(long relativeTime);
    void close();
    std::string getFileName();
};

实施:

#include "utils/SensorRecorder.h"
#include "utils/DateTools.h"
#include <cstring>
#include <iostream>
#include <boost/filesystem.hpp>

SensorRecorder::SensorRecorder(const char *classNameType) {
    boost::filesystem::path full_path(boost::filesystem::current_path());
    full_path.append(OUTPUT_DIR, boost::filesystem::path::codecvt());
    if (boost::filesystem::create_directory(full_path)) {
        std::cout << "Directory Created: " << full_path << std::endl;
    }
    std::string fileName = classNameType + ((std::string) "-") + DateTools::getPlainDate() + EXTENSION;
    full_path.append(fileName, boost::filesystem::path::codecvt());
    path = full_path.c_str();
    outFile.open(path);
}
int SensorRecorder::write(std::vector<unsigned char> value) {
    if (outFile.is_open()) {
        char *data = reinterpret_cast<char *>(value.data());
        auto now = std::chrono::system_clock::now();
        auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
        auto value = now_ms.time_since_epoch();

        if (duration == -1) {
            duration = 0;
        } else {
            duration = value.count() - duration;
        }
        // write in the file
        outFile << duration << SEPARATOR << data << '\0' << '\n';
        duration = value.count();
    } else {
        return 0;
    }
    return 1;
}
std::vector<unsigned char> SensorRecorder::read(long relativeTime) {
    infile.open(path);
    if (infile.is_open()) {
        std::cout << "Reading from the file" << std::endl;
        long duration;
        char comma;
        unsigned char data[300];

        while (infile >> duration >> comma >> data) {
            std::cout << "duration: " << duration << std::endl;
            std::cout << "data: " << data << std::endl;
            if (duration == relativeTime) {
                std::cout << "INSIDE " << std::endl;
                infile.close();

                // cast the value
                std::vector<unsigned char> outputValues(data, data + sizeof(data));
                return outputValues;
            }
        }
        infile.close();
    }
    return std::vector<unsigned char>();
}

我的测试:

TEST_F(SensorRecorderTest, TestWriteOnFile) {
    std::vector<unsigned char> inputValues01 = {'B', 'A', 'C'};
    std::vector<unsigned char> inputValues02 = {'D', 'E', 'F'};
    std::vector<unsigned char> inputValues03 = {'G', 'H', 'I'};
    mySensorRecorder = new SensorRecorder("SensorRecorderTest");

    // write on the file
    int ret = mySensorRecorder->write(inputValues01);
    ASSERT_EQ(ret, 1);

    std::this_thread::sleep_for(std::chrono::seconds(1));
    ret = mySensorRecorder->write(inputValues02);
    ASSERT_EQ(ret, 1);

    std::this_thread::sleep_for(std::chrono::seconds(2));
    ret = mySensorRecorder->write(inputValues03);
    ASSERT_EQ(ret, 1);

    mySensorRecorder->close();

    // read from the file
    std::vector<unsigned char> outputValues01 = mySensorRecorder->read(0);
    ASSERT_EQ(inputValues01, outputValues01);
}

错误:

Expected equality of these values:
  inputValues01
    Which is: { 'B' (66, 0x42), 'A' (65, 0x41), 'C' (67, 0x43) }
  outputValues01
    Which is: { 'B' (66, 0x42), 'A' (65, 0x41), 'C' (67, 0x43), '\xE4' (228), '\x16' (22), '\x7F' (127), '\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', ... }

2 个答案:

答案 0 :(得分:4)

问题是以null结尾的字符串。

char *data = reinterpret_cast<char *>(value.data());
outFile << duration << SEPARATOR << data << '\0' << '\n';

一个char *的契约本身以\0结尾(要知道要写多少个字符,strlen会查找第一个可用的\0)。就您而言,事实并非如此。您应该使用真实的字符串,或者至少使用:

outFile << duration << SEPARATOR << std::string(data, data+3) << '\n';

在此指令上添加\0不会使字符串被魔术终止。您必须保持大小。

(read具有相同的缺陷)。

答案 1 :(得分:0)

我更改了write方法,不将向量转换为char数组,之后我只是push_back \0字符。

int SensorRecorder::write(std::vector<unsigned char> value) {
    if (outFile.is_open()) {
        auto now = std::chrono::system_clock::now();
        auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
        auto v = now_ms.time_since_epoch();

        if (duration == -1) {
            duration = 0;
        } else {
            duration = v.count() - duration;
        }
        // write in the file
        value.push_back('\0');

        std::cout << value.size() << " " << value.data() << std::endl;
        outFile << duration << SEPARATOR << value.data() << '\n';

        // evaluate duration time to the next write
        duration = v.count();
    } else {
        std::cerr << "error writing..." << std::endl;
        return 0;
    }
    return 1;
}