[java] Java에서 INI 파일을 구문 분석하는 가장 쉬운 방법은 무엇입니까?

Java에서 레거시 응용 프로그램에 대한 드롭 인 대체를 작성하고 있습니다. 요구 사항 중 하나는 이전 응용 프로그램이 사용한 ini 파일을 그대로 새 Java 응용 프로그램으로 읽어야한다는 것입니다. 이 ini 파일의 형식은 주석을위한 문자로 #을 사용하는 헤더 섹션과 키 = 값 쌍이있는 일반적인 Windows 스타일입니다.

Java의 Properties 클래스를 사용해 보았지만 물론 다른 헤더 사이에 이름 충돌이 있으면 작동하지 않습니다.

그래서 질문은이 INI 파일을 읽고 키에 액세스하는 가장 쉬운 방법은 무엇입니까?



답변

내가 사용한 라이브러리는 ini4j 입니다. 가볍고 ini 파일을 쉽게 구문 분석합니다. 또한 설계 목표 중 하나가 표준 Java API 만 사용하는 것이었기 때문에 10,000 개의 다른 jar 파일에 대한 난해한 종속성을 사용하지 않습니다.

다음은 라이브러리 사용 방법에 대한 예입니다.

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));


답변

마찬가지로 , ini4j는 이를 달성하기 위해 사용될 수있다. 다른 예를 하나 보여 드리겠습니다.

다음과 같은 INI 파일이있는 경우 :

[header]
key = value

다음은 valueSTDOUT에 표시되어야합니다 .

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

더 많은 예제 는 튜토리얼 을 확인하십시오 .


답변

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 ));
   }
}


답변

다음은 아파치 클래스 HierarchicalINIConfiguration을 사용하는 간단하지만 강력한 예제입니다 .

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");
}

Commons Configuration에는 많은 런타임 종속성이 있습니다. 최소한 commons-langcommons-logging 이 필요합니다. 수행중인 작업에 따라 추가 라이브러리가 필요할 수 있습니다 (자세한 내용은 이전 링크 참조).


답변

또는 표준 Java API를 사용하여 java.util.Properties 를 사용할 수 있습니다 .

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


답변

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;
}


답변

또 다른 옵션은 Apache Commons Config에 INI 파일 에서로드하기위한 클래스도 있습니다 . 일부 런타임 종속성 이 있지만 INI 파일의 경우 Commons 컬렉션, lang 및 로깅 만 필요합니다.

속성과 XML 구성이있는 프로젝트에서 Commons Config를 사용했습니다. 사용하기 매우 쉽고 매우 강력한 기능을 지원합니다.