2011-12-21 22 views
9

मैं जावा के लिए बहुत नया हूं, और मेमोरी मैपिंग (प्रदर्शन सुधार की उम्मीद में) का उपयोग कर फ़ाइल तक पहुंचने के लिए मैथमैटिका के जावा इंटरफेस का उपयोग करने की कोशिश कर रहा हूं।मैपडबेट बफर का सरणी() विधि क्यों काम नहीं करती है?

मेथेमेटिका कोड मेरे पास है (मेरा मानना ​​है कि) निम्नलिखित जावा कोड (this के आधार पर) के बराबर है:

import java.io.FileInputStream; 
import java.nio.MappedByteBuffer; 
import java.nio.channels.FileChannel; 

public class MainClass { 
    private static final int LENGTH = 8*100; 

    public static void main(String[] args) throws Exception { 
    MappedByteBuffer buffer = new FileInputStream("test.bin").getChannel().map(FileChannel.MapMode.READ_ONLY, 0, LENGTH); 
    buffer.load(); 
    buffer.isLoaded(); // returns false, why? 
    } 
} 

मैं बफर पर array() विधि का उपयोग करना चाहते हैं, तो मैं लोड करने के लिए कोशिश कर रहा हूँ load() का उपयोग कर स्मृति में बफर सामग्री पहले। हालांकि, load() के बाद भी, isLoaded()false लौटाता है, और buffer.array() अपवाद फेंकता है: java.lang.UnsupportedOperationException at java.nio.ByteBuffer.array(ByteBuffer.java:940)

बफर लोड क्यों नहीं करता है और मैं array() विधि को कैसे कॉल कर सकता हूं?

मेरा अंतिम उद्देश्य asDoubleBuffer().array() का उपयोग करके double एस की एक सरणी प्राप्त करना है। विधि getDouble() सही ढंग से काम करता है, लेकिन मैं उम्मीद कर रहा था कि यह अच्छा प्रदर्शन के लिए एक बार में किया जाए। मैं क्या गलत कर रहा हूं?


जैसा कि मैंने मेथेमेटिका से यह कर रहा हूं, मैं मैं भी (बराबर जावा में ऊपर के लिए) का उपयोग किया वास्तविक मेथेमेटिका कोड पोस्ट करेंगे:

Needs["JLink`"] 
LoadJavaClass["java.nio.channels.FileChannel$MapMode"] 
buffer = JavaNew["java.io.FileInputStream", "test.bin"]@getChannel[]@map[FileChannel$MapMode`READUONLY, 0, 8*100] 

[email protected][] 
[email protected][] (* returns False *) 
+0

"झूठी वापसी का मूल्य यह इंगित नहीं करता है कि बफर की सामग्री भौतिक स्मृति में निवासी नहीं है।" 'लोड' केवल सर्वोत्तम प्रयास है, और वास्तव में डेटा को केवल भौतिक मेमोरी में लोड कर सकता है ताकि इसे तुरंत बाहर कर दिया जा सके। –

+0

@ टॉमहॉविन-टाइनलाइन मुझे लगता है कि मैंने 'लोड' के उद्देश्य को गलत समझा। मैं जो हासिल करना चाहता हूं वह बफर की सामग्री को युगल की सरणी के रूप में प्राप्त करना है। 'सरणी' विधि अनजाने में काम नहीं करती है, और मैंने जो अपवाद उल्लेख किया है उसे फेंकता है। मैंने यूयर फीडबैक के आधार पर प्रश्न अपडेट किया। – Szabolcs

+1

'सरणी' केवल उन बफर के लिए काम करता है जिन्हें एक सरणी द्वारा समर्थित किया जाता है (आमतौर पर '* बफर.व्रप' से)। –

उत्तर

4

जावाडोक के अनुसार
" मैप किए गए बाइट बफर की सामग्री किसी भी समय बदल सकती है, उदाहरण के लिए यदि मैप किए गए फ़ाइल के संबंधित क्षेत्र की सामग्री इस प्रोग्राम या किसी अन्य द्वारा बदल दी जाती है। चाहे ऐसे परिवर्तन होते हैं या नहीं, और जब वे होते हैं, ऑपरेटिंग-सिस्टम आश्रित है और इसलिए निर्दिष्ट नहीं किया गया।

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

मेरे लिए यह कई लोगों को लगता है

FileChannel fChannel = new FileInputStream(f).getChannel(); 
    byte[] barray = new byte[(int) f.length()]; 
    ByteBuffer bb = ByteBuffer.wrap(barray); 
    bb.order(ByteOrder.LITTLE_ENDIAN); 
    fChannel.read(bb); 

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

है?

डबल के लिए आप डबलबफर का उपयोग कर सकते हैं (डबल [] सरणी के साथ अगर f.length()/4 आकार) या बस बाइटबफर के getDouble (int) विधि को कॉल करें।

+0

मुझे विशेष रूप से इस कक्षा की आवश्यकता नहीं है। मैं आशा करता था कि बिल्टिन मैथमैटिका कार्यक्षमता के मुकाबले तेजी से रास्ते में, एक बहुत बड़ी बाइनरी फ़ाइल (यह सब नहीं) के हिस्से की सामग्री को युगल की सरणी के रूप में प्राप्त करने में सक्षम होने की उम्मीद थी। – Szabolcs

+0

"डबल के लिए आप डबलबफर (डबल [] सरणी के साथ f.length()/4 आकार के साथ अद्यतन कर सकते हैं या बस बाइटबफर के getDouble (int) विधि को कॉल कर सकते हैं।" आपने कहा कि आप केवल कुछ युगल पढ़ेंगे। मैं बाइटबफर का उपयोग अनियंत्रित बाइट्स के युगल में संभव रूपांतरण से बचने के लिए करता हूं (डबलबफर के मामले में)। – andrey

+0

धन्यवाद @andrey। मुझे अंततः 'डबल []' प्राप्त करने की आवश्यकता है, क्योंकि यह एक गणित वस्तु को स्वत: रूपांतरित कर देता है (यानी मैं कुछ इंडेक्स के साथ 'getDouble' का उपयोग नहीं कर सकता)। अगर मैं सीधे 'डबलबफर' में पढ़ने की कोशिश करता हूं, तो यह काम नहीं करता है। अगर मैं 'बाइटबफर' में पढ़ता हूं, तो यह काम करता है, और मैं इसे 'asDoubleBuffer()' के रूप में प्राप्त कर सकता हूं, लेकिन मैं इस तरह से प्राप्त करता हूं 'हैरएरे()' के लिए फिर से 'झूठा' देता है, यानी मैं इसे परिवर्तित नहीं कर सकता 'डबल' की एक सादा सरणी। क्या आपके पास पूरी चीज के माध्यम से स्पष्ट रूप से लूपिंग किए बिना डबल की सरणी कैसे प्राप्त करें और उन्हें एक-एक करके कॉपी करने के बारे में कोई सुझाव है? – Szabolcs

0
जावा में

:

final byte[] hb;     // Non-null only for heap buffers 

तो यह भी MappedByteBuffer के लिए लागू नहीं है लेकिन HeapByteBuffer के लिए है।

एंड्रॉयड में

:

** 
    * Child class implements this method to realize {@code array()}. 
    * 
    * @see #array() 
    */ 
    abstract byte[] protectedArray(); 

और फिर MappedByteBuffer में नहीं है, लेकिन उदाहरण के लिए ByteArrayBuffer समर्थन सरणी को लागू करता है।

@Override byte[] protectedArray() { 
    if (isReadOnly) { 
     throw new ReadOnlyBufferException(); 
    } 
    return backingArray; 
    } 

मेमोरी मानचित्र का बिंदु ढेर बंद होना है। एक बैकिंग सरणी ढेर पर होगी।
यदि आप FileChannel को RandomAccessFile से खोल सकते हैं और फिर चैनल पर मानचित्र कॉल कर सकते हैं, तो आप बाइट [] में पढ़ने के लिए मैपडबेट बफर पर थोक get() विधि का भी उपयोग कर सकते हैं। यह आईओओ से परहेज, ढेर में फिर से ढेर से प्रतियां।

buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); 
byte[] b = new byte[buffer.limit()]; 
buffer.get(b); 
संबंधित मुद्दे