[每日一码] 一个查询DWG文件属性的类
//////////////////////////////////////////////////////////////////////////// Реализация чтения DwgProps для AutoCAD 2004...2016 (возможно и дальше,
// если сохранится структура dwg-файла).
//////////////////////////////////////////////////////////////////////////
#include <io.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdlib.h>
#include <vector>
#include <string>
//
// Имена стандартных свойств чертежа
//
const char *stdPropNames[] = {
"title",
"subject",
"author",
"keywords",
"comments",
"lastSavedBy",
"revisionNumber",
"hyperlinkBase"
};
class DwgProps
{
struct record {
WORD len;
union {
char c;
wchar采用t w;
};
};
public:
DwgProps() {
for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames); i++){
m采用stdProps.push采用back("");
}
memset(bTotalEditingTime,0,sizeof(bTotalEditingTime));
memset(bCreateDateTime,0,sizeof(bCreateDateTime));
memset(bModifiedDateTime,0,sizeof(bModifiedDateTime));
};
~DwgProps() {}
//data items
const char *title() const {return m采用stdProps.c采用str(); }
const char *subject() const {return m采用stdProps.c采用str(); }
const char *author() const {return m采用stdProps.c采用str(); }
const char *keywords() const {return m采用stdProps.c采用str(); }
const char *comments() const {return m采用stdProps.c采用str(); }
const char *lastSavedBy() const {return m采用stdProps.c采用str(); }
const char *revisionNumber() const {return m采用stdProps.c采用str(); }
const char *hyperlinkBase()const {return m采用stdProps.c采用str(); }
const char *customName(int idx) const{
return ((idx >= 0 && idx < (int)m采用custPropNames.size())?m采用custPropNames.c采用str():0);
}
const char *customValue(int idx) const {
return ((idx >= 0 && idx < (int)m采用custPropValues.size())?m采用custPropValues.c采用str():0);
}
const char *customValue(const char *name) const{
for (int i=0; i < (int)m采用custPropNames.size(); i++) {
if (m采用custPropNames == name) return m采用custPropValues.c采用str();
}
return 0;
}
int customNumber() const { return (int) m采用custPropNames.size(); }
ULONG inDwg() { return ReadDiffDate(bTotalEditingTime); }
SYSTEMTIME created() { return ReadDate(bCreateDateTime); }
SYSTEMTIME updated() { return ReadDate(bModifiedDateTime); }
const void DateToString(char *buf, SYSTEMTIME tm)
{
sprintf( buf,
"%d-%02d-%02d %02d:%02d:%02d.%03d",
tm.wYear, tm.wMonth, tm.wDay,
tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds);
}
const void DiffDateToString(char *buf, ULONG tDiff)
{
int days = tDiff / (24*60*60*1000);
tDiff -= days * (24*60*60*1000);
int hours = tDiff / (60*60*1000);
tDiff -= hours * (60*60*1000);
int minutes = tDiff / (60*1000);
tDiff -= minutes * (60*1000);
int seconds = tDiff / 1000;
tDiff -= seconds * (1000);
int mseconds = tDiff;
sprintf( buf,
"Days:%d Hours:%d Minutes:%d Seconds:%d Milliseconds:%d",
days, hours, minutes, seconds, mseconds);
}
int load(const char * fname)
{
bool unicode = false;
int h;
char buf; memset(buf,0,sizeof(buf));
if ((h = 采用open(fname,采用O采用BINARY|采用O采用RDONLY)) == -1)
return 0;
char ACADVER;
if (采用read(h,ACADVER,sizeof(ACADVER)) <= 0) {
采用close(h); return 0;
}
if (atoi(ACADVER+2) < 1018) {// AutoCAD R14,2000...2002 обрабатывать не будем
采用close(h); return 0;
}
if (atoi(ACADVER+2) >= 1021) { // AutoCAD 2007... строки в Unicode
unicode = true;
}
// Указатель перемещаем на WORD, содержащий смещение DwgProps
if (采用lseek(h,0x20,SEEK采用SET) == -1) {
采用close(h); return 0;
}
// Считываем смещение DwgProps
WORD offset采用dwgprops = 0;
if (采用read(h,&offset采用dwgprops,sizeof(offset采用dwgprops)) <= 0) {
采用close(h); return 0;
}
long begin采用offset = offset采用dwgprops, cur采用offset = offset采用dwgprops;
// Устанавливаем указатель на начало DwgProps
if (采用lseek(h,offset采用dwgprops,SEEK采用SET) == -1) {
采用close(h); return 0;
}
// Теперь можно читать длины и сами строки:
record rec;
for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames); i++) {
if (采用read(h,&rec,sizeof(record)) == -1) {
采用close(h); return 0;
}
if (unicode) {
WideCharToMultiByte(CP采用ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
m采用stdProps = buf;
} else {
m采用stdProps = rec.c;
}
cur采用offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
if (采用lseek(h,cur采用offset,SEEK采用SET) == -1) {
采用close(h); return 0;
}
}
if (采用read(h,&bTotalEditingTime,sizeof(bTotalEditingTime)) == -1) {
采用close(h); return 0;
}
if (采用read(h,&bCreateDateTime,sizeof(bCreateDateTime)) == -1) {
采用close(h); return 0;
}
if (采用read(h,&bModifiedDateTime,sizeof(bModifiedDateTime)) == -1) {
采用close(h); return 0;
}
cur采用offset += (sizeof(bTotalEditingTime)+ sizeof(bCreateDateTime) + sizeof(bModifiedDateTime));
if (采用lseek(h,cur采用offset,SEEK采用SET) == -1) {
采用close(h); return 0;
}
// Читаем количество собственных (custom) переменных
WORD nCust = 0;
if (采用read(h,&nCust,sizeof(nCust)) <= 0) { 采用close(h); return 0; }
cur采用offset += sizeof(WORD);
for (int i=0; i < nCust; i++) {
// Считываем имя переменной
if (采用read(h,&rec,sizeof(record)) == -1) {采用close(h); return 0;}
if (unicode) {
WideCharToMultiByte(CP采用ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
m采用custPropNames.push采用back(buf);
} else {
m采用custPropNames.push采用back(rec.c);
}
cur采用offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
if (采用lseek(h,cur采用offset,SEEK采用SET) == -1) {
采用close(h); return 0;
}
if (采用read(h,&rec,sizeof(record)) == -1) {采用close(h); return 0;}
if (unicode) {
WideCharToMultiByte(CP采用ACP,0,rec.w,rec.len,buf,rec.len,0,NULL);
m采用custPropValues.push采用back(buf);
} else {
m采用custPropValues.push采用back(rec.c);
}
cur采用offset += (rec.len*((unicode)?2:1) + sizeof(rec.len));
if (采用lseek(h,cur采用offset,SEEK采用SET) == -1) {采用close(h); return 0;}
}
采用close(h);
return 1;
}
private:
//data
std::vector<std::string> m采用stdProps;
std::vector<std::string> m采用custPropNames;
std::vector<std::string> m采用custPropValues;
byte bTotalEditingTime;
byte bCreateDateTime;
byte bModifiedDateTime;
SYSTEMTIME minDate, maxDate;
//
// Преобразование даты/времени из юлианского календаря
//
SYSTEMTIME FromJulian(ULONG days)
{
FILETIME fmin = {0, 0} , fmax = {0x7fffffff, 0xffffffff} ;
FileTimeToSystemTime(&fmin, &minDate);FileTimeToSystemTime(&fmax, &maxDate);
SYSTEMTIME s; memset(&s,0,sizeof(s));
if (days < 0x1a4452) return minDate;
if (days > 0x51fe2c) return maxDate;
int j = days + 32044;
int g = j / 146097;
int dg = j % 146097;
int c = (((dg / 36524) + 1) * 3) / 4;
int dc = dg - (c * 36524);
int b = dc / 1461;
int db = dc % 1461;
int a = (((db / 365) + 1) * 3) / 4;
int da = db - (a * 365);
int y = (((g * 400) + (c * 100)) + (b * 4)) + a;
int m = (((da * 5) + 308) / 153) - 2;
int d = (da - (((m + 4) * 153) / 5)) + 0x7a;
int year = (y - 4800) + ((m + 2) / 12);
int month = ((m + 2) % 12) + 1;
int day = d + 1;
s.wYear = year;
s.wMonth = month;
s.wDay = day;
s.wHour = 2;
s.wMinute = 0;
s.wSecond = 0;
s.wDayOfWeek = 0;
s.wMilliseconds = 0;
return s;
}
//
// Добавление дробной части (миллисекунд)
//
SYSTEMTIME addMilliSecs(SYSTEMTIME s, double mseconds) {
FILETIME f; SystemTimeToFileTime(&s, &f);
ULARGE采用INTEGER u;
memcpy(&u, &f, sizeof(u));
ULONGLONG mmsec = mseconds * 10000;
u.QuadPart += mmsec;
memcpy(&f, &u, sizeof(f));
FileTimeToSystemTime(&f, &s);
return s;
}
//
// Чтение даты/времени
//
const SYSTEMTIME ReadDate(byte *src)
{
ULONG days = *((ULONG *)(src)); src += 4;
ULONG fraction = *((ULONG *)(src)); src += 4;
SYSTEMTIME tm = FromJulian(days);
if (tm.wYear == maxDate.wYear)
return tm;
return addMilliSecs(tm,fraction);
}
//
// Чтение интервала редактирования
//
const ULONG ReadDiffDate(byte* src)
{
ULONG days = *((ULONG *)(src)); src += 4;
ULONG fraction = *((ULONG *)(src)); src += 4;
ULONG diff = days * 24 * 60 * 60 * 1000 + fraction;
return diff;
}
};
////-----------------------------------------
//// Пример использования класса DwgProps
////-----------------------------------------
//#include "stdafx.h"
//#include <conio.h>
//#include <stdio.h>
//#include <string.h>
//#include <wtypes.h>
//#include <time.h>
//#include "DwgProps.h"
//
//
//const char * valid(const char *s)
//{
//return s ? s : "";
//}
//
//void main(int argc, char *argv[])
//{
//DwgProps p;
//
//if ( argc < 2 )
//{
// fprintf(stderr, "Usage: dwgprops file \n");
// return;
//}
//
////loop over files
//for ( int f = 1; f < argc; f++ )
//{
// printf("%s\n", argv);
//
// if ( p.load(argv) )
// {
// //print list of tags
// printf("Title: [%s]\n", valid(p.title()));
// printf("Subject: [%s]\n", valid(p.subject()));
// printf("Author: [%s]\n", valid(p.author()));
// printf("Comments: [%s]\n", valid(p.comments()));
// printf("Keywords: [%s]\n", valid(p.keywords()));
// printf("HyperlinkBase: [%s]\n", valid(p.hyperlinkBase()));
// printf("LastSavedBy: [%s]\n", valid(p.lastSavedBy()));
// printf("RevisionNo.: [%s]\n", valid(p.revisionNumber()));
// char buffer[ 256 ];
// p.DiffDateToString(buffer, p.inDwg());
// printf("Edit time: %s\n", buffer);
// p.DateToString(buffer, p.created());
// printf("Created: [%s]\n", buffer);
// p.DateToString(buffer, p.updated());
// printf("Updated: [%s]\n", buffer);
// for ( int i = 0; i < p.customNumber(); i++ ) {
// printf("Custom Name[%d]: [%s]\n", i, valid(p.customName(i)));
// printf("Custom Value[%d]:[%s]\n", i, valid(p.customValue(i)));
// }
// }
//}
//}
页:
[1]