admin 发表于 2024-3-14 20:16:23

[每日一码] 一个查询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]
查看完整版本: [每日一码] 一个查询DWG文件属性的类