找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 470|回复: 1

[每日一码] 一个查询DWG文件属性的类

[复制链接]

已领礼包: 40个

财富等级: 招财进宝

发表于 2017-2-6 10:52:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
//////////////////////////////////////////////////////////////////////////
// Реализация чтения 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[32767];
                        wchar_t w[32767];
                };
        };

public:

        DwgProps() {
                for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames[0]); 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[0].c_str(); }
        const char *subject()        const    {return m_stdProps[1].c_str(); }
        const char *author()         const    {return m_stdProps[2].c_str(); }
        const char *keywords()       const    {return m_stdProps[3].c_str(); }
        const char *comments()       const    {return m_stdProps[4].c_str(); }
        const char *lastSavedBy()    const    {return m_stdProps[5].c_str(); }
        const char *revisionNumber() const    {return m_stdProps[6].c_str(); }
        const char *hyperlinkBase()  const    {return m_stdProps[7].c_str(); }
        const char *customName(int idx) const  {
                return ((idx >= 0 && idx < (int)m_custPropNames.size())?m_custPropNames[idx].c_str():0);
        }
        const char *customValue(int idx) const {
                return ((idx >= 0 && idx < (int)m_custPropValues.size())?m_custPropValues[idx].c_str():0);
        }
        const char *customValue(const char *name) const  {
                for (int i=0; i < (int)m_custPropNames.size(); i++) {
                        if (m_custPropNames[i] == name) return m_custPropValues[i].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[32767]; memset(buf,0,sizeof(buf));
                if ((h = _open(fname,_O_BINARY|_O_RDONLY)) == -1)
                        return 0;
                char ACADVER[7];
                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[0]); 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[i] = buf;
                        } else {
                                m_stdProps[i] = 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[8];
        byte bCreateDateTime[8];
        byte bModifiedDateTime[8];
        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 [file ...]\n");
//    return;
//  }
//
//  //  loop over files
//  for ( int f = 1; f < argc; f++ )
//  {
//    printf("%s\n", argv[f]);
//
//    if ( p.load(argv[f]) )
//    {
//      //  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)));
//      }
//    }
//  }
//}

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-5 18:25 , Processed in 0.170978 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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