C++ 如何从二进制文件中读取最后一行
有一个二进制文件,其中包含如下数据(这两个文件都具有字符串数据类型) 我想读取位于文件末尾的数据(在本例中,确切地说是Didier&drogba)。所以我写了一个代码来处理它,如下所示 结构:C++ 如何从二进制文件中读取最后一行,c++,file-io,binary,C++,File Io,Binary,有一个二进制文件,其中包含如下数据(这两个文件都具有字符串数据类型) 我想读取位于文件末尾的数据(在本例中,确切地说是Didier&drogba)。所以我写了一个代码来处理它,如下所示 结构: struct user { string id; string pwd; }; 读取数据的代码: void confirm(const char* f) { user u; ifstream in; in.open(f, ios::in | ios::binary);
struct user
{
string id;
string pwd;
};
读取数据的代码:
void confirm(const char* f)
{
user u;
ifstream in;
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
}
void确认(常量字符*f)
{
用户u;
如果输入;
in.open(f,ios::in | ios::binary);
如果(!in)
{
cout u.id>>u.pwd)
{
if(在.eof()中)
{
cout通常在文件的每一行末尾都有一个换行符(或在某些操作系统上是***s***字符)
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
>std::skipws
将前进到文件末尾或下一个名称,如您所希望的那样设置eof()
标志。通常在文件的每一行末尾都有一个换行符(或某些操作系统上的字符***s***)。您的代码
while (in >> u.id >> u.pwd)
{
if (in.eof())
{
cout << "Registration Complete. " << endl;
cout << "Your user information: " << endl;
cout << "ID:" << u.id << " " << "Password: " << u.pwd << endl;
}
}
>std::skipws
将前进到文件末尾或下一个名称,如您所希望的那样设置eof()
标志。一种可能性如下:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.\n";
cout << "Your user information:\n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "\n";
}
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
user u;
while (in >> u)
;
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
这将主代码简化了一点,如下所示:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.\n";
cout << "Your user information:\n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "\n";
}
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
user u;
while (in >> u)
;
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
诚然,在这种情况下(只有两个字段),这只是一个小的改进,但仍然是一个小的改进,当您需要处理更多的字段时(尤其是当读取对象的代码变得更复杂时),将读取对象的代码隔离到其自身的函数中可以大大简化其余的代码
请注意,无论最后一个数据后面的文件中有多少空白(尾随\n或缺少空白不会影响结果),此操作都有效
一种可能是这样的:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.\n";
cout << "Your user information:\n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "\n";
}
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
user u;
while (in >> u)
;
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
这将主代码简化了一点,如下所示:
void confirm(const char* f)
{
user u;
ifstream in(f, ios::in | ios::binary);
while (in >> u.id >> u.pwd)
;
cout << "Registration Complete.\n";
cout << "Your user information:\n";
cout << "ID:" << u.id << " " << "Password: " << u.pwd << "\n";
}
struct user {
std::string id;
std::string pwd;
friend std::istream &operator>>(std::istream &is, user &u) {
return is >> u.id >> u.pwd;
}
};
user u;
while (in >> u)
;
if((u1.id == u->id)&& (u1.pwd == u->pwd))
{
cout << "Registration Complete." << endl;
cout << "You registered;" << endl;
cout << "ID:" << u1.id << "," << "Pwd: " << u1.pwd << endl;
delete u;
break;
}
诚然,在这种情况下(只有两个字段),这只是一个小的改进,但仍然是一个小的改进,当您需要处理更多的字段时(尤其是当读取对象的代码变得更复杂时),将读取对象的代码隔离到其自身的函数中可以大大简化其余的代码
请注意,无论最后一个数据后面的文件中有多少空白(尾随\n或缺少空白不会影响结果),此操作都有效
行实际上并不存在于二进制文件中,除非作为一种约定,例如行是一个字节序列(与'\0'
和'\n'
不同),由换行符'\n'
终止(该约定可能因操作系统而异,某些操作系统使用“\r\n”
或”\n\r”
甚至'\r'
作为行尾)
您可以循环读取文件末尾的行,将行保留在一些std::string
中,并解析最后一行字符串(使用等…)
可选的,将行的末尾视为空间分隔符,如Tyel-Dr.DoE < /Cord>中的一行将被处理为两行<代码> Tyler Bred < /C>和<代码>某个身份不明的人< /C> > .P> >行在二进制文件中并不存在,除非是惯例,就像行是字节序列。(与
'\0'
和'\n'
不同)以换行符'\n'
终止(这种约定可能因操作系统而异,一些操作系统使用“\r\n”
或“\n\r”
甚至'\r'
作为行尾)
您可以循环读取文件末尾的行,将行保留在一些std::string
中,并解析最后一行字符串(使用等…)
P> >将线的末尾视为空间分隔符,如图所示,Tyel-Dr.DoE 的单行将被处理为两行<代码> Tyler Bred < /代码>和<代码>某个身份不明的人< /代码> .< /P> < P>代码>删除u < /代码>
这将释放与用户
结构关联的内存。如果文件中的行数超过1行,您将获得访问冲突,因为在下一次迭代中,您将再次接触与用户
结构关联的内存
还包括:
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
in.open(f,ios::in | ios::binary);
如果(!in)
{
cout pwd)
{
无法删除u
这将释放与用户
结构关联的内存。如果文件中的行数超过1行,您将获得访问冲突,因为在下一次迭代中,您将再次接触与用户
结构关联的内存
还包括:
in.open(f, ios::in | ios::binary);
if (!in)
{
cout << "failed to read file!" << endl;
exit(0);
}
in.open(f,ios::in | ios::binary);
如果(!in)
{
cout pwd)
{
行在二进制中没有意义。你的问题在当前形式中没有意义。你应该发明你的文件格式约定。行在二进制中没有意义。你的问题在当前形式中没有意义。你应该发明你的文件格式约定。这while(in>>u.id>>u.pwd)在 EOF中,保证不触碰<代码> u>代码>字段,这是最近C++标准中一种很好、简化的保证,有趣的是注意与您的自定义操作器<代码>返回> U.ID> U.PWD;<代码> U.S/<代码>可以成功修改< <代码> UID >代码>仅具有<代码>>u、 pwd
对于包含奇数个要提取的字符串的损坏输入文件失败:您将最后一个字符串打印出来,就像它是u.id
一样,而之前的字符串是u.pwd
,(我的答案将不打印任何内容:-()。对于正确的错误处理:Basile的getline
/istringstream
很好。这在(< U.ID> U.PWD);保证不接触<代码> U>代码>字段,如果已经在<代码> EOF是一个很好的,简化的保证,在最近的C++标准中,有趣的是注意与您的自定义操作器的代码<返回> > UID> U.PWD;< /代码>