জাভাতে কোনও আইএনআই ফাইল পার্স করার সহজতম উপায় কী?


104

আমি জাভাতে কোনও উত্তরাধিকার অ্যাপ্লিকেশনটির জন্য একটি ড্রপ-ইন প্রতিস্থাপন লিখছি। প্রয়োজনীয়তার মধ্যে একটি হ'ল পুরানো অ্যাপ্লিকেশন ব্যবহৃত আইএনআই ফাইলগুলি নতুন জাভা অ্যাপ্লিকেশনের মধ্যে পড়তে হয়। এই আইএনআই ফাইলগুলির ফর্ম্যাটটি হ'ল উইন্ডো শৈলী, শিরোনাম বিভাগ এবং কী = মান জোড়া যুক্ত করে # মন্তব্য করার জন্য অক্ষর হিসাবে ব্যবহার করে।

আমি জাভা থেকে প্রোপার্টি ক্লাসটি ব্যবহার করার চেষ্টা করেছি, তবে অবশ্যই বিভিন্ন শিরোনামের মধ্যে নাম সংঘর্ষ থাকলে এটি কাজ করবে না।

সুতরাং প্রশ্নটি হল, এই আইএনআই ফাইলে পড়া এবং কীগুলি অ্যাক্সেস করার সবচেয়ে সহজ উপায় কী হবে?

উত্তর:


121

আমি যে লাইব্রেরিটি ব্যবহার করেছি তা ini4j । এটি লাইটওয়েট এবং সহজেই আইএনআই ফাইলগুলি পার্স করে। এছাড়াও এটি 10,000 অন্যান্য জার ফাইলগুলিতে কোনও নির্ভরশীল নির্ভরতা ব্যবহার করে না, কারণ ডিজাইনের লক্ষ্যগুলির মধ্যে একটি ছিল কেবলমাত্র স্ট্যান্ডার্ড জাভা এপিআই ব্যবহার করা

এটি লাইব্রেরিটি কীভাবে ব্যবহৃত হয় তার একটি উদাহরণ:

Ini ini = new Ini(new File(filename));
java.util.prefs.Preferences prefs = new IniPreferences(ini);
System.out.println("grumpy/homePage: " + prefs.node("grumpy").get("homePage", null));

2
কাজ করে না, ত্রুটি বলে যে "ইনফায়াল কোনও ধরণের সমাধান করা যায় না"
ক্যাবলেরো

@ ক্যাবলেরো হ্যাঁ মনে হচ্ছে IniFileক্লাস নেওয়া হয়েছিল, চেষ্টা করুনIni ini = new Ini(new File("/path/to/file"));
মেহেদি করামোসলি

2
ini4j.sourceforge.net/tutorial/OneMinuteTutorial.java.html তারা আবার ক্লাসের নাম পরিবর্তন করলেও সম্ভবত আপ টু ডেট থাকবে।
লোকাথোর

এই জিনিসটি কি আর কাজ করে? ০.০.৪ উত্স ডাউনলোড করেছেন এবং এটি নির্মাণও করেনি, এবং এটি একটি নিখোঁজ নির্ভরতা ছিল না .. এটির সাথে আরও বিরক্ত করার জন্য সময়টির উপযুক্ত নয়। এছাড়াও ini4j এর অন্যান্য প্রচুর ক্রেপ রয়েছে যেখানে আমাদের দরকার নেই, উইন্ডোজ রেজিস্ট্রি সম্পাদনা ... চলুন। # লিনাক্সমাস্টারেস ... তবে আমার ধারণা যদি এটি আপনার পক্ষে কাজ করে তবে নিজেকে ছিটকে পড়ুন।
ব্যবহারকারী

আইএনআই ফাইলের জন্য আমি লিখেছিলাম, আমাকে Winiক্লাসটি ব্যবহার করতে হয়েছিল, "ওয়ান মিনিট" টিউটোরিয়ালে বর্ণিত; prefs.node("something").get("val", null)পথ আমি আশা কাজ করে নি।
আগি হামারথিফ

65

উল্লিখিত হিসাবে , ini4j এটি অর্জন করতে ব্যবহার করা যেতে পারে। আমাকে অন্য একটি উদাহরণ দেখান।

যদি আমাদের মতো একটি আইএনআই ফাইল থাকে:

[header]
key = value

নিম্নলিখিতটি valueSTDOUT এ প্রদর্শিত হবে:

Ini ini = new Ini(new File("/path/to/file"));
System.out.println(ini.get("header", "key"));

আরও উদাহরণের জন্য টিউটোরিয়াল পরীক্ষা করে দেখুন।


2
ঝরঝরে! আমার অ্যাপ্লিকেশনগুলিতে আরও একটি নির্ভরতা যুক্ত করতে না পারার জন্য আমি সর্বদা কেবল বাফারড্রেডার এবং কিছুটা অনুলিপি / পেস্ট স্ট্রিং পার্সিং কোড ব্যবহার করে যাচ্ছি (এমনকি যখন আপনি সরলতম কাজের জন্যও তৃতীয় পক্ষের এপিআইগুলিতে যোগ করতে শুরু করেন তখন অনুপাতের বাইরে চলে যেতে পারে) )। তবে আমি এ জাতীয় সরলতা উপেক্ষা করতে পারি না।
গিম্বি

30

80 লাইনের মতো সহজ:

package windows.prefs;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IniFile {

   private Pattern  _section  = Pattern.compile( "\\s*\\[([^]]*)\\]\\s*" );
   private Pattern  _keyValue = Pattern.compile( "\\s*([^=]*)=(.*)" );
   private Map< String,
      Map< String,
         String >>  _entries  = new HashMap<>();

   public IniFile( String path ) throws IOException {
      load( path );
   }

   public void load( String path ) throws IOException {
      try( BufferedReader br = new BufferedReader( new FileReader( path ))) {
         String line;
         String section = null;
         while(( line = br.readLine()) != null ) {
            Matcher m = _section.matcher( line );
            if( m.matches()) {
               section = m.group( 1 ).trim();
            }
            else if( section != null ) {
               m = _keyValue.matcher( line );
               if( m.matches()) {
                  String key   = m.group( 1 ).trim();
                  String value = m.group( 2 ).trim();
                  Map< String, String > kv = _entries.get( section );
                  if( kv == null ) {
                     _entries.put( section, kv = new HashMap<>());   
                  }
                  kv.put( key, value );
               }
            }
         }
      }
   }

   public String getString( String section, String key, String defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return kv.get( key );
   }

   public int getInt( String section, String key, int defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Integer.parseInt( kv.get( key ));
   }

   public float getFloat( String section, String key, float defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Float.parseFloat( kv.get( key ));
   }

   public double getDouble( String section, String key, double defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Double.parseDouble( kv.get( key ));
   }
}

+1 কেবল রেজেক্স প্যাটার্ন / ম্যাচার ব্যবহারের জন্য।
মোহন

একটি নিখুঁত সমাধান নয় তবে একটি সূচনা পয়েন্ট, উদাহরণস্বরূপ, গেটসেকশন () এবং গেটস্ট্রিং () অনুপস্থিত থাকলে কেবলমাত্র পুরো বিভাগটি অনুপস্থিত থাকলে ডিফল্টভ্যালু দেয়।
জ্যাক মিলার

স্ট্রিং বাস্তবায়নের সাথে কাজ করা এই জাতীয় রেজেক্স বনামের মধ্যে পারফরম্যান্সের পার্থক্য কী?
ইওকস

একটি ছোট কনফিগারেশন ফাইল পড়ার সময় পারফরম্যান্স উদ্বেগের বিষয় নয়। আমি বিশ্বাস করি যে একটি ফাইল খোলার এবং বন্ধ করা অনেক বেশি গ্রাসযোগ্য, আমি বিশ্বাস করি।
এরোস্পেস

হ্যাঁ, এটি সাধারণ ব্যবহারের ক্ষেত্রে যেমন হওয়া উচিত ততটা সহজ। লোকেরা কেন এটি জটিল করতে চায় তা নিশ্চিত নয়। যদি আপনি কর্মক্ষমতা সম্পর্কে উদ্বিগ্ন হন (বা ত্রুটির প্রতিবেদনের মতো অন্যান্য উদ্বেগগুলি), হ্যাঁ, আপনি সম্ভবত অন্য কিছু ব্যবহার করতে চান (সম্ভবত অন্য কোনও ফর্ম্যাট পুরোপুরি)।
ব্যবহারকারী

16

অ্যাপাচি ক্লাস হায়ারার্কিকালআইএনআইসি কনফিগারেশন ব্যবহার করে এখানে একটি সহজ, তবে শক্তিশালী উদাহরণ রয়েছে :

HierarchicalINIConfiguration iniConfObj = new HierarchicalINIConfiguration(iniFile); 

// Get Section names in ini file     
Set setOfSections = iniConfObj.getSections();
Iterator sectionNames = setOfSections.iterator();

while(sectionNames.hasNext()){

 String sectionName = sectionNames.next().toString();

 SubnodeConfiguration sObj = iniObj.getSection(sectionName);
 Iterator it1 =   sObj.getKeys();

    while (it1.hasNext()) {
    // Get element
    Object key = it1.next();
    System.out.print("Key " + key.toString() +  " Value " +  
                     sObj.getString(key.toString()) + "\n");
}

কমন্স কনফিগারেশনের বেশ কয়েকটি রানটাইম নির্ভরতা রয়েছে । সর্বনিম্ন, কমন্স-ল্যাং এবং কমন্স-লগিং প্রয়োজন। আপনি এটি দিয়ে কী করছেন তার উপর নির্ভর করে আপনার অতিরিক্ত গ্রন্থাগারগুলির প্রয়োজন হতে পারে (বিশদটির জন্য পূর্ববর্তী লিঙ্কটি দেখুন)।


1
এটি আমার সঠিক উত্তর হবে। ব্যবহার করার জন্য খুব সহজ এবং বহুমুখী।
মার্কোলোপস

কমন্স কনফিগারেশন সংগ্রহ নয়।
jantox

13

অথবা স্ট্যান্ডার্ড জাভা এপিআই এর সাহায্যে আপনি java.util.Properties ব্যবহার করতে পারেন :

Properties props = new Properties();
try (FileInputStream in = new FileInputStream(path)) {
    props.load(in);
}

12
সমস্যা হ'ল আইএনআই ফাইল সহ স্ট্রাকচারের শিরোনাম রয়েছে। সম্পত্তি শ্রেণিটি কীভাবে শিরোলেখগুলি পরিচালনা করতে জানে না এবং নাম সংঘর্ষ হতে পারে
মারিও অর্টেগন

2
এছাড়াও, Propertiesক্লাসটি যথাযথভাবে
that

3
সহজ সমাধানের জন্য +1, তবে মারিও অর্টিগন এবং আরডিএসের নজরে আসায় এটি কেবল সাধারণ কনফিগারেশন ফাইলগুলিতে ফিট করে।
বেঞ্জ

1
আইএনআই ফাইলে [বিভাগ] রয়েছে, বৈশিষ্ট্য ফাইলটিতে অ্যাসাইনমেন্ট রয়েছে।
এয়ারস্পেস


10

18 টি লাইনে, java.util.Propertiesএকাধিক বিভাগে পার্স করতে প্রসারিত :

public static Map<String, Properties> parseINI(Reader reader) throws IOException {
    Map<String, Properties> result = new HashMap();
    new Properties() {

        private Properties section;

        @Override
        public Object put(Object key, Object value) {
            String header = (((String) key) + " " + value).trim();
            if (header.startsWith("[") && header.endsWith("]"))
                return result.put(header.substring(1, header.length() - 1), 
                        section = new Properties());
            else
                return section.put(key, value);
        }

    }.load(reader);
    return result;
}

2

অন্য বিকল্প হ'ল অ্যাপাচি কমন্স কনফিগারেশনের আইএনআই ফাইলগুলি থেকে লোড করার জন্য একটি ক্লাসও রয়েছে । এটিতে কিছু রানটাইম নির্ভরতা রয়েছে তবে আইএনআই ফাইলগুলির জন্য এটি কেবল কমন্স সংগ্রহ, ল্যাং এবং লগিংয়ের প্রয়োজন।

আমি তাদের সম্পত্তি এবং এক্সএমএল কনফিগারেশন সহ প্রকল্পগুলিতে কমন্স কনফিগার ব্যবহার করেছি। এটি ব্যবহার করা খুব সহজ এবং বেশ কয়েকটি শক্তিশালী বৈশিষ্ট্য সমর্থন করে।



2

আমি ব্যক্তিগতভাবে কনফুসিয়াসকে পছন্দ করি ।

এটি দুর্দান্ত, কারণ এতে কোনও বাহ্যিক নির্ভরতা প্রয়োজন হয় না, এটি ক্ষুদ্র - কেবল 16 কে, এবং স্বয়ংক্রিয়ভাবে আপনার আইএনআই ফাইলটি আরম্ভের সময় লোড করে দেয়। যেমন

Configurable config = Configuration.getInstance();  
String host = config.getStringValue("host");   
int port = config.getIntValue("port"); 
new Connection(host, port);

3 বছর পরে, মার্ক এবং ওপি সম্ভবত বার্ধক্যজনিত কারণে মারা গেছে ... তবে এটি সত্যিই ভাল ফলাফল।
ব্যবহারকারী

6
আমি কাছাকাছি যেতে বেত ব্যবহার করি, তবে এখনও বেঁচে
আছি

@ মারিওআর্টেগেন: শুনে খুব ভাল লাগল!
28 אוהב אותך

0

hoat4 এর সমাধানটি খুব মার্জিত এবং সহজ। এটি সমস্ত বুদ্ধিমান আইএনআই ফাইলগুলির জন্য কাজ করে। যাইহোক, আমি এমন অনেকগুলিকে দেখেছি যাদের চাবিকাঠি থেকে পালিয়ে যাওয়া স্থানের অক্ষর রয়েছে ।
এটি সমাধান করার জন্য, আমি এর একটি অনুলিপি ডাউনলোড এবং সংশোধন করেছি java.util.Properties। যদিও এটি কিছুটা অপ্রচলিত এবং স্বল্প-মেয়াদী, আসল মোডগুলি কয়েকটি লাইন এবং বেশ সহজ ছিল। আমি জেডিকে সম্প্রদায়ের কাছে পরিবর্তনগুলি অন্তর্ভুক্ত করার জন্য একটি প্রস্তাব পেশ করব।

একটি অভ্যন্তরীণ শ্রেণীর ভেরিয়েবল যুক্ত করে:

private boolean _spaceCharOn = false;

আমি কী / মান পৃথকীকরণের জন্য স্ক্যান সম্পর্কিত সম্পর্কিত প্রসেসিং নিয়ন্ত্রণ করি control আমি স্থানের অক্ষরগুলির অনুসন্ধান কোডটি একটি ছোট ব্যক্তিগত পদ্ধতিতে প্রতিস্থাপন করেছি যা উপরের ভেরিয়েবলের অবস্থার উপর নির্ভর করে একটি বুলিয়ান দেয়।

private boolean isSpaceSeparator(char c) {
    if (_spaceCharOn) {
        return (c == ' ' || c == '\t' || c == '\f');
    } else {
        return (c == '\t' || c == '\f');
    }
}

এই পদ্ধতিটি ব্যক্তিগত পদ্ধতির মধ্যে দুটি স্থানে ব্যবহৃত হয় load0(...)
এটি চালু করার জন্য একটি পাবলিক পদ্ধতিও রয়েছে Propertiesতবে স্পেস বিভাজক যদি আপনার আবেদনের জন্য সমস্যা না হয় তবে এর মূল সংস্করণটি ব্যবহার করা ভাল ।

যদি আগ্রহ থাকে তবে আমি আমার IniFile.javaফাইলে কোডটি পোস্ট করতে আগ্রহী । এটি উভয় সংস্করণের সাথে কাজ করে Properties


0

@ অ্যারোস্পেস দ্বারা উত্তর ব্যবহার করে, আমি বুঝতে পেরেছি যে আইএনআই ফাইলগুলির জন্য কোনও কী-মান ছাড়াই বিভাগ থাকা বৈধ। এই ক্ষেত্রে, কোনও কী-মানগুলি সন্ধানের আগে শীর্ষ স্তরের মানচিত্রের সাথে সংযুক্ত হওয়া উচিত, প্রাক্তন (জাভা 8 এর জন্য নূন্যতম আপডেট হওয়া):

            Path location = ...;
            try (BufferedReader br = new BufferedReader(new FileReader(location.toFile()))) {
                String line;
                String section = null;
                while ((line = br.readLine()) != null) {
                    Matcher m = this.section.matcher(line);
                    if (m.matches()) {
                        section = m.group(1).trim();
                        entries.computeIfAbsent(section, k -> new HashMap<>());
                    } else if (section != null) {
                        m = keyValue.matcher(line);
                        if (m.matches()) {
                            String key = m.group(1).trim();
                            String value = m.group(2).trim();
                            entries.get(section).put(key, value);
                        }
                    }
                }
            } catch (IOException ex) {
                System.err.println("Failed to read and parse INI file '" + location + "', " + ex.getMessage());
                ex.printStackTrace(System.err);
            }

-2

এটা ঠিক যেমন সহজ .....

//import java.io.FileInputStream;
//import java.io.FileInputStream;

Properties prop = new Properties();
//c:\\myapp\\config.ini is the location of the ini file
//ini file should look like host=localhost
prop.load(new FileInputStream("c:\\myapp\\config.ini"));
String host = prop.getProperty("host");

1
এটি আইএনআই বিভাগগুলি পরিচালনা করে না
ইগোর মেলিনিচেঙ্কো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.