写入文件,在阅读时分离值

时间:2013-11-14 02:32:54

标签: c++ file-io

我正在努力教自己编程,而一个早期的主题是我无法解决问题。文件IO。

到目前为止,我知道我可以保存用逗号分隔的数据,以便以后成功读取该数据。做类似以下的事情:

int x[] = {1,22,333,4444,55555};
std::ofstream FileWriter;
std::string dataName = "One through Five";
for( int i = 0; i < 5; ++i)
{
    FileWriter << x[i] << ',';
}
FileWriter << dataName << std::endl;
FileWriter.close();

这当然很容易,但这似乎很俗气,实际上效率低下。我想知道是否有更好的方法来保存数据,并且在我稍后阅读它时仍然可以分开。

不幸的是,我所做的搜索只产生了以下内容:

std::getline( FileReader, myStringBuffer, ',');

所以我可以存储单独的数据点,这样它们在读取时可以区分,在保存时没有使用分隔字符?也就是说,不使用某些字符或空格分隔数据。

3 个答案:

答案 0 :(得分:1)

根据您的值,按特定字符分隔值可以起作用:如果字符串不使用分隔字符(例如逗号),则可以使用逗号分隔符保存值。当没有任何已知有用的角色时,事情变得有趣。在这种情况下,典型的方法是使用引号和合适的转义字符,例如C和C ++用于特定字符串文字的内容:

  • 通常字符串以单引号"开头。
  • 要将引号嵌入字符串中,请使用反斜杠进行转义,例如"\""
  • 要嵌入转义字符反斜杠,它会使用两个反斜杠,例如"\\"

有时使用的另一种方法是将值与大小前缀组合。但是,使用的内容取决于确切的需求。

当您使用逗号作为分隔符时,您可能需要在读取格式化值时跳过逗号:例如,整数:它们不会轻易读取逗号,只是忽略它可能不合适。如果它丢失则显然是格式错误。您可能希望在存在时使用操纵器来添加逗号:

std::istream& comma(std::istream& in) {
    std::istream::sentry cerberos(in);
    if (in && in.peek() == ',') {
        in.ignore();
    }
    else {
        in.setstate(std::ios_base::failbit);
    }
    return in;
}
// ...
int i, j;
if (in >> i >> comma >> j) { ... }

输入表达式应该读取两个以逗号分隔的整数,如果其中任何一个值不是int,或者它们没有用逗号分隔,则会失败。

答案 1 :(得分:1)

如果我正确理解您的问题,您希望知道如何以您可以再次阅读的格式存储数据(可能是在另一个C ++程序中)。

如果是这样,那么有很多方法可以做到这一点:

最常见(也是最简单)的方式是:

  1. 空格分隔(例如): value1 value2 value3
  2. 逗号(这将生成以逗号分隔的文件,通常称为CSV文件) 1,2,3
  3. 或者,任何角色: 1#2#3
  4. 这样您可以像使用std::getline一样使用{例如对于CSV):

    char delim = ',';
    
    while(std::getline(input_stream, temporary_string, delim) {
        //data handling goes here...
    }
    

    当然,由于这是一个天真的例子(即您的数据被构造为表格),您将不得不调整代码以通过读取数据块中的数据来解决跨越多行的更多多面数据并根据您的格式解析这些块。

    复杂示例(卫星坐标):

    1.1 1.2 1.3 1.4 1.5
    1.6   1.7 1.8 1.9
    2.0        
    2.0
    2.1 2.2 2.3 2.4 2.5
    2.1     2.4
    

    这是以空格分隔的,格式如下:

    1. 每个数据点都以下列模式存储:数据,空间。
    2. 如果数据点不存在,则由空格表示,除非它 所有其他输出都是最后一个不存在的数据点 截断为换行符。

答案 2 :(得分:1)

基本二进制文件io实践将做你想要的。读取二进制数据时,您需要知道正在读取的每个数据的大小;知道这将推动你的许多设计决策。如果你想读取一个int后跟一个字符串,你需要知道一个int的大小(通过调用sizeof(int)很容易找到),这样你就可以从二进制blob中“蚕食”一个int的数据正在尝试从中加载数据,然后在读取int的数据后,您需要知道字符串的大小。由于字符串的长度是可变的,您需要假定一个标准长度(yuck!),或者首先从FROM A KNOWN SIZE OF DATA读取长度,然后将多个字节读入字符串。因此,您的数据写入程序需要在写出字符串之前写出字符串的长度(或任何其他可变大小的数据类型),作为已知的数据大小(比如将大小信息写为unsigned int)。

有关组织二进制数据以进行读/写的巧妙方法,请查看交换文件格式(IFF)。它是TIFF,RIFF等都基于的,是设计二进制文件blob的好方法。它基本上将数据存储为“块”,其中数据首先写出一个块ID,然后是块的大小(以字节为单位),然后是该块的数据。这样,读者程序可以检查块ID,如果它不想/知道如何处理某种甚至未知类型的数据,它可以跳过块大小(以字节为单位)并读取下一个块。