1

我正在尝试自学编程,而我难以理解的一个早期主题是文件 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, ',');

那么我是否可以存储单独的数据点,以便在读取时可以将它们区分为单独的,而在保存时不使用分隔符?也就是说,不使用某些字符或空格分隔数据。

4

3 回答 3

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) { ... }

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

于 2013-11-14T02:43:51.903 回答
1

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

如果是这样,那么您可以通过多种方式执行此操作:

最常见(也是最简单)的方法是通过:

  1. 空格分隔(例如): value1 value2 value3
  2. 逗号(这将生成一个逗号分隔的文件,通常称为 CSV 文件) 1,2,3
  3. 或者,任何字符: 1#2#3

这样您就可以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. 如果数据点不存在,则用空格表示,除非它是所有其他输出被截断为换行符的最后一个不存在的数据点。
于 2013-11-14T02:50:37.970 回答
1

基本的二进制文件 io 实践将做你想做的事。读取二进制数据时,需要知道所读取的每条数据的大小;知道这将推动您的许多设计决策。如果你想读入一个 int 后跟一个字符串,你需要知道一个 int 的大小(通过调用 sizeof(int) 很容易找到),这样你就可以从你的二进制 blob 中“蚕食”一个 int 的数据正在尝试从中加载数据,然后在您读取 int 的数据价值后,您需要知道您的字符串有多大。由于字符串的长度是可变的,因此您要么需要假设标准长度(糟糕!),要么首先从已知大小的数据中读取长度,然后将那么多字节读入字符串。因此,您的数据编写器需要在写出字符串之前写出字符串的长度(或任何其他可变大小的数据类型),

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

于 2013-11-14T16:11:54.693 回答