Notes › Tech Notes › What is \u4e2d? Converting Chinese text to and from Unicode escapes

What is \u4e2d? Converting Chinese text to and from Unicode escapes

When I took over that seven-year-old system, all I had to change was one line of UI copy: add a parenthetical note after "out of stock". The file was message_zh.properties, 1846 lines and 326 keys, the whole screen full of \uXXXX, and searching for the word stock hit nothing. I spent twenty minutes comparing lines to find the right one, then fumbled \u5de5 with a digit missing and the build failed with illegal escape character. That detour taught me one thing: those \u strings are not mojibake; they are the same Chinese characters written another way.

1. A code point is an ID number; \uXXXX is just its hexadecimal spelling

Unicode assigns every character an ID number called a code point, independent of bytes and of the language you write in. \u4e2d means "the code point of this character, written 4E2D in hex." The same character zhong can appear in several forms.

CharacterCode pointUnicode escapeHTML numeric entityDecimal code point
zhongU+4E2D\u4e2d中20013
wenU+6587\u6587有25991
gongU+5DE5\u5de5巧24039
juU+5177\u5177具20855

Two ranges are worth remembering: the Basic Multilingual Plane runs from U+0000 to U+FFFF, 65536 code points in total, and most common symbols and Chinese characters fall inside it; the main CJK block runs from U+4E00 to U+9FFF, 20992 code points. Rare characters and emoji above U+FFFF cannot be expressed with a single four-digit escape and need a surrogate pair: U+1F600 has to be written as the two parts \ud83d\ude00.

2. Five things that look like mojibake but live on different layers

Mixing these layers up is the fastest way to corrupt data.

Looks likeWhat it really isWhich layer
\u4e2d\u6587Escaped spelling of character code pointsSource code / JSON string layer
中The same code point as a decimal entityHTML markup layer
%E4%B8%ADThe three UTF-8 bytes E4 B8 AD of one Chinese character, percent-encodedURL transport layer
D6 D0The two GBK bytes of the same characterByte encoding layer
中文UTF-8 bytes displayed as Latin-1Already broken: a display accident

The last row is true mojibake: the bytes were interpreted wrongly, and no "convert back to Chinese" button can rescue it; you have to go to the source and fix the decoding. Likewise, the classic replacement-character mess comes from reading EF BF BD replacement characters again as GBK. I have seen people feed %u4E2D to decodeURIComponent and get nothing but URI malformed; that is the awkward legacy of escape(), belonging to neither world.

3. How I finally changed that line

  1. Locate it. I ran the whole file through Unicode Converter to get a plain Chinese version, searched that result for the word stock, took the key name, and went back to the original file to edit that line. I did not touch a single character of the original, to avoid invisible differences from a full round trip.
  2. Confirm the form. A properties file is read line by line, so the escape uses a single backslash, \u5de5; if the same text has to sit inside a Java source string, it becomes \\u5de5. One backslash too few or too many and the compiler just throws an illegal escape error.
  3. When generating the replacement line, I used the non-ASCII-only mode, so letters, digits and half-width punctuation stay as they are and the diff shows only the characters I actually changed; converting the whole selection turns every line into escapes and reviewers cannot see what changed.
  4. When I need a form a page can use directly, I switch the same text to decimal mode and get entities such as 中.

For the percent layer I use other tools: URL Encoder and Decoder works on byte sequences, so %E4%B8%AD is its business; Text Encoder handles full-width versus half-width forms and ASCII values. The three cannot replace one another; they sit on different layers.

4. A few numbers you can copy directly

  • The same two-character word: 2 characters, 6 bytes in UTF-8, 4 bytes in GBK, and 12 ASCII characters when written as \u4e2d\u6587; one escaped Chinese character always takes 6 characters.
  • Anywhere a quota is counted in characters, this hurts: signatures, SMS templates, config values. Full escaping multiplies the length by six, and a cut in the middle leaves a fragment like \u4e, which is a syntax error.
  • The characters you cannot see: \u3000 is the full-width space (12288), \u00a0 is the no-break space (160), and \u201c / \u201d are curly Chinese quotation marks (8220 / 8221). Copy text from a document or a chat window and nine times out of ten it carries them; restore to Chinese before find-and-replace, or the operation is meaningless.
  • Do not lose track of the backslash layers: a properties file uses a single backslash, \u5de5; inside a Java source string it becomes \\u5de5; put that text into JSON and another layer is peeled on. Each layer adds one escape, and mistakes are usually a missing one somewhere in between.

5. Common questions

Q: What is the 4e2d in \u4e2d?

It is the Unicode code point of the character zhong, 4E2D in hex, which is 20013 in decimal, so the HTML entity is written 中. Both point to the same character; the only difference is hex versus decimal.

Q: Does writing escapes instead of Chinese characters change how the code runs?

After parsing they are exactly equivalent; it is the same character. The difference is on the human side: an escaped form defeats full-text search, code review and copy checks, and it assumes the file itself can only safely hold ASCII.

Q: Why did older Java config files have to be escaped?

Before JDK 9, PropertyResourceBundle always read these files as ISO-8859-1, so Chinese had to be stored as \uXXXX escapes, and early JDKs shipped a dedicated converter called native2ascii, later deprecated. That explains why the file in my hands was full of escapes: it was a legacy constraint, not corrupt data.

Q: Why do character counts never match when copy contains emoji?

Because characters above the BMP take two UTF-16 code units: '\ud83d\ude00'.length is 2, so one smiley counts as two characters in any length check. Count by code point with something like codePointAt, and in source you can also write \u{1f600}, supported since ES6. As for the Invalid Unicode escape sequence error, it usually comes from a truncated escape such as a lone \u4e that cannot fill four hex digits.

Q: Can converting hundreds of lines at once break something?

The conversion itself is lossless; the risk is overwriting the original. My habit is to use the converted copy only for reading, never for saving, make the actual edits in the original file, and check with a diff before committing that it still has 1846 lines and only the target keys changed.

That line, out of stock with a note about changing it in settings, went in with the original single-backslash escape and compiled. Looking back, the valuable part of those twenty minutes was not finding a converter but figuring out which layer I was dealing with: escapes and entities are two spellings of one code point and convert losslessly; the percent layer belongs to URLs; and once bytes have been decoded wrongly, as with 中文, only fixing the decoding at both ends helps. No convert-to-Chinese button can save it.

📎 Related articles

PNG compressed three times only lost 426 bytes: the real boundary of lossless compression 2026-10-22 How Many Times Bigger a PNG Gets After Converting From WebP: When It Is Unavoidable and How to Keep the Growth Down 2026-10-22 Three Reasons the Small Text Smudges When a Screenshot Is Shrunk to a Quarter 2026-10-22 Cropped to the Same 300x300, Why Does the Avatar Always Sit Half a Cell Low-Right 2026-10-22 Forecasting 18 months at 1.7 times a month: why the script and the sheet give two numbers 2026-10-22