C++ 如何从二进制文件中读取最后一行

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);

有一个二进制文件,其中包含如下数据(这两个文件都具有字符串数据类型)

我想读取位于文件末尾的数据(在本例中,确切地说是Didier&drogba)。所以我写了一个代码来处理它,如下所示

结构:

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;< /代码>