C++Builder 程序员博客
7 Sep
请问用 CB实现对数据库实现同时向两个 数据库写数据,不是 两张表,是两 个 数据库名
例如:its
itses
我用oracle数据库比较多。希望能给点指引,有代码更好,
我不知道该向什么方向出发,是数据库的问题吗?用触发器还是BC代码线程处理。
本人刚学编程,对面向对象的过程和写程序的结构不是很清除。希望指点。
用2个ADOConnection连接2个数据库,分别操作,不就得了
1 Sep
程序里有几个子线程利用Socket发送和接收数据,如果使窗口最小化就不会产生错误,但是如果在这个过程中窗口最小化了,程序就会关闭,Socket连接也就断了,请问可能是什么原因会产生这个错误呢?
程序里并没有任何像OnResize()之类的操作呀,也没有在代码中设定过窗口大小什么的。
现在发现就算是对任务栏里的其它程序进行最大化最小化操作,也会使本程序出现异常……为什么别的进程也会影响到呢?
包的发送有问题吧
28 Aug
txt文件的格式是自己从原来的数据库用memo导出来的,数据都用tab分开的
第一行数据要导入第一个表
第二行数据要导入第二个表
后面的数据导入到第三个表(行数未知)
三张表同在一个数据库中
因为需要"定时导入数据",所以就利用了windows自带的任务计划功能(方法比较土 - -!
但是txt文件的路径需要用参数的方法告诉这个程序
求问下这类程序的写法
接触CB差不多一个月了,之前做的工作都是在别人的基础上修改程序
突然让自己写一个出来就傻了 - -!
还望各位大侠指点一下
定时导入这个可以不做的
主要是数据导入对我来说比较难做…
因为原来没有用C++ Builder创建过程序
不知道该如何下手..
比如说程序结构大概是怎样的?
你可以用orcle专用load倒入工具,只有配置一下即可,比你写程序简单多啦。
使用sql语句配合odbc一样可以导入,真的不要写程序啦,sql导入的灵活性可强多了
可以同时导入多个文件么?(每个文件结构相同)
求范例写法
多个表,用直接SQL有些繁。最简的方法,一行行的读,一行行导入
结你个例子:
1.先建三个表
create table t1( ta1 varchar(10),ta2 varchar(10) );
create table t2( tb1 varchar(10),tb2 varchar(10) );
create table t3( tc1 varchar(10),tc2 varchar(10) );
2.文本数据:
'111' '222'
'333' '444'
'555' '666'
'777' '888'
'999' 'aaa'
'bbb' 'ccc'
3.程序:
//————————————————————————— #include <vcl.h> #pragma hdrstop #include "testora.h" //————————————————————————— #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //————————————————————————— __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //————————————————————————— void __fastcall TForm1::Button1Click(TObject *Sender) { TStringList *t=new TStringList() ; String x; ADOConnection1->Connected=true; if (OpenDialog1->Execute()) { t->LoadFromFile(OpenDialog1->FileName); x=t->Strings[0]; x="insert into t1 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); x=t->Strings[1]; x="insert into t2 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); for(int i=2;i<t->Count;i++) { x=x=t->Strings[i]; if (x.Trim()=="") continue; x="insert into t3 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); } } delete t; } //—————————————————————————
感谢ls各位的指点
特别是keiy的代码
试了一下,报错说"missing comma"
然后把'111'和'222'中间的空格改成逗号就可以了
问下keiy大侠,可以改成不要界面,而转为支持多个参数的命令行的方式么?
参数为txt的路径,数目不确定。
"missing comma" 错是因为我的txt文件中间是tab而非空格(改为,或tab都可以)
console程序为:
#include <vcl.h> #include <ADODB.hpp> #include <DB.hpp> #include <iostream> using namespace std; #pragma link "adortl.lib" #pragma link "dbrtl.lib" #pragma link "rtl.lib" int main( int argc,char *argv[]) { if (argc<2) { cout << "Miss TXT FileName" << endl; return -1; } CoInitialize(NULL); TStringList *t=new TStringList() ; String x; TADOConnection *ADOConnection1=new TADOConnection(NULL); ADOConnection1->ConnectionString="你的连接串"; TADOQuery *ADOQuery1=new TADOQuery(NULL); ADOQuery1->Connection = ADOConnection1; ADOConnection1->Connected=true; cout << "connect db ok" <<endl; t->LoadFromFile(argv[1]); x=t->Strings[0]; x="insert into t1 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); x=t->Strings[1]; x="insert into t2 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); for(int i=2;i<t->Count;i++) { x=x=t->Strings[i]; if (x.Trim()=="") continue; x="insert into t3 values("+StringReplace(x,"\x09",",",TReplaceFlags()<<rfReplaceAll)+")"; ADOQuery1->SQL->Text=x; ADOQuery1->ExecSQL(); } delete t; cout << "ok" << endl; return 0; }
注意:编译时要加cp32mt.lib库
如你的文件名为t.cpp
编译时:
bcc32 t cp32mt.lib
(cp32mt.lib用#pragma link加在程序中是无用的,不知为什么)
谢谢keiy少
"你的连接串"是不是按照当时application的时候ADOConnection1的值填进去就可以了???
- -!
饿了,先回去吃饭了
明天接着看…
你的连接串"就是按照当时application的时候ADOConnection1的值填进去就可以了
在cmd下bcc32编译通过
然后转到工程目录,输入
Unit1.exe 2 111.txt
显示如下结果然后出错退出
connect db ok
—
输入
Unit1.exe 2 111.txt 222.txt 333.txt
结果和上面一样
—
111.txt 222.txt均为工程目录下文本文件
不知道是我参数输入不正确还是其他原因?
你看一下程序,我的程序只能有一个参数
试试
unit1.exe 111.txt
嗯,已经可以了…
如果希望读入多个参数而且参数数目不固定的话是不是需要用到CmdLine、ParamStr()、ParamCount()这几个函数?
可以不用CmdLine、ParamStr()、ParamCount(),因为c/c++本身就有
int main( int argc,char *argv[])
中的argc为参数个数。
argv[0]….程序本身
argv[1]….第一个参数
argv[2]….第二个参数
…
加了一个循环
for(int i=1;i <argc;i++)
{
t->LoadFromFile(argv[i]);
…
…
…
}
编译可以通过
不过运行时还是出错
是循环体写的不对么?
程序应该没问题.但要保证参数所指向的文件名全部存在,如按你写的
Unit1.exe 2 111.txt 222.txt 333.txt
中的2,也必须是一存在的文件的名字,且数据要符合上面的格式
我写的只是测试,容错方面还是要再完善的
另外编译一定要带上 cp32mt.lib 不然运行会错(在我机上如此)
嗯,回头我再调试一下…
麻烦keiy少了
明天过来结贴…
27 Aug
对网络编程不是很了解…问一问
如果我要获取我其他机器发到我本机某一特定端口的数据包,该如何做,有没有朋友给个思路?
那个bcb里的ServerSocket那个控件是不是只能监听ClientSocket程序发过来的数据?如果是TCP/IP模式的,是不是可以使用IDTCPServer等控件?
recvfrom(sock, buff, size, opt, addr, addr_size);
用这个函数就ok,这个函数在winsock里面;
其实,这个函数是freeBSD操作系统的,
unix也采用了,linux也是一样采用,
当然,windows也有这个函数;
ServerSocket,IDTCPServer都可以监听任何程序发过来的包
25 Aug
现有用户的密码字段,当将见面上Edit_Password->Text插入数据库时作加密运算,加密后再保存到数据库,如果修改密码就要将密码还原过来。
如:123456789是密码,插入数据库后看到的是一串乱码,但读取出来还是123456789
注:不要太复杂,如密码为123456插入数据库后不要是654321就行。
此问题很急,请大家速给帮个忙解决。
void Des_Bit2Byte(byte *text1, byte *text2) { int i_temp1, i_temp2; byte mask, c_temp1; for (i_temp1 = 0; i_temp1 < 8; i_temp1++) { c_temp1 = text1[i_temp1]; mask = 0×80; for (i_temp2 = 0; i_temp2 < 8; i_temp2++) { if (c_temp1 & mask) text2[i_temp1 * 8 + i_temp2] = 1; else text2[i_temp1 * 8 + i_temp2] = 0; mask >>= 1; } }; return; } void Des_Byte2Bit(byte *text1, byte *text2) { int i_temp1, i_temp2; byte mask; memset(text2, 0, 8); for (i_temp1 = 0; i_temp1 < 8; i_temp1++) { mask = 0×80; for (i_temp2 = 0; i_temp2 < 8; i_temp2++) { if (text1[i_temp1 * 8 + i_temp2]) text2[i_temp1] |= mask; mask >>= 1; } } return; } void Des_DesEncry(byte *text1, byte *key) { byte c_temp1[64], c_temp2[32]; int i_temp1, i_temp2; Des_TransPose(text1, Des_Table0, 64); Des_TransPose(key, Des_Table1, 56); for (i_temp1 = 0; i_temp1 < 16; i_temp1++) { memcpy(c_temp1, text1+32, 32); Des_Process(i_temp1, key, c_temp1, c_temp2, ‘L‘); for (i_temp2 = 0; i_temp2 < 32; i_temp2++) if (text1[i_temp2] == c_temp2[i_temp2]) c_temp1[i_temp2 + 32] = 0; else c_temp1[i_temp2 + 32] = 1; memcpy(text1, c_temp1, 64); } memcpy(text1, c_temp1+32, 32); memcpy(text1+32, c_temp1, 32); Des_TransPose(text1, Des_Table3, 64); return; } void Des_DesDecry(byte *text1, byte *key) { byte c_temp1[64], c_temp2[32]; int i_temp1, i_temp2; Des_TransPose(text1, Des_Table0, 64); memcpy(c_temp2, text1+32, 32); memcpy(text1+32, text1, 32); memcpy(text1, c_temp2, 32); Des_TransPose(key, Des_Table1, 56); for (i_temp1 = 0; i_temp1 < 16; i_temp1++) { memcpy(c_temp1 + 32, text1, 32); Des_Process(i_temp1, key, c_temp1 + 32, c_temp2, ‘R‘); for (i_temp2 = 0; i_temp2 < 32; i_temp2++) if (text1[i_temp2 + 32] == c_temp2[i_temp2]) c_temp1[i_temp2] = 0; else c_temp1[i_temp2] = 1; memcpy(text1, c_temp1, 64); } Des_TransPose(text1, Des_Table3, 64); return; } void Des_TransPose(byte *text, byte *table, int index) { byte c_temp1[64]; int i_temp1; memcpy(c_temp1, text, 64); for (i_temp1 = 0; i_temp1 < index; i_temp1++) text[i_temp1] = c_temp1[table[i_temp1] - 1]; return; } void Des_Process(int i, byte *key, byte *R32, byte *PB, byte flag) { byte extr32[48], extkey[56], c_temp1; int i_temp1; memcpy(extr32, R32, 32); Des_TransPose(extr32, Des_Table4, 48); if (toupper(flag) == ‘L‘) Des_Lshift(key, Des_Table5[i]); else Des_Rshift(key, Des_Table6[i]); memcpy(extkey, key, 56); Des_TransPose(extkey, Des_Table2, 48); for (i_temp1 = 0; i_temp1 < 48; i_temp1++) if (extr32[i_temp1] == extkey[i_temp1]) extr32[i_temp1] = 0; else extr32[i_temp1] = 1; for (i_temp1 = 0; i_temp1 < 8; i_temp1++) { c_temp1 = (byte)(extr32[i_temp1 * 6] * 32 + extr32[i_temp1 * 6 + 5] * 16 + extr32[i_temp1 * 6 + 1] * 8 + extr32[i_temp1 * 6 + 2] * 4 + extr32[i_temp1 * 6 + 3] * 2 + extr32[i_temp1 * 6 + 4]); c_temp1 = Des_Table8[i_temp1][c_temp1]; if (c_temp1 >= 8) { PB[i_temp1 * 4] = 1; c_temp1 = (byte)(c_temp1 - 8); } else PB[i_temp1 * 4] = 0; if (c_temp1 >= 4) { PB[i_temp1 * 4 + 1] = 1; c_temp1 = (byte)(c_temp1 - 4); } else PB[i_temp1 * 4 + 1] = 0; if (c_temp1 >= 2) { PB[i_temp1 * 4 + 2] = 1; c_temp1 = (byte)(c_temp1 - 2); } else PB[i_temp1 * 4 + 2] = 0; if (c_temp1 >= 1) PB[i_temp1 * 4 + 3] = 1; else PB[i_temp1 * 4 + 3] = 0; } Des_TransPose(PB, Des_Table7, 32); return; } void Des_Lshift(byte *key, byte cnt) { byte c_temp1, c_temp2; int i_temp1,i_temp2; for (i_temp2 = 0; i_temp2 < cnt; i_temp2++) { c_temp1 = key[0]; c_temp2 = key[28]; for (i_temp1 = 0; i_temp1 < 55; i_temp1++) key[i_temp1] = key[i_temp1 + 1]; key[27] = c_temp1; key[55] = c_temp2; } return; } void Des_Rshift(byte *key, byte cnt) { byte c_temp1, c_temp2; int i_temp1,i_temp2; for (i_temp2 = 0; i_temp2 < cnt; i_temp2++) { c_temp1 = key[27]; c_temp2 = key[55]; for (i_temp1 = 55; i_temp1 >0; i_temp1–) key[i_temp1] = key[i_temp1 - 1]; key[0] = c_temp1; key[28] = c_temp2; } return;
简单的,异或
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; class encrypt { public: encrypt(const char *); //构造函数,加密 ~encrypt(); void showcode(); void decrypt(); //解密 private: char *code; int length; }; encrypt::encrypt(const char *string) { int i=0; length=strlen(string);//获得原字符串的长度 code=new char[length+1];// 加上结束符’\0′ for(;i<length-1;i++) //从第一个字符开始,直到倒数第二个 { code[i]= string[i] ^ string[i+1]; //加密 } code[i]= string[i] ^ string[0];//i=length-1,最后一个字符 //跟第一个字符做异或 code[length] = ‘\0‘; //加上结束符 } encrypt::~encrypt() { delete[] code; } void encrypt::showcode() { for(int i=0;i<length;i++) printf("%1c",code[i]); //防止’\0′,将字符逐个打出.不用iostream //iostream遇到’\0′会自动结束,,而加密过程中可能中间出现’\0′,不该结束 } void encrypt::decrypt() { char p; cout <<"\nThe First Character:"; cin >> p; code[length-1] ^= p; //最后一个字符跟第一个再次异或,得到原来的字符(两次异或,得到原值) for(int i=length-2; i>=0 ; i–) //从倒数第二个开始 { code[i]^=code[i+1]; //跟后面一个做异或,得原值 } cout<<"the original string is:" <<endl; showcode(); cout <<endl; } int main() { encrypt e("hello world!"); e.showcode(); e.decrypt(); return 0; }
小弟刚学C++不久,还愿详细一点,现我的程序是窗口的形式,有个edt_password文本框,数据库中有个user表,表里有个password字段。
现我要将edt_password里的内容加密后放到password的字段中,然点再修改让password字段的内容显示到edt_password中,插入数据库是加密后的内容,读取出来要是解密后的内容,望兄弟给个这样的实际例子。
直接把edt_password里的内容放到password的字段中你会不会?
最简单的办法就是将各个位异或一下就可以了
搞个函数就可以了,忘了是引用谁的了,不过可以用。
AnsiString encode(AnsiString *source)//异或加密,带钥匙加密,加密钥匙内部定义
{
AnsiString astrEcode;
//用户专用密码,可以修改其中的5个密匙
static const char i_userkey[5] = {0xab,0xbc,0xcb,0xde,0xef};
//开始加密/解密
if(source->Length()>0)
{
for(int i=1; key=source->Length(); i <=key; i++)
astrEcode = astrEcode + (char)(*source->substring(i,1).c_str() ^ (i+i_userkey[i%5));
return astrEcode;
}
//解密的时候再调用这个函数就可以了。
建议使用成熟的加密算法。
3 Aug
我用的access的数据库,在表中我定义了双精度型的字段,提交进去的时候是标准的例如提交的是1.1;在access中也是1.1;可是在dbgrid的中显示的是1.099999999;我在access中的字段是设置了显示2位小数,提出来时还是这样,奇怪的是不是所有的都是这样,一样属性的两个字段,一个在dbgrid的中就出现了精度问题,另一个在dbgrid中就是正常的;在access中都是正常的显示,请问如何解决!!
1 Aug
两行数据是相同的内容,我在企业管理器里直接删哪行,都报错,说删除该行会影响到其它行,如果两行同时选中删,也不行.
在程序中用代码删,同样的结果.
会影响其他行,?
是不是有外键关联?,先取消掉外键关联,再删除看看,,
应该是有外健引起的。
这个问题我同样提在"数据库专区"得到了答案,在查询分析器里用"delete语句"删,在数据库专区才1分,立马就有人回答了,在CB的数据库专区,20分半天也没个人,看来这里人少哇
29 Jul
只用query,datasource,dbgrid等控件,是能显示数据库中的内容,但是我想查询完后将结果显示在edit上怎么办?
比如我的表中有name 和 phone两列
我用Query->SQL->Text="selec * from ‘表名’where name='aa'";
那怎么得到与之对应的phone将之显示在edit上?
我找了半天query的函数,也找了用grid的行列得数据,都不成功。
edit1->Text=query1->fieldbyname("字段名")->Astring
楼上的笔误了,是 query1->FieldByName("phone")->AsString ,
不过强烈建议用TDBEdit,这样可自动保证与字段数据的同步
哦,瞧我昨天费劲的,
int i = Query->FieldCount;
AnsiString Str;
if(i>0)
str = Query->Fields->Fields[0]->FieldName;
Edit->Text = Query->FieldByName(Str)->AsString;
果然有高人指点就是快呀
不对呀,如果我的查询到的是很多行数据,一个
Edit->Text = Query->FieldByName(Str)->AsString;
怎么表示呀?????
//一个Edit 只能显示一行的值
//循环显示
while ( !Query->Eof )
{
Edit1->Text = Query->FieldByName("id")->AsString;
Query->Next();
}
//Query 的AfterScroll 事件中(同步dbgrid中选中的行)
Edit1->Text = AnsiString(Query->FieldValues["id"]);
加入一个Button,点一次换一个记录
Query->Next();
Edit1->Text = Query->FieldByName("name")->AsString;
29 Jul
我用TServerSocket的TCP SOCKET堵塞模式,多线程与四个客户端通信,四个客户端会每隔一秒向我发送数据帧,数据帧的分割采用数据帧头upTransmitterSecondData和数据帧尾END进行分割,现在有一个奇怪的想象,平均每隔二到三天,接收到的数据包会出错一次,随后就正常。下面是出错包的内容:
upTransmitterSecondData ¦523304 ¦2008-06-02 23:51:03 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦EN蘵pTransmitterSecondData ¦523304 ¦2008-06-02 23:51:04 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦END
正确的是:
upTransmitterSecondData ¦523304 ¦2008-06-02 23:51:03 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦ENDupTransmitterSecondData ¦523304 ¦2008-06-02 23:51:04 ¦1 ¦35 ¦000F05C20//20 ¦0.40 ¦95.00 ¦10.00 ¦18.20 ¦0.56 ¦630.00 ¦464.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦759.00 ¦13.30 ¦297.00 ¦0.56 ¦1.63 ¦0.00 ¦0.00 ¦13675 ¦1.13 ¦END
也就是说第一个数据帧尾END被改变了。它不是每次发送数据包都出错,就是大概二到三天,出错一次,请教大家是何原因?
你的程序有没有验证机制,比如说包大小之类的校验一下,如果是错包,重发就是!
我没有采用原始的SCOKET协议进行分装,而是采用TServerSocket的TCP SOCKET堵塞模式,buffer大小为4096,每次接收完数据后进行数据帧分割,然后就会调用memset函数将buffer置零.现在问题是TCP通信情况下,数据帧已经不会出错了,为何还会出错呢?
我认为这就不可能出错的,不是出错重发问题啊!
因为TCP底层已经进行数据校验,保证数据的正确性,我的程序采用TServerSocket的TCP SOCKET堵塞模式,并非直接从底层SCOKET协议编程,所以可以认为接收到的数据已经正确了,如果说我的程序代码出错,为何平时代码不错呢?
这应该跟传输没关系,是应用层给TCP的数据出了问题,像“EN蘵”这样的情况我感觉是你对填充数据的缓存没处理干净。
memset函数怎么用的呢?看样子是指针错误,非法的内存块。
用什么版本的 SINFF ?
有时候 对的版本也会出现这种情况。。。
不一点是你代码错了
如果真的话 判断一下 发过来包的长度
然后和你需要接受的做比较
如果不一样 推出 重新 发送邀请命令
再接受。 成功了再做你需要的事情
最好祝你好运气。
MABEY TServerSocket 9.0 以下的版本存在BUG
建议升级道 10.0
当然老版本 代码不要该
你找台 没用的机器 装上 10.0 然后做测试。。
有时候 错的版本也会出现这种情况。。
不一定是你代码错了
然后和你需要接受数据大小做比较
我的编程环境是CB6+UPDATE4,分别和JAVA、VC和CB三种程序的客户端通信,奇怪的是与JAVA、VC的客户端通信均正常,就是与另外一家公司用CB6做客户端通讯出现这个问题!
memset(buffer, 0, 4096); // initialize the buffer
//////////////////////接收数据
if(pStream->WaitForData(1000))
{
ReadByteNum=pStream->Read(buffer, 4096);
if(ReadByteNum <= 0)
{
//缓冲区无数据
count++;
if(count>6)
TimeOut=true;
}
else
{
//有数据读入
netData="";
for(i=0;i <ReadByteNum;i++)
{
netData=netData+buffer[i];
}
//判断是否有错误的数据帧
if(!JudgeIsCorrectChar(netData))
{
netData="";
switch(equipmentID)
{
case 1: OtherTX1String=""; break;
case 2: OtherTX2String=""; break;
case 3: OtherTX3String=""; break;
case 4: OtherTX4String=""; break;
case 5: OtherTX5String=""; break;
case 6: OtherTX6String=""; break;
case 20: OtherANTString=""; break;
default:{}
}
/*
EnterCriticalSection(&OPLogInfoQLock);
AddInfoToQueue(LogInfoQueue,DateTimeToStr(Now())+" "+IntToStr(ReadByteNum)+" @"+netData+"@",-1);
LeaveCriticalSection(&OPLogInfoQLock);
*/
}
else
ReceiveDataHandle(equipmentID,netData);
count=0;
}
}
10楼的接收代码谁写的?ReadByteNum=pStream->Read(buffer, 4096); 如果这个只读取到了10个字节,数据会如何处理?
很明显应该是发送端或者接收端没有处理好最后一个字符。
EN蘵pTransmitterSecondData 即 EN\xccupTransmitterSecondData
感觉这段程序没什么问题啊。。。
难道C++builder的bug???
在错误的数据帧中,不仅仅是数据帧的结尾会出错,在数据帧的中间也会出错,如:
upTransmitterSecondData ¦523304 ¦2008-07-14 18啜 ? .00 ¦471.00 ¦3.79 ¦40.00 ¦8.30 ¦640.00 ¦760.00 ¦13.5 ¦296.00 ¦0.46 ¦1.75 ¦0.00 ¦0.00 ¦9540 ¦1.20 ¦END,这就和处理最后一个字符没有太大关系了,顺便提一下,对方用的是TServerSocket的非堵塞模式,而我用的是TServerSocket的堵塞模式,而另外两家用JAVA和VC的程序客户端均用的堵塞模式与我通信的,与这两家通信就没有任何问题,数据帧不会出错,就是与用CB这家通信时,数据帧出错!很是奇怪?难道与通信模式有关吗?
netData=""; for(i=0;i <ReadByteNum;i++) { netData=netData+buffer[i]; }
象这样子的代码,改成下面的代码不是更简洁而且更具效率?
netData.SetLength(ReadByteNum); memcpy(netData.c_str(), buffer, ReadByteNum);
会不会是CB6.0 TClientSocket的非堵塞模式有BUG,记得五、六年前刚接触TServerSocket时,曾做过一个C/S程序,客户端和服务端两边分别用是TServerSocket和TClientSocket的非堵塞模式进行通信,而且两边通信的数据量非常小,只有几十个字节(为了同步时间),每隔几秒发送一次。当程序运行在数据吞吐量比较小的网络中,程序不会报错,当网络吞吐量比较大时(类似网吧),程序就会出错,当时一直没有在意,现在又出现这种现象,会不会是TClientSocket的非堵塞模式有BUG呢?
15楼:netData=(AnsiString)buffer; 岂不更简洁?我现在着急找到原因啊!
象这种情况,原因应该从对方的代码当中找。
网络拥塞时会出错的
去搞份别人成功的代码
看懂了发展一下
不就行了啊
原因找到了:和程序没有任何关系,是瑞星杀毒软件造成的,我把瑞星杀毒软件退出运行了一个多星期,网络错包再也没有出现,这和我之前看到的一篇帖子不谋而合,那篇帖子说的是卡巴斯基会造成网络通信帧错误,这次是瑞星,真的很奇怪,但的确是这样的。我要给瑞星打个电话问问!
24 Jul
在用access的时候发生了这样的问题,比如a字段的类型为双精度型,在程序中提交的数字为3.4(即提交的都是带小数点的),之前还好,昨天应为程序测试改了其字段类型为单精度、字符型,最后又改回双精度型,可在dbgrid中出现的成3.400009878,这样的形式,怎么改都不行,我只好删掉了a字段,又重新创建了a字段,在录入界面的dbgrid中的显示就好了,成了3.4,可是在其他地方(我使用了kbm控件)又不行了,我看了,在access中也是3.4,感觉是因为定义了双精度型提出的时候有问题,最后只好用了roundto的方法保留两位小数,请问这是怎么回事呢,在之前都好好的,就是因为改了几次字段属性就不行了。
还有一个问题往数据库中如何提交数字的变量呢?比如ado1->sql->add("select * from b where a="i" "); 其中i是Float或是int的不定的变量例如可以是从1到10的循环,我采用了这样的形式,ado1->sql->add("select * from b where a="+FloatToStr(i)+" "); 也是别人教我的,通过了,再就是请问就这种方法为什么要将i转换成字符型呢,这个机制我不太懂.
楼上的哥哥再请教一下
1.第一个问题你是说在ado里改变吗?
2.我觉的在数据库中的浮点型的啊,可是程序中写入的sql语句提交的字符型,为什么可以匹配呢?
1.如果你是用ADO,那就在TADOTable或TADOQuery中加入字段,然后在字段属性的DisplayFormat中改
2.sql语句全部是以字符方式工作的,如:
select * from b where a=3.4
//设定小数位数
for(int i=2;i <=9;i++) //第3到第10个字段要设置为一位小数
{
TNumericField *field=(TNumericField *)ADOQuery2->Fields->Fields[i];
field->DisplayFormat="0.0";
}