30

I am reading a property file which consists of a message in the UTF-8 character set.

Problem

The output is not in the appropriate format. I am using an InputStream.

The property file looks like

username=LBSUSER
password=Lbs@123
url=http://localhost:1010/soapfe/services/MessagingWS
timeout=20000
message=Spanish character are = {á é í, ó,ú ,ü, ñ, ç, å, Á, É, Í, Ó, Ú, Ü, Ñ, Ç, ¿, °, 4° año = cuarto año, €, ¢, £, ¥}

And I am reading the file like this,

Properties props = new Properties();
props.load(new FileInputStream("uinsoaptest.properties"));
String username = props.getProperty("username", "test");
String password = props.getProperty("password", "12345");
String url = props.getProperty("url", "12345");
int timeout = Integer.parseInt(props.getProperty("timeout", "8000"));
String messagetext = props.getProperty("message");
System.out.println("This is soap msg : " + messagetext);

The output of the above message is

enter image description here

You can see the message in the console after the line

{************************ SOAP MESSAGE TEST***********************}

I will be obliged if I can get any help reading this file properly. I can read this file with another approach but I am looking for less code modification.

Kirby
  • 15,127
  • 10
  • 89
  • 104
Som
  • 826
  • 3
  • 10
  • 20

5 Answers5

82

Use an InputStreamReader with Properties.load(Reader reader):

FileInputStream input = new FileInputStream(new File("uinsoaptest.properties"));
props.load(new InputStreamReader(input, Charset.forName("UTF-8")));

As a method, this may resemble the following:

  private Properties read( final Path file ) throws IOException {
    final var properties = new Properties();

    try( final var in = new InputStreamReader(
      new FileInputStream( file.toFile() ), StandardCharsets.UTF_8 ) ) {
      properties.load( in );
    }

    return properties;
  }

Don't forget to close your streams. Java 7 introduced StandardCharsets.UTF_8.

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Würgspaß
  • 4,660
  • 2
  • 25
  • 41
  • That's a strange problem. In ubuntu I just use `props.load(propFile)` and it works well, but in windows I had to use above code to load unicode prop file correctly! – vakarami May 07 '17 at 10:01
  • It's not that strange, after all. Character sets are heavily platform-dependent. So, it should not surprise that Ubuntu behaves differently than Windows. In fact, you might have to change your code yet again after moving to the next Windows version (or to be precise: another JVM version). – Würgspaß Jun 05 '17 at 22:47
  • FileInputStream inputStream=new FileInputStream(new File(propFileName) throws `FileNotFoundException`. Where propFileName is `config/cop-app-dev.properties` – Mukhamedali Zhadigerov Oct 24 '18 at 10:55
  • @MukhamedaliZhadigerov That is another issue. Make sure the file with properties is present (and readable) relative to your java executable. If unsure, try an absolute path. – Würgspaß Oct 24 '18 at 11:11
  • @Würgspaß Yes. It's presented and reachable. I can reach that property file by using `InputStream inputStream=getClass().getClassLoader().getResourceAsStream(propFileName)` and `properties.load(inputStream);` – Mukhamedali Zhadigerov Oct 24 '18 at 11:18
  • @MukhamedaliZhadigerov the exception you've got is from `FileInputStream`. According to the docs it is thrown, _if the file does not exist, is a directory rather than a regular file, or for some other reason cannot be opened for reading._ So it is impossible to say what went wrong with your specific setup (have a close look at the stack trace, maybe there are some more details). But: Why don't you use the stream you already got by calling `getResourceAsStream`? Just replace your second line ike this: `props.load(new InputStreamReader(inputStream, Charset.forName("UTF-8")));` – Würgspaß Oct 24 '18 at 11:59
  • @Würgspaß I could fix that. As you said i used the stream i already got. And loaded property file like that: `properties.load(new InputStreamReader(inputStream));` without `Charset.forName("UTF-8")`. Seems like `new InputStreamReader(inputStream));` already presents data in UTF-8 and by adding `Charset.forName("UTF-8")` it does "extra transformation" which is unnecessary :) – Mukhamedali Zhadigerov Oct 24 '18 at 12:16
4

Use props.load(new FileReader("uinsoaptest.properties")) instead. By default it uses the encoding Charset.forName(System.getProperty("file.encoding")) which can be set to UTF-8 with System.setProperty("file.encoding", "UTF-8") or with the commandline parameter -Dfile.encoding=UTF-8.

Binkan Salaryman
  • 3,008
  • 1
  • 17
  • 29
  • This did not work on Java 8 in windows. If you look in the Java source it hardcodes to load0(new LineReader (new InputStreamReader(bis, "ISO8859-1"))); – teknopaul Apr 17 '18 at 22:00
1

If somebody use @Value annotation, could try StringUils.

@Value("${title}")
private String pageTitle;

public String getPageTitle() {
    return StringUtils.toEncodedString(pageTitle.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));
}
Ilya Khudyakov
  • 301
  • 3
  • 15
0

You should specify the UTF-8 encoding when you construct your FileInputStream object. You can use this constructor:

new FileInputStream("uinsoaptest.properties", "UTF-8");

If you want to make a change to your JVM so as to be able to read UTF-8 files by default, you will have to change the JAVA_TOOL_OPTIONS in your JVM options to something like this :

-Dfile.encoding=UTF-8
Lexicographical
  • 501
  • 4
  • 16
0

If anybody comes across this problem in Kotlin, like me: The accepted solution of @Würgspaß works here as well. The corresponding Kotlin syntax:

Instead of the usual

val properties = Properties()
filePath.toFile().inputStream().use { stream -> properties.load(stream) }

I had to use

val properties = Properties()
InputStreamReader(FileInputStream(filePath.toFile()), StandardCharsets.UTF_8).use { stream -> properties.load(stream) }

With this, special UTF-8 characters are loaded correctly from the properties file given in filePath.

waldrabe
  • 303
  • 2
  • 13