2010-06-17 12 views
6

पर्ल में, क्या एक स्ट्रिंग का उपयोग बाइट सरणी के रूप में 8-बिट डेटा युक्त करना उचित है? इस विषय पर मैं जो दस्तावेज पा सकता हूं वह 7-बिट तारों पर केंद्रित है।पर्ल में, क्या मैं एक स्ट्रिंग को बाइट सरणी के रूप में देख सकता हूं?

उदाहरण के लिए, अगर मैं $data

my $data; 

open FILE, "<", $filepath; 
binmode FILE; 
read FILE $data 1024; 

में एक बाइनरी फ़ाइल से कुछ डेटा पढ़ सकते हैं और मैं पहली बार बाइट बाहर निकलना चाहते हैं, substr($data,1,1) उचित है? (फिर, मान लीजिए कि यह 8-बिट डेटा है)

मैं ज्यादातर सी पृष्ठभूमि से आया हूं, और मुझे char पॉइंटर read() फ़ंक्शन पर पास करने के लिए उपयोग किया जाता है। मेरी समस्या यह हो सकती है कि मुझे समझ में नहीं आता कि स्ट्रिंग का अंतर्निहित प्रतिनिधित्व पर्ल में क्या है।

उत्तर

6

read आदेश, यहाँ reproduced के लिए संग्रहित प्रलेखन, जानकारी का एक बहुत कुछ है कि अपने प्रश्न के लिए प्रासंगिक है प्रदान करता है।

read FILEHANDLE,SCALAR,LENGTH,OFFSET

read FILEHANDLE,SCALAR,LENGTH

प्रयास निर्दिष्ट filehandle से चर SCALAR में लंबाई वर्ण डेटा के पढ़ने के लिए। वर्णों की संख्या वास्तव में पढ़ी जाती है, 0 फ़ाइल के अंत में, या त्रुटि होती है (बाद के मामले में $! भी सेट है)। SCALAR उगाया जा सकता है या संकुचित हो सकता है ताकि पढ़ने के बाद स्केलर के अंतिम चरित्र वास्तव में पढ़ सकें।

शुरुआत के अलावा स्ट्रिंग में किसी स्थान पर पढ़ने के डेटा को रखने के लिए एक ऑफ़सेट निर्दिष्ट किया जा सकता है। एक नकारात्मक ऑफ़सेट स्ट्रिंग के अंत से पीछे की गणना करने वाले कई पात्रों पर प्लेसमेंट निर्दिष्ट करता है। की तुलना में सकारात्मक सकारात्मक परिणाम पर स्ट्रिंग में परिणाम को पढ़ने के परिणाम से पहले \ 0 "बाइट्स के साथ आवश्यक आकार जोड़ा गया है।

कॉल वास्तव में पर्ल या सिस्टम के फ़्रेड() कॉल के संदर्भ में लागू किया जाता है। एक वास्तविक पढ़ने (2) सिस्टम कॉल प्राप्त करने के लिए, "sysread" देखें।

नोट पात्रों: filehandle की स्थिति पर निर्भर करता है, या तो (8 बिट) बाइट या वर्णों को पढ़ने जाते हैं।डिफ़ॉल्ट रूप से सभी फ़ाइल हैंडल बाइट्स पर काम करते हैं, लेकिन उदाहरण के लिए यदि फ़ाइल हैंडल ": utf8" I/O परत ("खुला" देखें, और "खुला" प्रज्ञा, खुला) के साथ खोला गया है, I/ओ यूटीएफ -8 एन्कोडेड यूनिकोड वर्णों पर काम करेगा, बाइट्स नहीं। इसी प्रकार "एन्कोडिंग" प्रज्ञा के लिए: उस मामले में बहुत अधिक वर्ण पढ़े जा सकते हैं।

+1

मेरी प्रकृति बहुत ही पैडेंटिक है, जब मैंने इसे प्रलेखन में पढ़ा तो मुझे 'चरित्र' अस्पष्ट मिला। मैं अस्पष्ट था अगर इसका मतलब डेटा की एक इकाई (यानी, एक बाइट) या स्ट्रिंग की एक इकाई (एन्कोडिंग पर निर्भर) – Mike

+4

कॉलिंग 'बिनमोड फ़ाइल, ": कच्ची" '' 'बिनमोड फ़ाइल,": बाइट्स "हमेशा अपनी डिफ़ॉल्ट आईओ परत के बावजूद, अपने बाइटहेडल को "बाइट्स" मोड में खोलें (कहें, अगर आपने 'utf8' का उपयोग किया है)। – mob

+0

मैं वास्तव में सहमत हूं कि "वर्ण" का उपयोग मुझे एक बग की तरह पढ़ता है, विशेष रूप से यह दिया गया है कि 'एनकोड (3perl)' में वर्ण, बाइट्स और ऑक्टेट्स के बीच भेद को कितना ध्यान दिया जाता है। यह सही शब्द होता है, लेकिन मुझे लगता है कि मुझे यह पसंद आएगा अगर यह "वर्ण (जैसा कि वर्तमान I/O परत द्वारा परिभाषित किया गया है)"। मुझे लगता है कि यह आपके उत्तर की भी आलोचना है, क्योंकि 'रीड' हमेशा "अक्षर" पढ़ता है - लेकिन कभी-कभी "चरित्र" को "ऑक्टेट" के रूप में परिभाषित किया जाता है और कभी-कभी "यूटीएफ -8 कोड पॉइंट" के रूप में परिभाषित किया जाता है। – darch

1

यदि आप बाइनरी फ़ाइल से बाइट्स पढ़ना चाहते हैं तो शायद आप sysopen और sysread का उपयोग करना चाहते हैं।

perlopentut भी देखें।

चाहे यह उचित या आवश्यक हो, आप वास्तव में क्या करने की कोशिश कर रहे हैं इस पर निर्भर करता है।

#!/usr/bin/perl -l 

use strict; use warnings; 
use autodie; 

use Fcntl; 

sysopen my $bin, 'test.png', O_RDONLY; 
sysread $bin, my $header, 4; 

print map { sprintf '%02x', ord($_) } split //, $header; 

आउटपुट:

C:\Temp> t 
89504e47
0

यदि आप हमें बताते हैं कि आप बाइट सरणी के साथ क्या करने का प्रयास कर रहे हैं तो यह और अधिक मदद कर सकता है। द्विआधारी डेटा के साथ काम करने के कई तरीके हैं, और प्रत्येक अपने आप को विभिन्न उपकरणों के सेट में उधार देता है।

क्या आप डेटा को एक पर्ल सरणी में परिवर्तित करना चाहते हैं? यदि ऐसा है, तो pack और unpack अच्छी शुरुआत है। split भी काम में आ सकता है।

क्या आप इसे बिना अनपॅक किए स्ट्रिंग के अलग-अलग तत्वों तक पहुंचना चाहते हैं? यदि ऐसा है, तो substr तेज है और 8 बाइट डेटा के लिए चाल करेगा। यदि आप अन्य बिट गहराई चाहते हैं, तो vec फ़ंक्शन पर नज़र डालें, जो एक बिट वेक्टर के रूप में स्ट्रिंग को चलाता है।

क्या आप स्ट्रिंग स्कैन करना चाहते हैं और कुछ बाइट्स को अन्य बाइट्स में कनवर्ट करना चाहते हैं? फिर s/// या tr/// संरचनाएं उपयोगी हो सकती हैं।

0

मुझे केवल बाइनरी सरणी के रूप में स्ट्रिंग के इलाज के बारे में एक छोटा सा उदाहरण पोस्ट करने की अनुमति दें - क्योंकि मुझे स्वयं यह मानना ​​मुश्किल लगता है कि "सबस्ट्र" नामक कुछ शून्य बाइट्स को संभालेगा; लेकिन मालूम होता है यह करता है - नीचे एक पर्ल डिबगर टर्मिनल सत्र का एक टुकड़ा (दोनों स्ट्रिंग और सरणी/सूची के साथ दृष्टिकोण) है:

$ perl -d 

Loading DB routines from perl5db.pl version 1.32 
Editor support available. 

Enter h or `h h' for help, or `man perldebug' for more help. 

^D 
Debugged program terminated. Use q to quit or R to restart, 
    use o inhibit_exit to avoid stopping after program termination, 
    h q, h R or h o to get additional info. 

    DB<1> $str="\x00\x00\x84\x00" 

    DB<2> print $str 
� 
    DB<3> print unpack("H*",$str) # show content of $str as hex via `unpack` 
00008400 
    DB<4> $str2=substr($str,2,2) 

    DB<5> print unpack("H*",$str2) 
8400 
    DB<6> $str2=substr($str,1,3) 

    DB<7> print unpack("H*",$str2) 
008400 

[...] 

    DB<30> @stra=split('',$str); print @stra # convert string to array (by splitting at empty string) 
� 
    DB<31> print unpack("H*",$stra[3]) # print indiv. elems. of array as hex 
00 
    DB<32> print unpack("H*",$stra[2]) 
84 
    DB<33> print unpack("H*",$stra[1]) 
00 
    DB<34> print unpack("H*",$stra[0]) 
00 
    DB<35> print unpack("H*",join('',@stra[1..3])) # print only portion of array/list via indexes (using flipflop [two dots] operator) 
008400 
1

स्ट्रिंग्स "वर्ण" है, जो एक बाइट से भी बड़ा कर रहे हैं के तार कर रहे हैं। 1 आप उनमें बाइट्स स्टोर कर सकते हैं और उन्हें कुशल बना सकते हैं जैसे कि वे पात्र हैं, substr उनमें से हैं और इतने पर, और जब तक आप स्मृति में इकाइयों को जोड़ते हैं, तो सबकुछ सुंदर आड़ू है। डेटा भंडारण अजीब है, लेकिन यह ज्यादातर आपकी समस्या नहीं है। 2

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

यह काफी दूर है, क्योंकि बड़े पैमाने पर एन्कोडिंग एक बड़ा और भ्रमित विषय है। मुझे कुछ संदर्भों के साथ इसे छोड़ने दें: Encode(3perl), open(3perl), perldoc open, और perldoc binmode पर बहुत सारे उल्लसित और गहरी विवरणों के लिए देखें।

तो सारांश का जवाब है "हां, आप स्ट्रिंग्स का इलाज कर सकते हैं जैसे कि वे बाइट्स रखते हैं, यदि वे वास्तव में बाइट्स रखते हैं, जिसे आप बाइट्स को पढ़ने और लिखकर आश्वस्त कर सकते हैं।"

1: या पैडेंटिक रूप से, "जो बाइट की तुलना में मूल्यों की एक बड़ी श्रृंखला व्यक्त कर सकता है, हालांकि जब यह सुविधाजनक है तब बाइट्स के रूप में संग्रहीत किया जाता है"। मुझे लगता है।

2: रिकॉर्ड के लिए, पर्ल में तारों को आंतरिक रूप से 'पीवी' नामक डेटा संरचना द्वारा दर्शाया जाता है, जो एक चरित्र सूचक के अलावा स्ट्रिंग की लंबाई और pos के वर्तमान मूल्य की तरह चीजें जानता है। 3

3: ठीक है, यह दिलचस्प होने पर pos के वर्तमान मूल्य को संग्रहीत करना शुरू कर देगा। यह भी देखें

use Devel::Peek; 

my $x = "bluh bluh bluh bluh"; 
Dump($x); 
$x =~ /bluh/mg; 
Dump($x); 
$x =~ /bluh/mg; 
Dump($x); 
संबंधित मुद्दे

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