2009-04-09 8 views
26

में 'स्ट्रिंग' के लिए TMemoryStream परिवर्तित हम पहले डेल्फी 2009 तक निम्नलिखित कोड था:डेल्फी 2009

<span style="font: 10pt Courier New;"><span class="pas1-reservedword">function</span><span class="pas1-space"> </span><span class="pas1-identifier">MemoryStreamToString(M:</span><span class="pas1-space"> </span><span class="pas1-identifier">TMemoryStream):</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">; 
</span><span class="pas1-reservedword">var 
</span><span class="pas1-space"> </span><span class="pas1-identifier">NewCapacity:</span><span class="pas1-space"> </span><span class="pas1-identifier">Longint; 
</span><span class="pas1-reservedword">begin 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(M.Size</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0)</span><span class="pas1-space"> </span><span class="pas1-reservedword">or</span><span class="pas1-space"> </span><span class="pas1-symbol">(M.Memory</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then 
</span><span class="pas1-space"> </span><span class="pas1-identifier">Result:=</span><span class="pas1-space"> </span><span class="pas1-string">'' 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">else 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-identifier">TMemoryStreamProtected(M).Capacity</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-identifier">M.Size</span><span class="pas1-space"> </span><span class="pas1-reservedword">then 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">begin 
</span><span class="pas1-space">  </span><span class="pas1-identifier">NewCapacity:=</span><span class="pas1-space"> </span><span class="pas1-identifier">M.Size+1; 
</span><span class="pas1-space">  </span><span class="pas1-identifier">TMemoryStreamProtected(M).Realloc(NewCapacity); 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; 
</span><span class="pas1-space"> </span><span class="pas1-identifier">NullString(M.Memory^)[M.Size]:=</span><span class="pas1-space"> </span><span class="pas1-character">#0; 
</span><span class="pas1-space"> </span><span class="pas1-identifier">Result:=</span><span class="pas1-space"> </span><span class="pas1-identifier">StrPas(M.Memory); 
</span><span class="pas1-space"> </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; 
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">; 
</span></span> 

हम डेल्फी 2009 के साथ अब यूनिकोड समर्थन करने के लिए इस कोड को कैसे परिवर्तित कर सकते हैं?

उत्तर

62

आपके पास जो कोड है वह पुराने डेल्फी संस्करणों के लिए भी अनावश्यक रूप से जटिल है। एक धारा बल के स्ट्रिंग संस्करण को क्यों लाया जाना चाहिए, स्ट्रीम की स्मृति को फिर से आवंटित किया जाना चाहिए?

function MemoryStreamToString(M: TMemoryStream): string; 
begin 
    SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char)); 
end; 

बस इतना ही डेल्फी संस्करणों में काम करता है, न सिर्फ डेल्फी 2009 यह काम करता है जब धारा किसी विशेष मामले के बिना खाली है। SetString एक कम सराहनीय समारोह है।

अपनी स्ट्रीम की सामग्री को डेल्फी 2009 तक अपने स्विच के साथ यूनिकोड को नहीं बदल रहे हैं, तो आप के बजाय इस समारोह का उपयोग करना चाहिए:

function MemoryStreamToString(M: TMemoryStream): AnsiString; 
begin 
    SetString(Result, PAnsiChar(M.Memory), M.Size); 
end; 

कि अपने मूल कोड के बराबर है, लेकिन विशेष मामलों को छोड़ देता है ।

+1

मैंने बहुत सारे डेल्फी मेमोरी सामान किए हैं, लेकिन मैंने सेटस्ट्रिंग के बारे में नहीं सुना था, हमेशा सेटलेथेंथ (dest, length) और मूव (src, @ (dest [1]), लंबाई का उपयोग किया जाता है); जो सेटस्ट्रिंग भी करता है (यह _LStrFromPCharLen को कॉल करता है) –

+0

इसे किसी पीसीहर में टाइपकास्टिंग करने से कोई समस्या नहीं होनी चाहिए। –

+0

सूचक सब कुछ के साथ संगत है। टाइप-कास्ट करने के लिए आपको एकमात्र कारण यह है कि यदि संकलक को ओवरलोड रिज़ॉल्यूशन के साथ परेशानी होती है। –

2

मैं अब तक अपग्रेड नहीं किया है, लेकिन मेरी समझ है:

NewCapacity := (M.Size + 1) * SizeOf(Char); 
16

या शायद आप अपने कोड सीधे एक TStringStream सीधे उपयोग करने के लिए refactor कर सकते हैं? आप इसे TMemoryStream के बजाय उपयोग कर सकते हैं (उनके पास एक ही इंटरफ़ेस है) और आप इसे myString: = myStringStream.DataString को कॉल करके इसे एक स्ट्रिंग में 'रूपांतरित' कर सकते हैं;

+1

दरअसल, यह पहली बात थी जो दिमाग में आई थी। TStringStream क्यों न बनाएं, इसमें मेमोरीस्ट्रीम लोड करें, और डेटास्ट्रिंग वापस करें? –

12

एक "स्वच्छ" जिस तरह से हो सकता है:

function StreamToString(aStream: TStream): string; 
var 
    SS: TStringStream; 
begin 
    if aStream <> nil then 
    begin 
    SS := TStringStream.Create(''); 
    try 
     SS.CopyFrom(aStream, 0); // No need to position at 0 nor provide size 
     Result := SS.DataString; 
    finally 
     SS.Free; 
    end; 
    end else 
    begin 
    Result := ''; 
    end; 
end; 
+0

"aStream.Position: = 0" की आवश्यकता नहीं है जैसे कि आप "SS.CopyFrom (aStream, 0)" कहते हैं, यह स्रोत को 0 पर रखेगा और आपके लिए आकार प्राप्त करेगा। – jonjbar

+0

ठीक है, काफी उचित है। –

+6

आपको डी 2009 + में 'टीस्ट्रिंगस्ट्रीम' से सावधान रहना होगा, क्योंकि यह अब 'टीनकोडिंग' है-अब जागरूक है। 'CopyFrom()' स्रोत 'TStream' के कच्चे बाइट्स की प्रतिलिपि बनायेगा, लेकिन' डेटास्ट्रिंग 'प्रॉपर्टी गेटर' टीस्ट्रिंग स्ट्रीम 'कन्स्ट्रक्टर ('TEncoding.Default' को जो भी 'TEncoding' पास किया गया है, का उपयोग करके उन बाइट्स को डीकोड करेगा। या डिफ़ॉल्ट रूप से 'TEncoding.UTF8', आईआईआरसी)। इसलिए यदि 'TStream' एन्कोडिंग' TStringStream' एन्कोडिंग से मेल नहीं खाती है, तो आपको डेटा हानि/भ्रष्टाचार मिलेगा। –

3

मैं का उपयोग करें:

function StreamToString(const Stream: TStream; const Encoding: TEncoding): string; 
var 
    StringBytes: TBytes; 
begin 
    Stream.Position := 0; 
    SetLength(StringBytes, Stream.Size); 
    Stream.ReadBuffer(StringBytes, Stream.Size); 
    Result := Encoding.GetString(StringBytes); 
end; 

यह केवल डेल्फी XE7 साथ परीक्षण किया गया है।

+0

'टीबीइट्स 'गतिशील सरणी है।'ReadBuffer()' का पहला पैरामीटर एक untyped 'var' है 'ReadBuffer()' को पास करने के लिए सही मेमोरी पता प्राप्त करने के लिए आपको' TBytes' को अस्वीकार करने की आवश्यकता है, उदाहरण के लिए: 'ReadBuffer (स्ट्रिंगबाइट्स [0], .. ।) 'या सुरक्षित' रीडबफर (पीबीटीई (स्ट्रिंगबाइट्स) ^, ...) 'जब' आकार' 0 है। –

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