है, मैं उत्पादन में देख रहे किनारे के मामले के साथ प्रयोग कर रहा हूं। हमारे पास एक व्यावसायिक मॉडल है जहां ग्राहक टेक्स्ट फाइलें उत्पन्न करते हैं और फिर उन्हें हमारे सर्वर पर एफ़टीपी करते हैं। हम उन फ़ाइलों को निगलना और उन्हें हमारे जावा बैकएंड पर संसाधित करते हैं (CentOS मशीनों पर चल रहे हैं)। हमारे ग्राहकों के अधिकांश (9 5% +) यूटीएफ -8 में इन फ़ाइलों को उत्पन्न करने के बारे में जानते हैं जो हम चाहते हैं। हालांकि हमारे पास कुछ जिद्दी ग्राहक हैं (लेकिन बड़े खाते) जो इन फ़ाइलों को सीपी 1252 चरित्र सेट के साथ विंडोज मशीन पर उत्पन्न करते हैं। हालांकि, कोई समस्या नहीं है, हमने कुछ तृतीय पक्ष libs (जो हमारे लिए "प्रसंस्करण" का अधिकांश काम करते हैं) को कुछ जादुई वू डू के माध्यम से किसी भी चरित्र सेट में इनपुट को संभालने के लिए कॉन्फ़िगर किया है।जावा फ़ाइल सिस्टम पर फ़ाइल नहीं देख सकता है जिसमें अवैध वर्ण
कभी-कभी, हम एक फ़ाइल देखते हैं जिसमें अवैध नाम यूटीएफ -8 वर्ण (सीपी 1252) हैं। हमारे सॉफ्टवेयर FTP सर्वर फ़ाइल पढ़ने chokes के सामान्य विधि से में इन फ़ाइलों को पढ़ने के लिए कोशिश करता है और फेंकता है जब एक FileNotFoundException
:
File f = getFileFromFTPServer();
FileReader fReader = new FileReader(f);
String line = fReader.readLine();
// ...etc.
अपवाद कुछ इस तरह दिखाई:
java.io.FileNotFoundException: /path/to/file/some-text-blah?blah.xml (No such file or directory) at java.io.FileInputStream.open(Native Method) at
java.io.FileInputStream.(FileInputStream.java:120) at java.io.FileReader.(FileReader.java:55) at com.myorg.backend.app.InputFileProcessor.run(InputFileProcessor.java:60) at
java.lang.Thread.run(Thread.java:662)
तो मैं क्या सोचते हैं ऐसा हो रहा है क्योंकि फ़ाइल नाम में अवैध वर्ण हैं, हम इसे पहले स्थान पर भी कभी नहीं पढ़ पाएंगे। यदि हम कर सकते हैं, तो फ़ाइल की सामग्री के बावजूद, हमारा सॉफ़्टवेयर इसे सही तरीके से संसाधित करने में सक्षम होना चाहिए। तो यह वास्तव में अवैध यूटीएफ -8 वर्णों के साथ फ़ाइल नाम पढ़ने के साथ एक मुद्दा है।
एक परीक्षण मामले के रूप में, मैंने अपने सर्वरों में से एक पर तैनाती के लिए एक बहुत ही सरल जावा "ऐप" बनाया और कुछ चीजों का परीक्षण (स्रोत कोड नीचे दिया गया है) का परीक्षण किया। मैंने फिर एक विंडोज मशीन में लॉग इन किया और एक टेस्ट फाइल बनाई और इसे test£.txt
नाम दिया। फ़ाइल नाम में "परीक्षण" के बाद चरित्र पर ध्यान दें। यह Alt-0163 है। मैंने इसे हमारे सर्वर पर एफ़टीपी किया, और जब मैंने अपनी मूल निर्देशिका पर ls -ltr
चलाया, तो मुझे यह देखने में आश्चर्य हुआ कि यह test?.txt
के रूप में सूचीबद्ध है।
इससे पहले कि मैं किसी भी आगे जाना है, यहाँ जावा "एप्लिकेशन" मैं परीक्षण के लिए लिखा है/इस मुद्दे के पुनरुत्पादन है: जब मैं टर्मिनल (java -cp . com/Driver t*
) से चलाने
public Driver {
public static void main(String[] args) {
Driver d = new Driver();
d.run(args[0]); // I know this is bad, but its fine for our purposes here
}
private void run(String fileName) {
InputStreamReader isr = null;
BufferedReader buffReader = null;
FileInputStream fis = null;
String firstLineOfFile = "default";
System.out.println("Processing " + fileName);
try {
System.out.println("Attempting UTF-8...");
fis = new FileInputStream(fileName);
isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
buffReader = new BufferedReader(isr);
firstLineOfFile = buffReader.readLine();
System.out.println("UTF-8 worked and first line of file is : " + firstLineOfFile);
}
catch(IOException io1) {
// UTF-8 failed; try CP1252.
try {
System.out.println("UTF-8 failed. Attempting Windows-1252...(" + io1.getMessage() + ")");
fis = new FileInputStream(fileName);
// I've also tried variations "WINDOWS-1252", "Windows-1252", "CP1252", "Cp1252", "cp1252"
isr = new InputStreamReader(fis, Charset.forName("windows-1252"));
buffReader = new BufferedReader(isr);
firstLineOfFile = buffReader.readLine();
System.out.println("Windows-1252 worked and first line of file is : " + firstLineOfFile);
}
catch(IOException io2) {
// Both UTF-8 and CP1252 failed...
System.out.println("Both UTF-8 and Windows-1252 failed. Could not read file. (" + io2.getMessage() + ")");
}
}
}
}
, मैं निम्नलिखित उत्पादन प्राप्त करें:
Processing test�.txt
Attempting UTF-8...
UTF-8 failed. Attempting Windows-1252...(test�.txt (No such file or directory))
Both UTF-8 and Windows-1252 failed. Could not read file.(test�.txt (No such file or directory))
test�.txt
?!? मैंने कुछ शोध किया और पाया कि "�" यूनिकोड प्रतिस्थापन चरित्र \uFFFD
है। तो मैं अनुमान क्या हो रहा है यह है कि CentOS FTP सर्वर को पता नहीं है कि Alt-0163 (£
) को कैसे प्रबंधित किया जाए और इसलिए यह \uFFFD
(�
) के साथ बदल देता है। लेकिन मैं क्यों समझ में नहीं आता ls -ltr
प्रदर्शित करता है एक फ़ाइल test?.txt
कहा जाता है ...
जो भी हो, ऐसा लगता है कि समाधान कुछ तर्क यह है कि फ़ाइल के नाम में इस चरित्र के अस्तित्व की खोज करता है जोड़ने के लिए है, और अगर पाया , किसी अन्य चीज़ को फ़ाइल का नाम बदलता है (जैसे शायद स्ट्रिंग-वार replaceAll("\uFFFD", "_")
या ऐसा कुछ करें) कि सिस्टम पढ़ और संसाधित कर सकता है।
समस्या यह है कि जावा फ़ाइल सिस्टम पर यह फ़ाइल नहीं देखता है। CentOS जानता है कि फ़ाइल वहां है (test?.txt
), लेकिन जब वह फ़ाइल जावा में पारित हो जाती है, तो जावा इसे test�.txt
के रूप में व्याख्या करता है और किसी कारण से No such file or directory
...
मैं इस फ़ाइल को देखने के लिए जावा कैसे प्राप्त कर सकता हूं ताकि मैं File::renameTo(String)
पर प्रदर्शन कर सकूं? यहां बैकस्टोरी के लिए खेद है, लेकिन मुझे लगता है कि यह प्रासंगिक है क्योंकि इस परिदृश्य में प्रत्येक विवरण की गणना की जाती है। अग्रिम में धन्यवाद!
ताकि आप निर्देशिका में फ़ाइलों को सूचीबद्ध नहीं कर सकें, फिर देखें कि उनके नाम में "विषम अक्षर" हैं और उन्हें "timestamp + random.something" में फ़ाइल.इनैम के साथ नाम दें? –
@ मार्कस मिककोलेन - क्या आप इसे मैन्युअल रूप से करने के बारे में बात कर रहे हैं? यदि नहीं, तो आप किस भाषा/स्क्रिप्ट का जिक्र कर रहे हैं? – IAmYourFaja
मेरा सुझाव है कि आप फाइलनामों को पास करने के बजाय फ़ाइल ऑब्जेक्ट्स का उपयोग करें। जो शायद किसी भी फाइलनाम भ्रष्टाचार को रोक देगा। –