2015-03-11 3 views
5

मेरी परियोजनाओं के हिस्से के रूप में, मेरे पास एक बाइनरी डेटा फ़ाइल है जिसमें 32 बिट पूर्णांक की एक बड़ी श्रृंखला शामिल है जो मेरी कक्षाओं में से एक प्रारंभिकरण में पढ़ता है। मेरी सी ++ लाइब्रेरी में, मैं इसे में पढ़ा निम्नलिखित प्रारंभकर्ता साथ:स्विफ्ट में, मैं एक मौजूदा बाइनरी फ़ाइल को सरणी में कैसे पढ़ूं?

Evaluator::Evaluator() { 
    m_HandNumbers.resize(32487834); 
    ifstream inputReader; 

    inputReader.open("/path/to/file/7CHands.dat", ios::binary); 

    int inputValue; 
    for (int x = 0; x < 32487834; ++x) { 
     inputReader.read((char *) &inputValue, sizeof (inputValue)); 
     m_HandNumbers[x] = inputValue; 
    } 
    inputReader.close(); 
}; 

और स्विफ्ट के लिए पोर्टिंग में, मैं (यह केवल 130 एमबी है) एक बफर में पूरी फ़ाइल को पढ़ने के लिए और फिर बाइट्स बाहर नकल का निर्णय लिया बफर का।

तो, मैं निम्नलिखित किया है:

public init() { 
    var inputStream = NSInputStream(fileAtPath: "/path/to/file/7CHands.dat")! 
    var inputBuffer = [UInt8](count: 32478734 * 4, repeatedValue: 0) 
    inputStream.open() 
    inputStream.read(&inputBuffer, maxLength: inputBuffer.count) 
    inputStream.close() 
} 

और यह है कि में ठीक काम करता है जब मैं इसे डिबग, मैं देख सकता inputBuffer कि मेरे हेक्स संपादक का कहना है कि यह होना चाहिए बाइट्स की एक ही सरणी में शामिल है। अब, मैं उस डेटा को प्रभावी ढंग से वहां से प्राप्त करना चाहता हूं। मुझे पता है कि यह संग्रहीत है .. आप जिस प्रारूप को कॉल करते हैं, जहां कम से कम महत्वपूर्ण बाइट्स पहले होते हैं (यानी 0x00011D4A को फ़ाइल में '4 ए 1 डी 0100' के रूप में दर्शाया जाता है)। मैं इसे मैन्युअल रूप से इसके माध्यम से फिर से चलाने और हाथ से बाइट मूल्यों की गणना करने का लुत्फ उठा रहा हूं, लेकिन मुझे आश्चर्य है कि अगर कोई त्वरित तरीका है तो मैं [Int32] की सरणी पास कर सकता हूं और इसे उन बाइट्स में पढ़ सकता हूं। मैंने NSData का उपयोग करने की कोशिश की, इस तरह के साथ के रूप में:

let data = NSData(bytes: handNumbers, length: handNumbers.count * sizeof(Int32)) 
    data.getBytes(&inputBuffer, length: inputBuffer.count) 

लेकिन यह है कि मूल्यों को लोड करने के लिए नहीं मालूम था (सभी मूल्यों अभी भी थे शून्य)। क्या कोई मुझे इस बाइट सरणी को कुछ Int32 मानों में परिवर्तित करने में मदद कर सकता है? बेहतर है कि उन्हें अभी भी मेरे वैरिएबल आकार को प्रोजेक्ट में रखने के लिए इंट (यानी 64 बिट पूर्णांक) में परिवर्तित करना होगा।

उत्तर

3

आपके एंडियन-नेस के बारे में निश्चित नहीं है, लेकिन मैं निम्न फ़ंक्शन का उपयोग करता हूं। आपके कोड से अंतर बाइट्स की लंबाई के बजाय वास्तविक आवश्यक प्रकार के NSRanges का उपयोग कर रहा है। यह दिनचर्या एक समय में एक मान पढ़ती है (यह ईएसआरआई फाइलों के लिए है जिनकी सामग्री फ़ील्ड द्वारा फ़ील्ड बदलती है), लेकिन आसानी से अनुकूल होना चाहिए।

func getBigIntFromData(data: NSData, offset: Int) -> Int { 
    var rng = NSRange(location: offset, length: 4) 
    var i = [UInt32](count: 1, repeatedValue:0) 

    data.getBytes(&i, range: rng) 
    return Int(i[0].bigEndian)// return Int(i[0]) for littleEndian 
} 
+0

मैंने उस फ़ंक्शन का उपयोग करने का प्रयास किया और मुझे शून्य के अलावा कुछ भी नहीं मिला। मुझे नहीं लगता कि data.getBytes कथन इनपुट बफर से डेटा को सही ढंग से लोड कर रहा है। आपका काम अच्छी तरह से काम कर सकता है लेकिन मुझे इस समय कोई जानकारी नहीं है। क्या आपको कोई कारण दिखाई देता है, क्योंकि मुझे पता है कि इनपुटबफर में गैर-शून्य हैं, मेरा डेटा क्यों है .getBytes कथन काम नहीं कर रहा है? – Charles

+1

'data.getBytes (& inputBuffer ...)' 'डेटा' से * पढ़ता है और इसे * * इनपुट बफर 'में रखता है, न कि दूसरी तरफ। आपको फ़ाइल को 'NSData' में पढ़ने की आवश्यकता है, फिर इसे सही आकार के पूर्णांक की सरणी में पढ़ें। – Grimxn

+0

इस पर आधारित, मैंने वास्तव में डेटा फ़ाइल के पथ के साथ डेटा को शुरू करने में काफी सरलता से चीजों को सरल बना दिया, अर्थात्: 'डेटा = NSData (contentOfFile: "/path/to/file/7CHands.dat") दें!'और यह डेटा को लोड करने तक एक आकर्षण की तरह काम करता प्रतीत होता है, फिर आपके फ़ंक्शन के लिए एक साधारण कॉल (थोड़ा इंडियन में, जैसा कि यह निकलता है) और सबकुछ जहाज-आकार है। हालांकि इसमें काफी समय लगता है, हालांकि रिलीज बिल्ड में भी, 9 0 या उससे अधिक समय लगता है जबकि सी ++ तात्कालिक था। क्या दोनों भाषाओं के बीच अंतर वास्तव में पर्याप्त है, या क्या मुझे कहीं बिल्डिंग सेटिंग याद आ रही है? – Charles

2

Grimxn मेरी समस्या है, जो मुझे दिखाया है कि कैसे एक सरणी में बफर के वर्गों को पढ़ने के लिए का हल की रीढ़ प्रदान की; फिर उसने मुझे पूरे बफर को एक बार में पढ़ने का एक तरीका दिखाया। सरणी के सभी आइटमों को Int पर असीमित रूप से परिवर्तित करने के बजाय, मैंने बस सरणी को UInt32 के रूप में बफर में पढ़ा और उस सरणी को एक्सेस करने वाले फ़ंक्शन में Int पर कास्टिंग किया।

अभी के लिए, क्योंकि मेरे पास अभी तक मेरी उपयोगिता श्रेणी परिभाषित नहीं है, इसलिए मैंने सीधे अपने प्रारंभिक में Grimxn कोड को एकीकृत किया है। वर्ग प्रारंभकर्ता अब इस तरह दिखता है:

public class Evaluator { 
    let HandNumberArraySize = 32487834 

    var handNumbers: [Int32] 

    public init() { 
     let data = NSData(contentsOfFile: "/path/to/file/7CHands.dat")! 
     var dataRange = NSRange(location: 0, length: HandNumberArraySize * 4) 
     handNumbers = [Int32](count: HandNumberArraySize, repeatedValue: 0) 
     data.getBytes(&handNumbers, range: dataRange) 

     println("Evaluator loaded successfully") 
    } 

... 

} 

... और समारोह के लिए उन्हें का संदर्भ देता है अब है: मुझे एक बहुत ही वास्तविक में मदद करने के लिए StackOverflow को

public func cardVectorToHandNumber(#cards: [Int], numberToUse: Int) -> Int { 
    var output: Int 

    output = Int(handNumbers[53 + cards[0] + 1]) 

    for i in 1 ..< numberToUse { 
     output = Int(handNumbers[output + cards[i] + 1]) 
    } 

    return Int(handNumbers[output]) 
} 

Grimxn के लिए धन्यवाद और एक बार फिर से धन्यवाद मार्ग!

+0

बढ़िया! अपने संदर्भ फ़ंक्शन के लिए सदस्यता प्रोटोकॉल देखें। यह जरूरी नहीं है, लेकिन यह चीजों को कम कर सकता है ... https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Subscripts.html – Grimxn

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