typedef struct{ unsigned char id; unsigned char YY; unsigned char MM; unsigned char DD; unsigned long recordCount; unsigned short headerSize; unsigned short recordSize; unsigned char reserved1[17]; unsigned char codePage; unsigned char reserved2[2];} QDBFHeader;typedef struct{ unsigned char fieldName[11]; //nazwa rekordu unsigned char fieldType; /* typ pola : C(har) 43h | D(ata) 44h / L(ogical) 4ch | M(emo) 4dh / N(umeric) 4eh | */ unsigned char reserved[4]; //zarezerwowane unsigned char fieldLen[2]; /* dla numerycznych 1 bajt = dlugosc pola 2 bajt = ilosc miejsc po przecinku dla innych typow 1 bajt = dlugosc pola 2 bajt = nieuzywany */ unsigned char notused[14]; // nieuzywane} QDBFField;
void QSocketModel::saveToDBF(const QString & fileName, QTextCodec *codec){ unsigned int recordCountDbfPortion = 100; unsigned int i, j, dbfFieldCount; unsigned short k; char *buf, *b, term; QString str; QDBFHeader *hdr; QDBFField *fld, *p_fld; QFile file(fileName); QFileInfo fileInfo(file); QDataStream fileStream(&file); if(!isActive()) return; hdr = NULL; fld = NULL; buf = NULL; if (file.exists()) if(!file.remove()){ throw QDBError(trUtf8("Невозможно удалить файл.")); } if(!file.open(QIODevice::ReadWrite)) throw QDBError(trUtf8("Невозможно создать файл.")); try{ blockSignals( true ); dbfFieldCount = Fields->count(); hdr = (QDBFHeader*) malloc(sizeof(QDBFHeader)); fld = (QDBFField*) malloc(dbfFieldCount * sizeof(QDBFField)); memset(hdr, 0x00, sizeof(QDBFHeader)); memset(fld, 0x00, dbfFieldCount * sizeof(QDBFField)); hdr->id = 0x03; // Convert 2006 to 06 hdr->YY = QString::number( QDate::currentDate().year() ).remove(0, 2).toUShort(); hdr->MM = QDate::currentDate().month(); hdr->DD = QDate::currentDate().day(); hdr->recordCount = recordCount(); hdr->headerSize = sizeof(QDBFHeader) + dbfFieldCount * sizeof(QDBFField) + 1; if(codec == QTextCodec::codecForName("CP1251")) hdr->codePage = (unsigned char) 0x57; else if(codec == QTextCodec::codecForName("CP866")) hdr->codePage = (unsigned char) 0x26; for(i = 0, p_fld = fld, hdr->recordSize = 1; i < dbfFieldCount; ++i, ++p_fld) { str = Fields->Fields[i]->fieldName().left(10); memcpy(p_fld->fieldName, str.toLatin1().data(), str.length()); switch(Fields->Fields[i]->dataType()) { case QField::ftBCD: p_fld->fieldType = 'N'; p_fld->fieldLen[0] = Fields->Fields[i]->sqlPrecision(); p_fld->fieldLen[1] = 0 - Fields->Fields[i]->sqlScale(); break; case QField::ftDouble: p_fld->fieldType = 'N'; p_fld->fieldLen[0] = 20; p_fld->fieldLen[1] = 10; break; case QField::ftDate: case QField::ftDateTime: p_fld->fieldType = 'D'; p_fld->fieldLen[0] = 8; break; case QField::ftInteger: p_fld->fieldType = 'N'; p_fld->fieldLen[0] = 10; break; case QField::ftSmallint: p_fld->fieldType = 'N'; p_fld->fieldLen[0] = 5; break; case QField::ftLargeint: p_fld->fieldType = 'N'; p_fld->fieldLen[0] = 20; break; case QField::ftString: p_fld->fieldType = 'C'; p_fld->fieldLen[0] = Fields->Fields[i]->sqlSize(); break; case QField::ftBoolean: p_fld->fieldType = 'L'; p_fld->fieldLen[0] = Fields->Fields[i]->sqlSize(); break; default: throw QDBError(trUtf8("В этой версии QSocketModel " "тип поля '") + Fields->Fields[i]->fieldName() + trUtf8("' не может быть сохранён в Dbf файле.")); } hdr->recordSize += (unsigned short) p_fld->fieldLen[0]; } fileStream.writeRawData((char*)hdr, sizeof(QDBFHeader)); fileStream.writeRawData((char*)fld, dbfFieldCount * sizeof(QDBFField)); term = 0x0D; // Завершающий символ конца заголовка fileStream.writeRawData(&term, sizeof(unsigned char)); i = 0; buf = (char*) malloc(recordCountDbfPortion * hdr->recordSize); b = buf; first(); while( !isEof() ){ // Метка - удалена запись или нет if(codec) *b = codec->fromUnicode( QString::fromUtf8(" ") ).at(0); else *b = QString::fromUtf8(" ").at(0).toLatin1(); b++; for(j = 0, p_fld = fld; j < dbfFieldCount; ++j, ++p_fld) { k = (unsigned short) p_fld->fieldLen[0]; if(Fields->Fields[j]->isNull()) str = QString(k, QString::fromUtf8(" ").at(0)); else switch(p_fld->fieldType) { case 'D': str = Fields->Fields[j]->toDate().toString("yyyyMMdd"); break; case 'N': str = QString::number(Fields->Fields[j]->toDouble(), 'f', 0 - Fields->Fields[j]->sqlScale()); if(str.length() > k) str.resize( k ); else str = QString(k - str.length(), QString::fromUtf8(" ").at(0)) + str; break; case 'C': case 'L': str = Fields->Fields[j]->toString(); if(str.length() > k) str.resize( k ); else str += QString(k - str.length(), QString::fromUtf8(" ").at(0)); break; } if(codec) str = codec->fromUnicode( str ); memcpy(b, str.toLatin1().data(), k); b += k; } ++i; if(i == recordCountDbfPortion) { fileStream.writeRawData(buf, i * hdr->recordSize); i = 0; b = buf; } next(); } // while if(i > 0){ fileStream.writeRawData(buf, i * hdr->recordSize); } term = 0x1A; // Завершающий символ конца файла fileStream.writeRawData(&term, sizeof(char)); } catch(QDBError & e) { blockSignals( false ); if(hdr != NULL) free(hdr); if(fld != NULL) free(fld); if(buf != NULL) free(buf); file.close(); file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::WriteGroup | QFile::ReadOther | QFile::WriteOther); throw e; } blockSignals( false ); if(hdr != NULL) free(hdr); if(fld != NULL) free(fld); if(buf != NULL) free(buf); file.close(); file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::WriteGroup | QFile::ReadOther | QFile::WriteOther);}
p_fld->fieldLen[0] = Fields->Fields[i]->sqlSize();
unsigned int recordCountDbfPortion = 100;
for(i = 0, p_fld = fld, hdr->recordSize = 1; i < dbfFieldCount; ++i, ++p_fld) { str = headerItems.at(i).left(10);//header List memcpy(p_fld->fieldName, str.toLatin1().data(), str.length()); //just "C" fields for now p_fld->fieldType = 'C'; p_fld->fieldLen[0] = str.length();//which is 10 hdr->recordSize += (unsigned short) p_fld->fieldLen[0]; }
str = Fields->Fields[i]->fieldName().left(10);
p_fld->fieldLen[0]
first(); // Встаём на началоwhile( !isEof() ) // погнали по всем строкам от первой и до конца.{... next();}