Vim ist einer der wenigen Editoren, der Zeichenkodierungen und Zeilenenden vollständig explizit behandelt — jede Datei hat eine Kodierung (fileencoding) und ein Zeilenende-Format (fileformat), beide sind sichtbar und veränderbar. Was in vielen grafischen Editoren als „kaputte Sonderzeichen" oder „komische unsichtbare Leerzeichen" daherkommt, lässt sich in Vim diagnostizieren und korrigieren. Dieser Artikel deckt die Konzepte ab: den Unterschied zwischen encoding (Vim-intern) und fileencoding (datei-spezifisch), wie man Legacy-Encodings wie CP1252 oder ISO-8859-1 öffnet, den Wechsel zwischen Unix-LF, Windows-CRLF und alt-Mac-CR, sichtbare Steuerzeichen via listchars und das BOM-Handling.
encoding vs. fileencoding
Vim unterscheidet zwei Encoding-Begriffe, und ihre Verwechslung ist die häufigste Quelle für Encoding-Fehler:
| Option | Wirkung |
|---|---|
encoding | Vim-intern: wie Vim Strings im Speicher hält und im Terminal anzeigt |
fileencoding | datei-spezifisch: in welcher Kodierung Vim die aktuelle Datei liest und schreibt |
Beim Öffnen einer Datei macht Vim Folgendes:
- Versucht, das Encoding der Datei zu erraten (oft per BOM, sonst per Heuristik der
fileencodings-Liste). - Speichert das erkannte Encoding pro Buffer als
fileencoding. - Liest die Datei mit
fileencodingund konvertiert intern zuencoding. - Beim Speichern wird wieder zurück nach
fileencodingkonvertiert.
encoding ist also Vims interne Lingua franca. Der heutige Default und einzig sinnvolle Wert ist UTF-8:
" Vim-internes Encoding: immer UTF-8 (Default seit Vim 7.4.1799)
set encoding=utf-8
" Liste der Encodings, die Vim beim Öffnen versucht — Reihenfolge
" bedeutet Priorität. utf-8 zuerst, dann westeuropäische Klassiker.
set fileencodings=utf-8,utf-16,cp1252,iso-8859-15,latin1
" Default-Encoding beim Speichern neuer Dateien
set fileencoding=utf-8Diese drei Zeilen sind heute Standard. Nur sehr alte oder sehr spezifische Setups brauchen Abweichungen.
Aktuelle Werte anzeigen
Zu jeder offenen Datei lässt sich Encoding und Zeilenende-Format direkt abfragen:
:set encoding? " z. B. encoding=utf-8 (Vim-intern)
:set fileencoding? " z. B. fileencoding=utf-8 (für diese Datei)
:set fileformat? " z. B. fileformat=unix (LF) | dos (CRLF) | mac (CR)
:set bomb? " bomb / nobomb — BOM-Marker am Datei-AnfangEine kompakte Variante: alle vier Werte in einer Statusline-Komponente sichtbar machen.
" Statusline-Komponente mit Encoding und Format
set statusline=%f\ %m%r%h%w\ [%{&fileencoding}/%{&fileformat}]%=%l/%L,%c
set laststatus=2Damit ist auf einen Blick sichtbar, ob die aktuelle Datei UTF-8 oder Latin1 ist, ob die Zeilenenden Unix oder DOS sind. Plugins wie vim-airline zeigen das ebenfalls in der Statusline an.
Legacy-Encodings öffnen
Wenn Vim eine Datei mit einer falschen Annahme öffnet — z. B. eine alte Windows-Datei in CP1252 wird als UTF-8 interpretiert, was zu kaputten Umlauten führt —, hilft das Re-Öffnen mit explizitem Encoding:
" Datei in CP1252 öffnen (klassisches Windows-Latin)
:e ++enc=cp1252 alte-datei.txt
" ISO-8859-1 / Latin-1
:e ++enc=latin1 archiv.txt
" UTF-16 mit BOM-Detection
:e ++enc=utf-16 ms-export.txt
" Aktuelle Datei mit anderem Encoding neu laden
:e ++enc=cp1252++enc= ist ein File-Encoding-Argument für den :e-Befehl — Vim öffnet die Datei mit dieser Annahme statt mit der Default-Heuristik. Wer regelmäßig Legacy-Encodings sieht, kann auch die fileencodings-Liste so erweitern, dass Vim sie automatisch erkennt:
" UTF-8 zuerst, dann CP1252 als Fallback für Windows-Legacy
set fileencodings=utf-8,utf-16,cp1252,iso-8859-15,latin1Hinweis: die Reihenfolge ist wichtig. Vim probiert die Liste von links nach rechts. UTF-8 ist „streng" — wenn ein Byte-Muster nicht UTF-8-konform ist, wird Vim weiterversuchen. CP1252 und Latin1 sind „permissiv" — fast jede Byte-Sequenz wird akzeptiert. Daher gehört Latin1 immer ans Ende der Liste; sonst werden saubere UTF-8-Dateien als Latin1 fehlinterpretiert.
Encoding konvertieren
Um eine Datei von einem Encoding ins andere zu konvertieren, sind zwei Schritte nötig: richtig öffnen, anders speichern.
" 1. Mit dem richtigen Source-Encoding öffnen
:e ++enc=cp1252 alte-datei.txt
" 2. Auf das Ziel-Encoding umstellen
:set fileencoding=utf-8
" 3. Speichern — Vim schreibt in UTF-8
:wDas ist die typische Konvertierungs-Sequenz. Beim Speichern in Schritt 3 konvertiert Vim aus dem internen encoding=utf-8 zurück in das jetzt geänderte fileencoding=utf-8 — also keine Konvertierung, sondern direktes Schreiben.
Für Bulk-Konversionen ist die Shell besser geeignet — iconv ist das Standard-Werkzeug:
# Eine Datei
iconv -f cp1252 -t utf-8 alte.txt > neue.txt
# Alle .txt im Verzeichnis
for f in *.txt; do
iconv -f cp1252 -t utf-8 "$f" > "$f.utf8" && mv "$f.utf8" "$f"
doneIn Vim lässt sich iconv als externer Filter aufrufen (:%!iconv -f cp1252 -t utf-8), wenn man den Buffer-Inhalt direkt konvertieren will, ohne :e ++enc= zu nutzen.
Zeilenenden: fileformat
Drei Zeilenende-Konventionen existieren historisch:
fileformat | Trennzeichen | Plattform |
|---|---|---|
unix | \n (LF) | Linux, macOS (seit OS X), BSD, moderner Standard |
dos | \r\n (CRLF) | Windows, viele Netzwerk-Protokolle |
mac | \r (CR) | klassisches Mac OS bis Version 9 — heute praktisch ausgestorben |
Vim erkennt das Format einer Datei automatisch (über die fileformats-Liste, Default unix,dos) und zeigt es als fileformat an. Wer den Wert wechseln möchte:
" Aktuelles Format anzeigen
:set fileformat?
" Auf Unix-LF wechseln
:set fileformat=unix
" Auf Windows-CRLF wechseln
:set fileformat=dos
" Speichern — Vim schreibt mit dem neuen Format
:wIn der Statusline ist das Format sichtbar als [unix]/[dos]/[mac] neben dem Dateinamen. Wenn nichts angezeigt wird, ist es Unix (der Default wird oft nicht explizit dargestellt).
Häufige Stolperfallen
^Mam Zeilenende: typischer Indikator, dass eine Datei mit CRLF gespeichert ist und Vim sie als Unix interpretiert hat. Das^Mist das\r-Zeichen, das in Unix-Augen nicht zum Zeilenende gehört. Lösung::set fileformat=dos, dann erkennt Vim die CRLF-Paare als Zeilenenden und das^Mverschwindet.- Mixed line endings: eine Datei mit teilweise LF und teilweise CRLF entsteht meist durch versehentliches Mischen von Editoren. Vim macht das beim Speichern zu einem konsistenten Format. Zum Aufräumen:
:%s/\r//gentfernt alle übrig gebliebenen\r-Zeichen.
" Wenn Vim die Datei als unix gelesen hat, aber CRLF drin ist:
:%s/\r//g " alle \r aus dem Buffer entfernen
:w " als Unix speichern (fileformat=unix)Unsichtbare Steuerzeichen sichtbar machen
Tabs, Trailing-Whitespace, nicht-druckbare Zeichen — alles unsichtbar im normalen Vim-Buffer. Mit :set list macht Vim sie sichtbar, in Kombination mit listchars lässt sich die Darstellung konfigurieren:
" Steuerzeichen darstellen
set list
" Wie sie aussehen sollen
set listchars=tab:▸\ ,trail:·,extends:❯,precedes:❮,nbsp:␣
" Bedeutung:
" tab = Darstellung eines Tab-Zeichens (hier: Pfeil + Leerzeichen)
" trail = Trailing-Whitespace am Zeilenende (Mittelpunkt)
" extends = Zeile geht über den rechten Rand hinaus (geht es weiter)
" precedes = Zeile reicht über den linken Rand hinaus
" nbsp = non-breaking space (kritisch für YAML/Markdown)Mit dieser Konfig wird offensichtlich, wenn eine Datei Tabs statt Spaces nutzt (Pfeile), Trailing-Whitespace hat (Mittelpunkte am Zeilenende) oder kaputte non-breaking-Spaces (␣) enthält — alles häufige Quellen subtiler Bugs.
Zum Toggeln im Alltag:
" <leader>l toggelt die Darstellung
nnoremap <silent> <leader>l :set list!<CR>BOM — der Byte-Order-Mark
Manche Encodings nutzen einen Byte-Order-Mark (BOM) — drei Bytes am Datei-Anfang, die das Encoding identifizieren. In UTF-8 ist das EF BB BF, das in einer Hex-Anzeige als  oder ähnlich auftaucht.
| Encoding | BOM | Sichtbar als |
|---|---|---|
| UTF-8 | EF BB BF | nicht-druckbar (manche Tools zeigen ) |
| UTF-16 LE | FF FE | nicht-druckbar |
| UTF-16 BE | FE FF | nicht-druckbar |
In Vim wird das BOM-Verhalten über die Option bomb (true/false) gesteuert. Beim Öffnen einer Datei erkennt Vim automatisch, ob eine BOM vorhanden ist; beim Speichern hängt das Schreiben des BOM davon ab, ob bomb gesetzt ist.
:set bomb? " ist BOM aktiv für diese Datei?
:set bomb " BOM beim Speichern schreiben
:set nobomb " BOM weglassen
:w " neue Datei-Schreibung mit/ohne BOMPraktische Empfehlung:
- UTF-8 ohne BOM ist der Default-Standard in Unix- und Web-Welt. Das ist die richtige Wahl für die meisten Setups.
- UTF-8 mit BOM wird unter Windows traditionell von Notepad und einigen alten Office-Tools erwartet. Bei XML- oder INI-Dateien für Windows-Tools manchmal nötig.
- UTF-16 mit BOM für Windows-Export-Formate (z. B. Excel-CSV-UTF-16).
In Web-Workflows ist UTF-8-ohne-BOM Pflicht: das BOM kann zu unsichtbaren Zeichen am HTML-Anfang führen, die das Rendering brechen. Wer eine Web-Datei sieht und unerklärliche Whitespace-Phänomene am Anfang hat, prüft als erstes :set bomb?.
Komplette Setup-Vorlage
Eine bewährte Konfiguration für moderne Vim-Setups:
" ============================================================
" Encoding und Zeilenenden
" ============================================================
" Vim-internes Encoding (Default seit 7.4.1799, explizit setzen)
set encoding=utf-8
" Default-Encoding beim Speichern neuer Dateien
set fileencoding=utf-8
" Reihenfolge der Erkennung beim Öffnen
" (UTF-8 zuerst, Latin1 als Fallback ans ENDE)
set fileencodings=utf-8,utf-16,cp1252,iso-8859-15,latin1
" Default-Zeilenende-Format und Erkennungs-Reihenfolge
set fileformat=unix
set fileformats=unix,dos,mac
" Kein BOM (Standard im Unix-/Web-Umfeld)
set nobomb
" Sichtbare Darstellung von Steuerzeichen
set list
set listchars=tab:▸\ ,trail:·,extends:❯,precedes:❮,nbsp:␣
" Toggle-Mapping
nnoremap <silent> <leader>l :set list!<CR>
" Trailing-Whitespace beim Speichern entfernen (optional, aggressiv)
" autocmd BufWritePre * :%s/\s\+$//eDiese Konfiguration deckt 95 % der Anwendungsfälle ab. Die kommentierte letzte Zeile (autocmd BufWritePre) ist optional und sehr meinungsstark — sie entfernt automatisch Trailing-Whitespace beim Speichern, was in vielen Projekten gewünscht ist, in anderen aber als zu invasiv gilt (z. B. Markdown mit absichtlichen Trailing-Zeilen-Pausen).
Häufige Stolperfallen
`encoding=utf-8` ist nicht dasselbe wie `fileencoding=utf-8`
Vims internes Encoding und das Datei-Encoding sind getrennt. encoding ist Vim-intern und sollte fast immer auf UTF-8 stehen. fileencoding ist pro Datei und beschreibt, was auf der Platte landet. Wer beides nicht unterscheidet, ist bei Encoding-Problemen oft verwirrt, warum Änderungen nicht greifen.
`latin1` gehört ans ENDE der `fileencodings`-Liste
Latin1 ist permissiv — jede Byte-Sequenz wird akzeptiert. Wenn es vor UTF-8 in der Liste steht, werden saubere UTF-8-Dateien fälschlicherweise als Latin1 interpretiert und Umlaute kommen kaputt an. Reihenfolge: streng zuerst, permissiv zuletzt.
`^M` am Zeilenende ist ein CRLF-Indikator
Vim hat die Datei als unix-Format gelesen, aber sie hat in Wirklichkeit CRLF-Zeilenenden. Die \r-Bytes hängen jetzt am Ende jeder Zeile als sichtbares ^M. Fix: :set fileformat=dos (Vim erkennt nun die CRLF-Paare), oder :%s/\r//g zum Aufräumen plus :w als Unix-Datei.
BOM in HTML/JS/CSS bricht das Rendering
Ein UTF-8-BOM am Anfang einer HTML-Datei führt zu einem unsichtbaren Zeichen, das in manchen Browsern als Whitespace gerendert wird — und Layout-Bugs verursacht. Web-Dateien sollten immer ohne BOM gespeichert werden. set nobomb in der .vimrc als Default.
Non-breaking spaces sind unsichtbar — und brechen YAML
In YAML und Markdown sind nbsp-Zeichen (U+00A0) ein häufiger Bug: optisch wie Leerzeichen, vom Parser aber nicht als Whitespace erkannt. Mit listchars=...nbsp:␣ werden sie sichtbar. Häufige Quelle: Copy-Paste aus Word, Browser-Textfeldern oder PDFs.
`iconv` ist Vim-extern, oft schneller für Bulk-Konversion
Wer 50 Dateien konvertieren will, ruft besser iconv im Loop auf, statt jede in Vim zu öffnen. Vim ist für interaktive Konversionen gut, iconv für skriptbare Bulk-Operationen.
Weiterführende Ressourcen
Externe Quellen
- Vim Help: encoding-values — Liste aller bekannten Encoding-Namen.
- Vim Help: fileencoding — datei-spezifisches Encoding.
- Vim Help: fileformat — Zeilenende-Format.
- Vim Help: listchars — sichtbare Steuerzeichen-Konfiguration.
- Vim Help: bomb — BOM-Steuerung.
- iconv (GNU) — externer Encoding-Konverter.