鱼C论坛

 找回密码
 立即注册
查看: 3859|回复: 18

[已解决]文件的定位读写问题,请各位大佬解惑

[复制链接]
发表于 2023-1-29 21:27:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 两手空空儿 于 2023-1-29 21:41 编辑

我的设想是用一个文件来存放员工的【人数】和【员工信息】,添加或者删除时再更新文件的内容,示例代码如下

  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #define FILE "save.txt"

  5. using namespace std;

  6. class Employee{
  7. public:
  8.         //
  9.         Employee(int num, string name, int age):m_number(num), m_name(name), m_age(age){               
  10.         }
  11.         //
  12. //private:
  13.         int m_number;
  14.         string m_name;
  15.         int m_age;               
  16. };

  17. int main(void)
  18. {
  19.         int cnt = 2; //员工的数量
  20.         Employee emp[2] =  {
  21.                 {11, "张三", 25},
  22.                 {12, "李四", 33}};       
  23.         //写入数据
  24.         ofstream ofs(FILE, ios::out);
  25.         ofs << cnt << endl;
  26.         ofs << emp[0].m_number << " " << emp[0].m_name << " " << emp[0].m_age << endl;
  27.         ofs << emp[1].m_number << " " << emp[1].m_name << " " << emp[1].m_age << endl;
  28.         ofs.close();
  29.        
  30.         //增加数据,问题来了。。。。。。。。。。。。。。
  31.         //单独写入cnt, 再往文件尾追加员工信息

  32.         return 0;
  33. }
复制代码

在文件中,2(cnt)这个数字是以字符形式存放的,只占文件的1个位置, cnt = 10时,就会占两个位置
随着人数的增加,当cnt为两们数,叁位数,或者更多时,
   ofs << cnt << endl; 这一句会覆盖第一位员工的数据,
怎么才能解决这个问题?难道只能每次更新数据的时候把所有数据读出来,再重新写入一次?
(用另外的文件单独存放cnt是可以的,但是我不想分开存放)       
有没有一种方法,让文件的开头给cnt留出足够的位置,在这之后再写入员工数据
比如 cnt是 int类型,4个字节,就用4个位置用内存的形式放进去,
或者是其它什么方法
最佳答案
2023-1-29 22:10:22
两手空空儿 发表于 2023-1-29 21:54
多放很多空格会不会影响后面数据的读取?
怎么在打开文件后直接定位到第一个员工的数据的开头呢?  
是 ...

C++ 标准库的输出流可以用 std::setw 来设置位宽,自动填充空格
先输入数量时会自动跳过前缀空白字符,应该不会影响后续读取?
不过还是建议用二进制,二进制指的是用 std::basic_ostream<CharT,Traits>::write 或类似方法直接把这个变量的内存表示写进文件,这个长度(基本)是固定的,如果配合 uint32_t 之类的类型使用则可以保证其写入文件必然是 32 / CHAR_BIT 个(通常是 4 个)字节,通常也不需要做填充之类的操作
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-29 21:54:41 | 显示全部楼层
dolly_yos2 发表于 2023-1-29 21:36
可以插空格之类的字符填充预留的位置吧
另外如果不需要保持生成文件人类可读,可能用二进制存储这个数量也 ...

多放很多空格会不会影响后面数据的读取?
怎么在打开文件后直接定位到第一个员工的数据的开头呢?  
是不是只能在初始创建文件时就把10个空格放进去,
要是先写入cnt,再补空格,这个操作有点管繁琐,还要计算每次要补多少个空格, 一个空格占两们位置,当cnt为奇数位时,写入cnt之后的读取是不是也会不准确?

二进制存储也是会覆盖后面数据的吧, 用二进制的方式,空格来占位好像还行,我试试
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 22:25:09 | 显示全部楼层

谢谢大佬~~~
你的用法好高级,我要好好消化一下,
有没有哪个地方可以查询 标准类库的函数的地方,>>  <<   和 read, write  这些东西我要好好学习一下
还有string类内的函数,现在学的有点乱
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 22:27:09 | 显示全部楼层
dolly_yos2 发表于 2023-1-29 21:36
可以插空格之类的字符填充预留的位置吧
另外如果不需要保持生成文件人类可读,可能用二进制存储这个数量也 ...

用二进制的方式 ,10个空格占位,这个方法是可行的
  1. //写入数据
  2.         ofstream ofs(FILE, ios::trunc | ios::binary);
  3.         ofs << "          " <<endl;
  4.         ofs.seekp(ios::beg);
  5.         ofs << cnt;
  6.         ofs.seekp(10);
  7.         ofs << emp[0].m_number << " " << emp[0].m_name << " " << emp[0].m_age << endl;
  8.         ofs << emp[1].m_number << " " << emp[1].m_name << " " << emp[1].m_age << endl;
  9.         cout << "第一次写入完成" << endl;
  10.         system("pause");
  11.         //更改人数
  12.         ofs.seekp(ios::beg);
  13.         cnt = 9999;
  14.         ofs << cnt;
  15.         ofs.close();
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 22:34:57 | 显示全部楼层
dolly_yos2 发表于 2023-1-29 22:10
C++ 标准库的输出流可以用 std::setw 来设置位宽,自动填充空格
先输入数量时会自动跳过前缀空白字符, ...

好的,谢谢~~~
C++标准库从哪里可以查到啊,学C的时候查了库函数让自己明白了不少,学C++又不行了,
iostream就会 << , >> , string 类用起来也不太清楚
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 22:40:35 | 显示全部楼层

辛苦大佬啦,模版,容器 ,这些我还没学,还看不懂,哈哈哈哈哈

加油学,学完再回过头来再学习大佬的这段代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 23:22:37 | 显示全部楼层
人造人 发表于 2023-1-29 22:29
https://cplusplus.com/reference/iostream/
https://zh.cppreference.com/w/cpp/header
https://www.a ...

谢谢~~~~ 全部收藏啦,把常用的东西仔细学一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 23:24:01 | 显示全部楼层
dolly_yos2 发表于 2023-1-29 22:10
C++ 标准库的输出流可以用 std::setw 来设置位宽,自动填充空格
先输入数量时会自动跳过前缀空白字符, ...

谢谢~~~ ,帮我解决了暂时的问题,二进制读写的操作我还要好好学习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-31 12:11:28 | 显示全部楼层
本帖最后由 两手空空儿 于 2023-1-31 12:16 编辑
人造人 发表于 2023-1-29 21:58
不要用ascii写,用二进制写


我终于悟了,打开文件的方式是不是用binary和读写完全没什么关系,我前面以为打开方式不同决定写入和读取的方式
是不是用binary的打开方式,只影响换行符这个东西
用write的方式写入数字,都不用考虑会覆盖问题,内存里怎么放的,文件里就是怎么放的
字符串加长的话会有覆盖的问题,这个要自己注意
用<<  或者 fprintf 这种方式向文件里写东西是把数字转成了字符串写进去的
谢谢大佬提点
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-11-3 08:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表