Empty on WindowsLowercase u with umlaut
ASCII 129 is empty on Windows and ü in old DOS.
Byte 129 (0x81) has no character in Windows-1252, and tools disagree about what to do with it. Python's 'cp1252' codec follows Microsoft's original table, where the slot is undefined, so decoding fails with UnicodeDecodeError: 'charmap' codec can't decode byte 0x81. Browsers follow the WHATWG Encoding Standard instead, which maps 0x81 to the invisible control character U+0081, so the same bytes load without an error and show nothing. If Python throws, the file may not be Windows-1252 at all. In UTF-8, 0x81 is a continuation byte that can finish many characters (after C3 it completes Á, for example), so check the bytes around it before you switch the encoding.
ü (Small U with Umlaut) is byte 129 in code page 437, the original IBM PC character set, and maps to Unicode U+00FC. Windows-1252 leaves byte 129 unassigned, so German DOS text read as Windows-1252 drops the letter or turns it into an invisible control code, and Müller comes out as Mller. Code page 850 kept ü at 129 too, so this byte decodes the same under either DOS code page. Its capital Ü is 154 in DOS.
/* Byte 129 (0x81) has no character in Windows-1252.MultiByteToWideChar passes it through as the control code U+0081,so treat it as a sign that the text is not really Windows-1252. */unsigned char b = 129;char c = (char)129; /* -127 on x86, where char is signed */
#include <stdio.h>int main(void) {/* Byte 129 is ü only on a console using code page 437(chcp 437 on Windows, or DOSBox). On a UTF-8 terminal thelone byte 0x81 is invalid and prints as garbage, often �. */putchar(129);/* char is signed on x86, so a plain char holding 0x81 is -127.Use unsigned char when you compare or index by byte value. */char c = (char)129;unsigned char u = 129;printf("\n%d %d\n", c, u); /* -127 129 *//* Portable: print the Unicode character as UTF-8 instead. */printf("\u00FC\n"); /* C3 BC */return 0;}
ü is also ASCII 252 on Windows, which has the full guide.
Python is reading a UTF-8 file as Windows-1252, the default for open() on US and Western European Windows, and hit byte 81, which Windows-1252 leaves empty. In Spanish text that's the second byte of Á. Pass the encoding explicitly with `open(path, encoding='utf-8')`, or set PYTHONUTF8=1 so UTF-8 becomes the default for the whole process.
The leading zero switches you to the Windows-1252 table, and byte 129 is empty there, so you get an invisible control character or nothing at all. Drop the zero: Alt+129 reads the DOS table and gives ü. If you want the zero-style code anyway, ü sits at Alt+0252 on the Windows side.
Convert the file from the DOS code page once and keep the UTF-8 copy: `iconv -f CP850 -t UTF-8 old.txt > new.txt`. Read as Windows-1252, the ü lands on the empty byte 129, so Müller becomes Mller. The other umlauts don't vanish but turn into quotation marks, with ä showing as „ and ö as ”.