Also available in: Español · Português · Français · العربية
Java .properties escaper: the file is not UTF-8
Paste a properties file and see what each of Java's two loaders reads from the same bytes, plus the escaped form that makes them agree.
What is a .properties file?
A .properties file is Java's oldest and simplest configuration format: one key and one value per line, separated by an equals sign, and a hash for comments. It has been in the standard library since the beginning, it is what most translation bundles are still written in, and it is simple enough that people edit it in whatever they have open.
That simplicity hides something. A properties file has no encoding of its own. Nothing in the file says which one it is, there is no header and no byte order mark, and the answer depends entirely on which method opened it. Read through the stream method and every byte becomes one character, which is ISO 8859-1. Read through the reader method and it is whatever encoding the reader was built with. Read the XML flavour of the very same format and the default is UTF-8. One format, three answers.
So the file that looks right in your editor is not necessarily the file your program reads. This page shows both readings side by side from the same bytes, marks the values where they disagree, and gives you the escaped form that both loaders read identically.
How to use it
- Paste the file. It is encoded as UTF-8, which is what a modern editor saves. The sample buttons cover accented text, the same text already escaped, the separator and comment rules, a Windows path, and a continued line.
- Compare the two columns. One is what the stream loader reads, one is what a UTF-8 reader reads, both from those same bytes. A row marked as differing is a value your program will see differently depending on how the file was opened.
- Take the escaped form. Every character above plain ASCII written as an escape. That version cannot be broken by an editor changing the file's encoding, and it is what Java itself writes when it saves a properties file.
Why the same file reads two ways
The documentation states it plainly: the stream methods work the same way as the reader methods except that the stream is encoded in ISO 8859-1, and each byte is one Latin-1 character. The implementation is even more direct — a byte becomes a character by masking it to its low eight bits, with no decoder involved at all.
So a file saved as UTF-8 and read through the stream method gives you one character per byte. An e with an acute accent takes two bytes in UTF-8, and those two bytes become two characters, which is why café arrives as café. The value is not corrupted in transit and nothing warns you; it is simply being decoded by a rule the person who saved the file was not thinking about.
There is a distinction here worth being precise about, because it is easy to get backwards. An accented Latin letter is perfectly representable in ISO 8859-1 — e-acute is a single byte there. The problem is not that the character cannot be written, it is that the file was written in a different encoding from the one being read. A character above U+00FF is a separate case: those genuinely cannot be written in ISO 8859-1 at all, and must be escaped for the stream loader to see them however the file is saved.
The escape that fixes both is a backslash, the letter u, and four hexadecimal digits. Four, exactly, and only one u — the documentation says so, and the reference implementation throws rather than guessing if it finds anything else. That last point is a little pointed, because the Java language itself allows any number of u characters in an escape in source code. The same escape syntax, two different rules, in one platform.
The escape rules that eat your data
After a backslash, exactly four letters mean anything: t, r, n and f, for tab, carriage return, newline and form feed. Every other character after a backslash is simply itself, and the backslash disappears. That is deliberate — it is how you put a literal colon or equals sign inside a key — but it turns a Windows path into a trap.
Write a path as C colon backslash Users backslash temp and the result is worse than losing the separators. The first backslash vanishes before the U, and the second one is followed by a t, so it becomes a tab character. The value your program receives is C colon Users, an invisible tab, then emp. Doubling every backslash is the fix, and it is why properties files full of Windows paths look so strange.
The line rules have their own surprises. A key ends at the first equals sign, colon, space, tab or form feed, whichever comes first — so a line reading key value with no punctuation at all is a perfectly valid entry. Leading whitespace is stripped from every line, both hash and exclamation mark start a comment, and a line ending in a backslash continues onto the next, whose own leading whitespace is then also stripped. That last rule is what lets a long message be wrapped and indented without the indentation becoming part of the value.
What this tool does not do
It does not decide what your file actually contains on disk. You are typing text here, and the page encodes it as UTF-8 because that is what an editor saves today. If your file is genuinely stored as ISO 8859-1 then the stream loader will read it correctly and it is the reader that needs telling — the same comparison, the other way round.
It stops at the format. Whether a value is a sensible database URL, whether a key belongs in this bundle, whether the resource bundle machinery will find the file at all — none of that is visible in the bytes, and none of it is checked. And if what you actually have is text that already arrived mangled, the mojibake repair tool on this site is the page for that; this one is about producing a file that cannot become mangled in the first place.
The behaviour described here is Java's. Other languages read the same format with their own rules, and several of them assume UTF-8 outright, which is exactly why a file that works in one toolchain can break in another. The escaped form is the common ground: it is pure ASCII, so every reader of every persuasion agrees on it.
Why is it free?
Encoding a string and reading it back two ways is arithmetic your browser does instantly. There is no server in the path, so there is nothing to meter and no account to create.
Nothing is uploaded. The file you paste stays in this tab.