2009-10-09 13 views
12

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

"草鷗外.gif" जो जावा पात्रों \u8349\uD85B\uDFF6\u9DD7\u5916.gif

अगर मैं इस फ़ाइल नाम से एक फ़ाइल बनाने के लिए, मैं इसे नहीं खोल सकता क्योंकि मैं एक FileNotFound अपवाद में बंट जाता है। यहां तक ​​कि फ़ाइल वाले फ़ोल्डर पर इस का उपयोग करते हुए असफल हो जायेगी:

File[] files = folder.listFiles(); 
for (File file : files) { 
    if (!file.exists()) { 
     System.out.println("Failed to find File"); //Fails on the surrogate filename 
    } 
} 

कोड मैं वास्तव में साथ काम कर रहा हूँ के अधिकांश के रूप में हैं:

FileInputStream instream = new FileInputStream(new File("草鷗外.gif")); 
// operations follow 

वहाँ किसी तरह मैं इस समस्या का समाधान कर सकते हैं, या तो फ़ाइल नाम से बचने या फ़ाइलों को अलग-अलग खोलना?

+0

आपके पर्यावरण में Charset.defaultCharset() का मूल्य क्या है? –

+2

(दुर्भाग्यवश, स्टैक ओवरव्लो को सरोगेट्स के साथ भी समस्या है, और इस सवाल से यू +26 एफएफ 6 विचारधारा को तोड़ दिया है) – bobince

+0

क्या आप सिस्टम.getप्रोपर्टी ("file.encoding") देता है? अपने एन्कोडिंग जावा-डीफाइल.एन्कोडिंग = ENCODING_GOES_HERE को बदलने का प्रयास करें यदि न ही आपके सिस्टम लोकेल को बदलता है। यदि यह भी करता है और न ही काम करता है तो हम इसे हल करने के लिए एक विशेषज्ञ की प्रतीक्षा करेंगे। – JCasso

उत्तर

4

यदि आपके पर्यावरण के डिफ़ॉल्ट लोकेल में उन वर्णों को शामिल नहीं किया गया है, तो आप फ़ाइल नहीं खोल सकते हैं।

देखें: File.exists() fails with unicode characters in name

संपादित करें: ठीक है .. क्या आप की जरूरत सिस्टम स्थान को बदलने के लिए है। आप जो भी ओएस उपयोग कर रहे हैं।

संपादित:

देखें: How can I open files containing accents in Java?

देखें: JFileChooser on Mac cannot see files named by Chinese chars?

+0

दोनों सिस्टम लोकेल को बदले बिना ऐसा करना संभव नहीं है? जिस कार्यक्रम को मैं निर्माण कर रहा हूं उसे किसी भी लोकेल पर चलाने की आवश्यकता होगी, और मुझे इन पात्रों को इनपुट करने और इन फ़ाइलों के साथ एक यूएस/अंग्रेजी लोकेल में भी निपटने में सक्षम होना चाहिए। – Bear

+0

खराब समाधान - क्योंकि ऐप उपयोगकर्ताओं पर चलाया गया है, जो मेरे कंप्यूटर पर नहीं बैठता है। और अलग-अलग लोकेल हैं, और उनके पास ऐसा करने के लिए कठोर प्रशासक नहीं है। –

+0

AFAIK कोई अन्य समाधान नहीं है। यह सीमा सूर्य/ओरेकल जावा के साथ आता है। यदि आप अपने उपयोगकर्ताओं के लिए एक सेव डायलॉग प्रदर्शित करते हैं तो आप JFileChooser को आजमा सकते हैं। – JCasso

7

मैं उचित UTF-8 के बजाय CESU-8 उपयोग कर रहा है जावा या मैक से एक संदेह है। विभिन्न प्रकार के आंतरिक उद्देश्यों के लिए जावा "संशोधित यूटीएफ -8" (जो सीईएसयू -8 की थोड़ी भिन्नता है) का उपयोग करता है, लेकिन मुझे पता नहीं था कि यह इसे फाइल सिस्टम/डिफ़ॉल्ट चार्जसेट के रूप में उपयोग कर सकता है। दुर्भाग्य से मेरे पास परीक्षण करने के लिए यहां न तो मैक और न ही जावा है।

"संशोधित" "बुरी तरह से खराब" कहने का एक संशोधित तरीका है। इसके बजाय तरह अनुपूरक (गैर बीएमपी) के लिए एक चार बाइट UTF-8 अनुक्रम outputting पात्रों में से & # x26FF6 ;:

\xF0\xA6\xBF\xB6 

यह किराए की कोख से प्रत्येक के लिए एक UTF-8 एन्कोड अनुक्रम आउटपुट:

\xED\xA1\x9B\xED\xBF\xB6 

यह मान्य यूटीएफ -8 अनुक्रम नहीं है, लेकिन बहुत से डिकोडर्स इसे वैसे भी अनुमति देंगे। समस्या यह है कि यदि आप वास्तविक यूटीएफ -8 एन्कोडर के माध्यम से राउंड-ट्रिप करते हैं तो आपके पास एक अलग स्ट्रिंग है, ऊपर चार-बाइट एक है। उस नाम और बूम के साथ फ़ाइल तक पहुंचने का प्रयास करें! असफल।

तो सबसे पहले सिर्फ जाँच कैसे फ़ाइल नाम वास्तव में अपने वर्तमान फाइल सिस्टम के तहत जमा हो जाती है, इस तरह के पायथन 2.x के रूप में फ़ाइल नामों के लिए बाइट का उपयोग करता है एक मंच का उपयोग कर करते हैं:

$ python 
Python 2.x.something (blah blah) 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> os.listdir('.') 

मेरी फाइल सिस्टम पर (लिनक्स, ext4, UTF -8), फ़ाइल नाम "草 & # x26FF6; 鷗 外।gif "के रूप में बाहर आता है:

['\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif'] 

जो आप चाहते हैं। यदि आपको यही मिलता है, तो शायद यह जावा गलत कर रहा है। आप लंबे समय तक छह-बाइट-चरित्र संस्करण मिलता है: शायद ओएस एक्स यह गलत कर

['\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif'] 

यह है ... यह हमेशा इस तरह फ़ाइल नाम की दुकान करता है? (या फ़ाइलें कहीं और मूल रूप से आया?) क्या होगा यदि आप 'उचित' संस्करण ?:

os.rename('\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif', '\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif') 
+2

वास्तव में एक बग नहीं है क्योंकि यह spec का हिस्सा है (भले ही यह अक्सर भ्रमित हो।) – finnw

+0

पायथन कमांड का परिणाम आपके द्वारा पहले सूचीबद्ध उचित फ़ाइल नाम था, इसलिए यह जावा अच्छा नहीं खेलना चाहिए। – Bear

+0

ओह, यह दुर्भाग्यपूर्ण है। यहां तक ​​कि यदि आपने टूटी हुई सीईएसयू -8 स्थिति का पता लगाया है, तो भी मैं इसके आसपास काम करने और बाइट उन्मुख फ़ाइल नाम इंटरफ़ेस प्राप्त करने के किसी भी तरीके से नहीं सोच सकता। :-(आपको सूर्य को ठीक करने के समय तक सरोगेट्स को स्पष्ट रूप से अस्वीकार करना पड़ सकता है। कितना खराब। – bobince

3

यह मैक JVM के साथ एक समस्या साबित हुआ करने के लिए फ़ाइल का नाम बदलें (1.5 और 1.6 पर परीक्षण किया)। अनुपूरक वर्ण/सरोगेट जोड़े वाले फ़ाइल नाम जावा फ़ाइल क्लास के साथ उपयोग नहीं किए जा सकते हैं। मैंने परियोजना के मैक संस्करण (ick) के लिए कार्बन कॉल के साथ एक जेएनआई लाइब्रेरी लिखना समाप्त कर दिया। मुझे संदेह है कि सीईएसयू -8 अंक बॉबेंस का उल्लेख है, क्योंकि यूएनएफ -8 पात्रों को प्राप्त करने के लिए जेएनआई कॉल ने सीईएसयू -8 स्ट्रिंग लौटा दी है। ऐसा कुछ ऐसा नहीं दिखता है जो आप वास्तव में प्राप्त कर सकते हैं।

0

यह पुराने-स्कूल जावा फ़ाइल एपीआई में एक बग है, शायद मैक पर? वैसे भी, नया java.nio api बहुत बेहतर काम करता है। मेरे पास कई फाइलें हैं जिनमें यूनिकोड वर्ण और सामग्री है जो java.io.File और संबंधित वर्गों का उपयोग करके लोड करने में विफल रही है। java.nio.Path का उपयोग करने के लिए मेरे सभी कोड को कनवर्ट करने के बाद सब कुछ काम करना शुरू कर दिया। और मैं org.apache.commons.io.FileUtils प्रतिस्थापित (जो एक ही समस्या है) java.nio.Files साथ ...

... और पढ़ सकते हैं और एक उपयुक्त चारसेट का उपयोग कर फ़ाइल की सामग्री लिखने के लिए, उदाहरण के लिए सुनिश्चित हो: Files.readAllLines (myPath, StandardCharsets.UTF_8)

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