#include
std::ifstream input;
input.open(“selfInput.txt”); //打开文件,如果没有该文件就在创建项目的文件中新建
input >> ipaddr >> index >> pid; //将这些ipaddr等输入到文件中
cout << ipaddr << endl << index << endl << pid<<endl;
#include
std::ofstream output;
output.open(“selfInput.txt”);
output << m_IPAddr << “\n” << m_index << “\n” << m_PID; //从文件中读取
/*实现txt文件的读入 并重新写入另外一个txt文件中
*/
#include
#include
#include
#include <stdlib.h>
using namespace std;
int main()
{
//string str;
//写入文件 输出到文件
/*
while (getline(fin,str)) //getline(fin,str)是逐行读取fin文件中的信息 用str接收读取到的信息
{
fout << str << endl;
cout << str << endl;
}*/
char buf[10];
char *p;
p = buf;
memset(buf,0,10);
ifstream fin; //读取
fin.open("d:\\fin.txt", ios::in);
ofstream fout; //fout写入对象
fout.open("d:\\fout.txt", ios::out | ios::app); //在文件后面续加内容
while ((*p=fin.get())!=EOF)
{
cout << *p << endl;
fout << *p << endl;
p++;
}
fin.close();
fout.close();
system("pause");
return 0;
}
关于打开文件的路径
#define filePath “D:/vsproject/fcin.exe” //这里需要使用右斜杠
#define filePath “D:\vsproject\fcin.exe” //如果是左斜杠许需要双条 考虑到转义字符的功能
0、 在这个项目中使用了封装过后的软总线DbTelecom,这样在使用软总线的时候,只需要初始化软总线即可。
DbTelecom *telecom=DbTelecom::GetInstance();
其余的发布、订阅主题还是和平时一样照些不误。
1、 发送文件这部分的内容
掌握fopen、fseek、ftell、fread、fwrite、fclose等函数基本用法。
关于文件的操作具体三步骤:打开文件-》对文件的操作-》关闭文件
fseek函数:将文件指针定位到指定位置
ftell函数:测量文件指针距离文件开始处的距离,一会和fseek结合起来使用
fread、fwrite函数:读写需要注意具体参数,在本项目中是读取一包数据发送一包;收到一包数据向文件中写入一包数据;
1) 获取文件的长度
思路:分别将文件指针定位到文件头、文件尾,在结合ftell函数得到两个距离值,两值相减就是文件的长度。
2) 读取文件的某一段内容
fread函数:是从文件指针向后读取一段数据,因此可以使用fseek定位位置,从而读取某一段的内容。
读取文件的时候出现错误:
fread(fileBlock, SIZE_EACH_BLOCK, 1, filePtr);
当你整个文档的内容大小不足SIZE_EACH_BLOCK的时候,读取文件的返回值不是,这样读取文件是错误的!!
3) 读取一包数据,使用软总线发送一包
在sender项目中定义了结构体,将你需要发送的数据 copy 到结构体的buf中,再使用sendData()函数发送出去
软总线其实就是一种类似socket的通信方式,
发送获取三个参数:主题、buf、buf的长度
接收是用一个结构体接收:相同的主题名、tmpParam.m_pBuf、tmpParam.m_ulBufSize
(注意后面两个参数与你发送的参数值是一样的,它是使用通信功能传输过来的!!)
这种方法可以解答:两个不同的项目如何共享同一个变量?
使用通信方式传输,绝对不是我想的全局变量
4) 第一包发送总的文件包数以及文件名
5) 判断最后一包
在接收端使用一个counter计数,每发送一包数据,接收的时候就会使用回调函数,这是就counter。分别对counter1 和 counter总的包数 进行相应的操作。
6) 注意内存的分配 看结构部分
你在发送端发送什么类型的数据,在接收端就要解析相应的数据
解析的时候需要注意内存的合理分配。
2、 接收文件这部分的内容
1) 对回调函数新的认识
tmpParam.m_pBuf:就是你发送数据的buf, 使用引用,指向那一块内存
tmpParam.m_ulBufsize:就是你发送数据的buf的长度
2) 如何判断第一包和最后一包?
使用全局变量记录一下即可,具体用法需要感受一下
3) 关于文件句柄的问题
当FILE *fp;定义为全局的时候,只需要打开文件一次即可。获取了文件句柄具体用法看项目
4) 原本的想法是用一个buf,将读取的数据全部接收过来,然后再分包写入,但是这样写会出现写入的exe文档打不开。后来的修改方案就是读取一份,写入一份数据。
5) 注意包数
6) 判断有没有全部接收过来,有没有遗漏,查看最后的内容、大小、以及整个包的长度。
7) 当你异常退出的时候,返回值的问题或者使用exit(1)等退出
3、 在编写过程中出现的问题
1) 下面的框架可能不正确和/或缺失,没有kernel32.dll加载符号
这个问题没有特定的解决方法,
a) 但是需要注意判断类似文件打开失败的if语句中,需要有返回值或者使用exit(0)退出。
b) 使用数组的时候,需要有内存的分配意识,具体情况在下面分析。
2) 关于全局变量和局部变量?
使用全局或者局部变量的时候都要有意识进行简单的初始化
如果没有初始化,可能会有如下的情况:
a) 对于全局变量,编译器会为它分配默认的初值,如:0,NULL;但是也不是总是这样,当项目过大,系统中没有剩余内存的时候,系统就不会为它分配初值。(这种情况还没有遇到过,只是听组长这样讲过而已)。所以全局变量需要谨慎使用。
b) 对于没有初始化的局部变量,编译器不会为它分配初值,其也就没有分配内存。
3) 文件中的内容没有传过来?
这个问题的出现是memcpy(MsgBlock.s_BlockBuf, fileBlock, SIZE_EACH_BLOCK);
就是调试的时候发现fileBlock中内容,但是MsgBlock.s_BlockBuf里面是空的。
解决方法:为MsgBlock.s_BlockBuf分配内存
struct MsgFileBlock
{
char s_BlockBuf[101024]; //我这样写只是声明了数组的大小为101024,但是没有为其分配内存。
};
MsgFileBlock()
{
memset(s_BlockBuf,’0’,10 * 1024); //中间表示存放的是什么类型的数据
}
4) 会出现文件覆盖的问题?
出现这个问题的原因是:我每次读取的内容存放在fileBlock中,然后使用memcpy函数将fileBlock中的内容copy到MsgBlock.s_BlockBuf中。这样就会出现后来的内容把之前的内容覆盖。因此需要每读取一包数据,就发送一包数据(SendData()函数发送)
5) 内存分配的问题
注意区分声明和分配内存
对于向int 、float这样的数据类型,
int i; //这样只是声明
int i=0; //为其赋了初值后,系统就会为它分配4个字节的内存
对于数组类型的:
char s_BlockBuf[10*1024];
memset(s_BlockBuf,’0’,10 * 1024); //使用memset分配内存
const int MaxLength = 100 * 1024 * 1024;
char *sMsg = new char[MaxLength]; //使用new函数在堆栈上分配内存
4、 报文编码与解码的问题
编码:
memcpy(MsgBlock.s_BlockBuf, &MsgBlock.s_BlockNumber, sizeof(int));
memcpy(MsgBlock.s_BlockBuf + sizeof(int), TmpBlock, SIZE_EACH_BLOCK);
DbTelecom::GetInstance()->SendData(“Request”, MsgBlock.s_BlockBuf, SIZE_BLOCK);
解码:
int serialNumber;
int bagSize = tmpParam.m_ulBufSize - sizeof(int);
memcpy(&serialNumber,tmpParam.m_pBuf,sizeof(int));
char *message = new char[bagSize];
memcpy(message,tmpParam.m_pBuf+sizeof(int),bagSize);
记住一点内存的在 一定范围内 偏移