2010-07-08 11 views
8

डेल्फी 7 से 2010 तक कोड परिवर्तित करते समय मुझे एक अजीब समस्या है। इसे रिकॉर्ड के साथ करना है। नीचे परिभाषित रिकॉर्ड, डी 7 में आकार दिया गया है, 432 बाइट्स है, और डी 200 9 (और 2010) में यह 496 है। मुझे पता है कि एक आसान समाधान यह एक पैक रिकॉर्ड बनाना है, तो सभी संस्करण 426 बाइट्स तक आते हैं ... हालांकि, हमारे पास डेटा संग्रहित है जहां हमने रिकॉर्ड स्ट्रीम किया था और अब हम उन धाराओं को एक नई भाषा के साथ पढ़ने की कोशिश कर रहे हैं।200 9 (और 2010) की तुलना में डेल्फी 7 रिकॉर्ड आकार

TToTry = Record 
a,b,c,d : Extended; 
e,f,g,h : Extended; 
i : String[15]; 
j,k,l,m,n,o,p,q,r,s,t : Array[1..3] of Extended; End; 

इस मुद्दे की जांच में, मैंने एक और रिकॉर्ड बनाया, और, किसी भी कारण से, आकार समान हैं? रिकॉर्ड छोटा है, लेकिन इसमें समान डेटा प्रकार हैं। लेकिन यह भाषा के सभी संस्करणों में एक ही आकार में आता है।

TMyRecord = Record 
Ext1 : Extended; 
Ext2 : Extended; 
Ext3 : Extended; 
Ext4 : Extended; 
Ext5 : Extended; 
Ext6 : Extended; 
Int1 : Integer; 
Int2 : Integer; 
char1 : AnsiChar; 
char2 : AnsiChar; 
MyString : String[15]; 
Arr1 : Array[1..3] of Extended; 
Arr2 : Array[1..3] of Extended; end; 

किसी के पास कोई अंतर्दृष्टि है कि एक रिकॉर्ड इतना अलग क्यों है, और दूसरा वही है? निश्चित रूप से डेल्फी में बाइट सीमा संरेखण के साथ कुछ करना है। लेकिन एक संस्करण से अगले संस्करण में इतनी तेजी से क्या बदल गया?

+0

मुझे पता है कि डेल्फी रिकॉर्ड के लिए डिफ़ॉल्ट बाइट संरेखण हाल के संस्करण में बदल गया है (200 9 मुझे लगता है) लेकिन मुझे विवरणों के बारे में निश्चित नहीं है। –

उत्तर

2

मुझे विश्वास है कि डिफ़ॉल्ट संरेखण व्यापक बना दिया गया था। बाद के संस्करणों में संरेखण 4 निर्दिष्ट करें और देखें कि यह आपके इच्छित तरीके से बाहर आता है या नहीं।

भविष्य के लिए आपको यह सुनिश्चित करना चाहिए कि डिस्क पर लिखे जाने वाले किसी भी रिकॉर्ड को पैक किया गया है ताकि आप इस तरह से जला नहीं जाएंगे।

संपादित करें: चूंकि संरेखण में से कोई भी काम नहीं करता है (जो मुझे आश्चर्यचकित करता है) मैं मूल पर वापस जाऊंगा और यह समझ सकता हूं कि यह वास्तव में कैसे गठबंधन किया गया है। रिकॉर्ड को $ एफएफ जैसे कुछ भरें, डेटा डालें और इसे लिखें - देखें कि $ एफएफ कहाँ से बच गए। नया रिकॉर्ड लें, इसे पैक करें और पुराने रिकॉर्ड में पैडिंग से मेल खाने के लिए फिलर्स जोड़ें।

एक बात: क्या यह वास्तव में केवल एक रिकॉर्ड है? पुराने दिनों में मैंने वस्तुओं को विरासत के साथ नकली रिकॉर्ड के रूप में उपयोग किया है - ओह, विरासत के बिंदु पर सामान्य संरेखण लागू किया गया था और मैं इसे रोक नहीं सका। मजबूर संरेखण को मेरे डेटा को तोड़ने के लिए डेटा से पहले पैड करने के लिए समाप्त हो गया। (यह एक एपीआई के लिए जा रहा था, यह था सही हो सकता है, मैं क्षेत्रों को स्वतंत्र रूप से क्रियान्वित नहीं कर सके।)

+0

एक "संरेखण निर्दिष्ट करें" कैसे करता है? –

+0

इसे मिला: {$ ए 4}। लेकिन यह मदद नहीं की। संख्या अब 464 है। मैंने अन्य सभी {$ ए?} संभावनाओं और किसी भी मैच की कोशिश नहीं की। –

14

ठीक है, पहली समस्या यह है कि आप डिस्क के लिए एक गैर-पैक रिकॉर्ड संग्रहीत है। उत्पाद रिलीज़ के बीच फ़ील्ड और सरणी पैकिंग को बदलने की अनुमति है क्योंकि आम तौर पर स्मृति में लेआउट प्रक्रिया के बाहर दिखाई नहीं देता है। आपने उस नियम को तोड़ दिया है।

बाइट गद्दी चूक डेल्फी 7 और डेल्फी 2009 के बीच बदल गया है, क्या चूक D7 में थे पता लगाना और डेल्फी 2009

में एक ही करने के लिए डिफ़ॉल्ट सेट करते हैं इसके अलावा सरणी पैकिंग डिफ़ॉल्ट की जाँच करें। मुझे याद नहीं है कि इसके लिए एक अलग सेटिंग है या नहीं।

डेबग मेमोरी व्यू में डेल्फी 200 9 में अपनी रिकॉर्ड संरचना पर नज़र डालें। कुछ या सभी अतिरिक्त आकार रिकॉर्ड के पैडिंग के कारण हो सकते हैं (इसमें फ़ील्ड नहीं) ताकि जब किसी सरणी में रिकॉर्ड का उपयोग किया जाता है तो सरणी तत्व तेजी से मशीन सीमाओं पर होते हैं।

यदि इनमें से कोई भी मदद नहीं करता है, तो डी 2009 में एक अस्थायी पैक रिकॉर्ड प्रकार बनाएं और वास्तविक डेटा फ़ील्ड के बीच बाइट पैडिंग फ़ील्ड मैन्युअल रूप से डालें जब तक कि रिकॉर्ड आकार और फ़ील्ड संरेखण D7 लेआउट से मेल नहीं खाते। यह सिर्फ आकार नहीं है, यह क्षेत्र संरेखण है। इस अस्थायी पैक रिकॉर्ड का उपयोग करने में अपनी पुरानी डेटा फ़ाइल पढ़ें। फिर डेटा क्षेत्र को फ़ील्ड द्वारा अपने "वास्तविक" रिकॉर्ड प्रकार में डी 2009 में स्थानांतरित करें और एक नई फ़ाइल लिखें।

और जब आप इसमें हों, तो उस रिकॉर्ड प्रकार को डी 200 9 में पैक करें ताकि यह फिर से न हो।

+4

यह सब मानते हैं कि आपके पास डी 7 पर वापस जाने का विकल्प नहीं है और रिकॉर्ड संरचना को पैक करने और पैक किए गए रिकॉर्ड की एक फ़ाइल लिखने के लिए कोड को संशोधित करने का विकल्प नहीं है। तथ्य के बाद बाइट पैडिंग से मैन्युअल रूप से मिलान करने की कोशिश करने से कम काम होगा। – dthorpe

+0

हिंद दृष्टि हमेशा 20/20 है ... और आगे सोच विकास (और डेवलपर्स) हमेशा नहीं होता है। 2009/2010 के लिए रिक्त स्थान के साथ पैक किए गए रिकॉर्ड के बारे में अच्छा विचार। हम इसे आज़माएंगे। –

+8

हिंदसाइट भी शैक्षणिक होना चाहिए। फ़ाइल में अनपॅक किए गए रिकॉर्ड लिखना प्रति कैरियर में केवल एक बार होना चाहिए। ;> – dthorpe

7

मुझे विश्वास है कि आपने सुविधा पर हिट किया है! मुझे आपके TToTry के साथ D2007 के साथ उचित आकार नहीं मिला, इसलिए मुझे डीबगर के साथ फ़ील्ड पते देखना पड़ा;

सबसे पहले, नीचे रिकॉर्ड के आकार,

{$A8} 
type 
    TToTry = record 
    j: array[1..3] of Extended; 
    k: array[1..3] of Extended; 
    l: array[1..3] of Extended; 
    m: array[1..3] of Extended; 
    end; 

(32 * 4) है। इसकी उम्मीद है, क्योंकि Extended 10 बाइट्स है, 30 बाइट 32 बाइट्स पर संरेखित होंगे।

लेकिन इस रिकॉर्ड के आकार,

{$A8} 
type 
    TToTry = record 
    j, k, l, m: array[1..3] of Extended; 
    end; 

(30 * 4) है। यह निश्चित रूप से अप्रत्याशित है - फ़ील्ड्स को अभी भी 8 बाइट सीमा पर संरेखित करना चाहिए।

(बात की पुष्टि कैसे D7 नहीं है, लेकिन मेरी सोच
तो अब हम जानते हैं कि :) कि वर्गीकृत किया क्षेत्रों भरे होते हैं है, यह इस प्रकार है कि D7 पर संरेखण 8 बाइट्स है और अपने रिकॉर्ड लगभग पैक किया जाता है;

TToTry = Record 
a,b,c,d : Extended; // 40 bytes (8*5) 
e,f,g,h : Extended; // 40 bytes (8*5) 
i : String[15];  // 16 bytes (8*2) 
j,k,l,m,n,o,p,q,r,s,t: Array[1..3] of Extended; // 330 bytes 
End; 

संकलक यह 8 की एक बहु के लिए पिछले समूह के 6 बाइट्स padding है और फिर आप 40 + 40 + 16 + 336 = 432 बाइट्स मिलता है।

डी 2009/डी 2010 के साथ आप या तो प्रत्येक फ़ील्ड घोषित कर रहे हैं - उन्हें समूहित किए बिना, या व्यवहार बदल दिया गया है। किसी भी तरह से पैक पैक अपने रिकॉर्ड और अंत में 6 बाइट सरणी डमी फ़ील्ड जोड़ें, और आपको जाने के लिए अच्छा होना चाहिए।

यदि यह काम नहीं करता है, तो अपने रिकॉर्ड के फ़ील्ड पते को डी 7 के साथ देखें, फिर पैक किए गए रिकॉर्ड का उपयोग करके और डमी फ़ील्ड का उपयोग करके डी 2009 पर एक सटीक डुप्लिकेट बनाएं, जब आप अपना संग्रहीत डेटा आयात कर सकें डमी फ़ील्ड ड्रॉप करें।

-
मैंने कभी ऐसा व्यवहार नहीं ज्ञात है और मुझे इसे कहीं भी दस्तावेज नहीं मिल रहा है। फिर भी, यह एक ऐसी सुविधा की तरह है जो मुझे एक बग कहने में संकोच करता है। मुझे नहीं पता कि व्यवहार डी 2009 या डी 2010 के साथ समान है, यह देखने के लिए कि यह है या नहीं। यदि ऐसा है, तो अपेक्षित परिणाम प्राप्त करने के लिए - आधे पैक वाले रिकॉर्ड नहीं होने के लिए - आलसी मत बनें और गैर-पैक किए गए रिकॉर्ड के लिए प्रत्येक फ़ील्ड को अपने आप घोषित करें।

+0

डेल्फी 200 में दूसरे रिकॉर्ड का आकार 128 बाइट्स – kludg

+0

@ सर्ग है - इसे देखने के लिए धन्यवाद, इसलिए यह एक सुविधा नहीं है। वास्तव में मुझे डी 2007 के साथ परीक्षण करते समय अन्य अजीब/अप्रत्याशित संरेखण का सामना करना पड़ा। मुझे खुशी है कि बाद के संस्करणों में यह सीधे है! –

2

{$ A8} निर्देश लागू करने का मतलब यह नहीं है कि सभी रिकॉर्ड फ़ील्ड 8-बाइट सीमा पर गठबंधन हैं - शिकायतकर्ता एक अलग संरेखण रणनीति का उपयोग करता है। उदाहरण के लिए,

{$A8} 
type 
    TToTry = record 
    a: byte; 
    b: word; 
    c: longword; 
    end; 

के आकार, डेल्फी 2009 में 8 बाइट्स है क्योंकि संकलक 2-बाइट सीमा, 4 बाइट सीमा पर 4 बाइट मूल्य, और में केवल वास्तविक संरेखण पर 2-बाइट मूल्य संरेखित करता है उपर्युक्त उदाहरण बी फ़ील्ड 2-बाइट सीमा पर गठबंधन है।

मूल प्रश्न क्या डेल्फी 7 और डेल्फी 2009 के बीच बदल के लिए के रूप में - मैं जानता हूँ कि यह एक पुरानी पोस्ट है पढ़ Sertac Akyuz जवाब और यह

+0

आह, ठीक है! मेरे जवाब पर आपकी टिप्पणी के लिए मेरी टिप्पणी के साथ 'अजीब/अप्रत्याशित' का मतलब यही था। लेकिन क्या इसकी उम्मीद की जा सकती है? दस्तावेज़ कहते हैं: "{$ A8} या {$ A +} स्थिति में, रिकॉर्ड प्रकारों में फ़ील्ड जिन्हें पैक किए गए संशोधक के बिना घोषित किया जाता है और वर्ग संरचनाओं में फ़ील्ड क्वाड शब्द सीमाओं पर गठबंधन होते हैं।" –

+2

@Sertac: क्वाड शब्द संरेखण केवल उन डेटा प्रकारों पर लागू होता है जो लंबाई में कम से कम 8 बाइट हैं। एक 8 बाइट सीमा पर एक बाइट क्षेत्र डालकर x86 आर्किटेक्चर पर प्राप्त करने के लिए बहुत कुछ नहीं है। (यह एल 2 कैश में कैश लाइन टकराव के साथ मदद कर सकता है, लेकिन यह वास्तव में वास्तव में मामूली है)। सर्ग ने कहा, डेटा प्रकार $ ए/एन/आकार तक अपनी प्राकृतिक सीमा (= डेटा का आकार) को संरेखित करते हैं। ध्यान दें कि कई संरेखण बिंदुओं पर विचार करने के लिए: संरचना की शुरुआत से फ़ील्ड का ऑफसेट, सरणी के भीतर डेटा का संरेखण, और रिकॉर्ड के पैडिंग को किसी सरणी में उपयोग होने पर अच्छी तरह संरेखित करने के लिए स्वयं को संरेखित करने के लिए। – dthorpe

+1

@dthorpe - धन्यवाद, सभी समझ में आते हैं। लेकिन मैं चाहता हूं कि प्रलेखन में 'संरचित प्रकार' या 'संरेखित फ़ील्ड' विषय इस पर अधिक स्पष्ट हों, खासकर मेरे जैसे उन लोगों के लिए जिन्हें अंतर्निहित वास्तुकला का कोई ज्ञान नहीं है .. –

3

को मेरी टिप्पणी है, लेकिन मैं डेल्फी XE2 के साथ एक ही मुद्दा कल में भाग । मेरे पास कई टाइप की गई फ़ाइलें हैं जिन्हें टर्बो डेल्फी 2006 ऐप का उपयोग करके लिखा गया था और मैंने पैक किए गए रिकॉर्ड का उपयोग न करने की गलती भी की।मेरी स्थिति जटिल थी क्योंकि मैं परिवर्तनीय लंबाई रिकॉर्ड का उपयोग कर रहा था (यही वह है जिसे हम उन्हें z/OS दुनिया में कहते हैं, डेल्फी शब्द के 100% निश्चित नहीं), इसलिए गलत-संरेखण रिकॉर्ड कुंजी टैग को समाप्त नहीं कर रहा था सही क्षेत्र, इस प्रकार उप-अभिलेखों में से कोई भी सही जगह पर नहीं होने का कारण बनता है, जिससे पूरी फाइल बेकार हो जाती है।

जो मैंने पाया वह यह है कि आप कोड के एक विशिष्ट ब्लॉक के आसपास संरेखण कंपाइलर निर्देश डाल सकते हैं। {$OLDTYPELAYOUT ON}

{$OLDTYPELAYOUT ON} 
RMasterRecord = Record  
    mKey  : word; 
    mDeleted : boolean; 
    case mType : ANSIChar of 
     'V' : //Info 
      (Vers : RVersionLayout); 
     […] 
{$OLDTYPELAYOUT OFF} 

मैं केवल मास्टर रिकॉर्ड है कि लिखा हो जाता है चारों ओर निर्देश दिया और, फाइल करने के लिए पढ़ने के आसपास नहीं उप रिकॉर्ड परिभाषाएँ: कि के साथ, मैं भी इस छोटे से मणि की खोज की। इसने मेरी समस्या हल की, और अब मैं XE2 में संकलित कर सकता हूं और मेरी टीडी 2006 फाइलें पढ़ सकता हूं। अगली बार मैं पैक किए गए रिकॉर्ड (या बेहतर अभी तक, SQLite) का उपयोग करूंगा। लेकिन मैंने सोचा कि मैं इसे साझा करूंगा, क्योंकि इस साइट ने मुझे वर्षों से अनजाने में मदद की है।

आप यहां $ OLDTYPELAYOUT के बारे में अधिक पढ़ सकते हैं: http://docwiki.embarcadero.com/RADStudio/XE5/en/Internal_Data_Formats#Record_Types। वैसे, इसे तय करने वाला पहला व्यक्ति {$A4} था, लेकिन जब मैंने {$OLDTYPELAYOUT ON} की खोज की तो मैंने इसे उपयोग करने के लिए स्विच किया, क्योंकि यह अधिक स्पष्ट है।

संबंधित मुद्दे