Java에서 INI 파일을 해석하는 가장 쉬운 방법은 무엇입니까?
자바에서 레거시 어플리케이션의 드롭인 대체를 쓰고 있습니다.요건 중 하나는 이전 어플리케이션에서 사용하던ini 파일을 그대로 새로운 Java 어플리케이션으로 읽어야 한다는 것입니다.이 ini 파일의 형식은 일반적인 윈도 스타일로 헤더 섹션과 키=값 쌍이 있으며 #를 주석 문자로 사용합니다.
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
은 '보다 낫다'라고 되어야 합니다.value
표준 출력:
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 ));
}
}
다음은 Apache 클래스의 계층 구조를 사용한 단순하지만 강력한 예입니다.INIC 구성:
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-lang 및 commons-logging이 필요합니다.사용 방법에 따라 추가 라이브러리가 필요할 수 있습니다(자세한 내용은 이전 링크를 참조하십시오).
또는 표준 Java API에서는 java.util을 사용할 수 있습니다.속성:
Properties props = new Properties();
try (FileInputStream in = new FileInputStream(path)) {
props.load(in);
}
18행, 18행, 18행, 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 컬렉션, 언어 및 로깅만 필요합니다.
Properties와 XML Configuration을 포함한 프로젝트에서 Commons Config를 사용한 적이 있습니다.매우 사용하기 쉽고 매우 강력한 기능을 지원합니다.
JINIFile도 먹어볼 수 있어요.Dellphi에서 TiniFile을 번역한 것이지만 Java용입니다.
https://github.com/SubZane/JIniFile
저는 개인적으로 유학을 더 좋아합니다.
외부 의존관계가 필요 없어 16K에 불과하고 초기화 시 자동으로 ini 파일이 로딩되므로 좋습니다.예.
Configurable config = Configuration.getInstance();
String host = config.getStringValue("host");
int port = config.getIntValue("port");
new Connection(host, port);
hot4의 솔루션은 매우 우아하고 심플합니다.모든 정상적인 ini 파일에 사용할 수 있습니다.하지만 열쇠에 이스케이프되지 않은 공백 문자가 있는 것을 많이 보았습니다.
이 문제를 해결하기 위해 다음 복사본을 다운로드하여 수정했습니다.java.util.Properties
조금 비정통적이고 단기적이지만 실제 모드는 몇 줄에 불과하고 매우 단순했습니다.변경 내용을 포함한 제안을 JDK 커뮤니티에 제출합니다.
내부 클래스 변수를 추가하면 다음과 같이 됩니다.
private boolean _spaceCharOn = false;
키/값 분리점 스캔 관련 처리를 제어합니다.공백 문자 검색 코드를 위 변수의 상태에 따라 부울을 반환하는 작은 개인 메서드로 대체했습니다.
private boolean isSpaceSeparator(char c) {
if (_spaceCharOn) {
return (c == ' ' || c == '\t' || c == '\f');
} else {
return (c == '\t' || c == '\f');
}
}
이 방법은 개인 방법 중 두 곳에서 사용됩니다.load0(...)
.
스위치를 켜는 공개적인 방법도 있지만 원래 버전을 사용하는 것이 좋습니다.Properties
스페이스 세퍼레이터가 어플리케이션에 문제가 되지 않는 경우.
만약 관심이 있다면, 저는 기꺼이 코드를 제 앞으로 게시할 것입니다.IniFile.java
파일입니다. 어느 버전의 파일에서도 동작합니다.Properties
.
@Aerospace의 답변을 사용하여 INI 파일에 키 값이 없는 섹션이 있는 것이 정당하다는 것을 깨달았습니다.이 경우 키 값이 발견되기 전에 최상위 맵에 추가해야 합니다(Java 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);
}
ini4j를 사용하여 INI를 속성으로 변환할 수 있습니다.
Properties properties = new Properties();
Ini ini = new Ini(new File("path/to/file"));
ini.forEach((header, map) -> {
map.forEach((subKey, value) -> {
StringBuilder key = new StringBuilder(header);
key.append("." + subKey);
properties.put(key.toString(), value);
});
});
이렇게 간단해...
//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");
언급URL : https://stackoverflow.com/questions/190629/what-is-the-easiest-way-to-parse-an-ini-file-in-java
'source' 카테고리의 다른 글
JavaScript를 사용하여 문자열에서 문자를 삭제하려면 어떻게 해야 합니까? (0) | 2022.11.16 |
---|---|
부동값을 인쇄할 때 과학적 표기법을 사용하지 않는 방법은 무엇입니까? (0) | 2022.11.15 |
MySQL 및 Maria에서 상호 호환되는 가비지 문자열 함수를 생성하는 동안 오류가 발생했습니다.DB (0) | 2022.11.15 |
Composer - 요청된 PHP 확장 mbstring이 시스템에 없습니다. (0) | 2022.11.15 |
http를 통한 파일에 대한 직접 액세스를 차단하지만 php 스크립트 액세스를 허용합니다. (0) | 2022.11.15 |