CSV – opanuj chaos cyferek i literek

desi9n.pl logo desi9n.pl

Mapa strony
PL EN

CSV to jeden z najprostszych i najpopularniejszych formatów przechowywania danych tabelarycznych. W artykule wyjaśniamy, jak działa CSV, jakie są jego ograniczenia i jak bezpiecznie go używać w projektach IT.

Porządkowanie danych z pliku CSV – cyfry, teksty i separatory w uporządkowanej tabeli
Ilustracja przedstawiająca porządkowanie danych z chaotycznego pliku CSV – cyfry, litery i separatory zamienione w czytelną tabelę.

Dlaczego CSV wciąż dominuje w wymianie danych

CSV (Comma-Separated Values) to format, który przetrwał dekady nie dlatego, że jest doskonały, lecz dlatego, że jest prosty. Plik tekstowy, wiersze oddzielone znakiem nowej linii, kolumny — separatorem. Każdy system potrafi go wyeksportować, każdy arkusz kalkulacyjny — zaimportować. W projektach, które realizujemy w desi9n, CSV pojawia się regularnie: import danych klientów do CRM, eksport zamówień z e-commerce, zasilanie hurtowni danych BI, wymiana danych między systemami księgowymi. Problem w tym, że za pozorną prostotą kryje się szereg pułapek, które potrafią zepsuć dane w sposób trudny do wykrycia.

Separator — przecinek, średnik czy tabulator

Nazwa mówi „comma-separated", ale w Polsce i większości krajów europejskich domyślnym separatorem w Excelu jest średnik (;). Powód: przecinek pełni u nas funkcję separatora dziesiętnego (3,14 zamiast 3.14). Jeśli wyeksportujesz plik z przecinkiem jako separatorem i otworzysz go na polskim Windowsie w Excelu — wszystkie kolumny wpadną do jednej. LibreOffice Calc przynajmniej pyta o separator przy imporcie; Excel domyślnie bierze ustawienia regionalne systemu.

Inne spotykane separatory to tabulator (\t — pliki TSV), pipe (|) i znak ASCII 31 (unit separator, rzadko). Przy projektowaniu eksportu danych w systemach dedykowanych pozwalamy użytkownikowi wybrać separator i kodowanie — to kilka linii kodu, a oszczędza godziny wsparcia technicznego.

Kodowanie znaków — UTF-8, BOM i Windows-1250

Polskie znaki diakrytyczne (ą, ę, ó, ś, ź, ż, ć, ń, ł) to źródło połowy problemów z CSV. Plik zapisany w UTF-8 bez BOM (Byte Order Mark) otwarty w Excelu na Windowsie może wyświetlić „zażółć gęślą jaźń" jako „zażółć gÄ™ÅlÄ jaźń". Rozwiązanie: dodaj BOM (3 bajty: EF BB BF) na początku pliku. Excel rozpozna wtedy UTF-8 poprawnie. LibreOffice i Google Sheets radzą sobie bez BOM.

Starsze systemy polskie (szczególnie księgowe i ERP z lat 2000–2010) eksportują CSV w kodowaniu Windows-1250 (lub ISO 8859-2). Przy imporcie do nowoczesnego systemu potrzebujesz konwersji — w PHP: mb_convert_encoding($line, 'UTF-8', 'Windows-1250'), w Pythonie: open(path, encoding='cp1250'). Bez tego polskie znaki zamieniają się w pytajniki lub krzaki.

Typy danych — CSV nie wie, co przechowuje

Format CSV nie definiuje typów — wszystko jest ciągiem tekstowym. Interpretacja zależy od programu odczytującego, co prowadzi do zaskakujących efektów:

  • Liczby z zerami wiodącymi — kod pocztowy 01-234 lub numer konta 0012345 trafia do Excela jako liczba i traci zera. Obejście: otocz wartość cudzysłowem i poprzedź znakiem równości (="01-234") lub importuj kolumnę jako tekst.
  • Daty — zapis 03/04/2025 może być interpretowany jako 3 kwietnia lub 4 marca, zależnie od ustawień regionalnych. Stosuj ISO 8601 (2025-04-03).
  • Separatory dziesiętne1,5 w polskim pliku to półtora, ale system anglojęzyczny odczyta to jako dwie kolumny.
  • Wartości logicznetrue/false, 1/0, tak/nie — brak standardu, każdy system interpretuje po swojemu.

CSV injection — zagrożenie, o którym mało kto pamięta

Jeśli komórka CSV zaczyna się od znaku =, +, - lub @, Excel i LibreOffice potraktują ją jako formułę. Atakujący może wstawić do pola formularza wartość typu =CMD|'/C calc'!A0 — po otwarciu wyeksportowanego CSV w Excelu system wykona polecenie systemowe. To nie teoria: OWASP dokumentuje ten wektor ataku jako „CSV Injection" (inaczej „Formula Injection").

Obrona jest prosta: przy eksporcie danych do CSV poprzedź podejrzane wartości znakiem apostrofu (') lub tabulatorem. W PHP i Pythonie warto napisać funkcję sanityzującą, która sprawdza pierwszy znak każdej komórki. Przy imporcie CSV do bazy danych stosuj parametryzowane zapytania — nigdy nie wstawiaj wartości z CSV bezpośrednio do SQL.

Narzędzia do walidacji i naprawy CSV

Zanim zaimportujesz plik do bazy danych, warto go zwalidować. W Pythonie biblioteka csvkit oferuje narzędzie csvclean, które wykrywa niezamknięte cudzysłowy i niespójną liczbę kolumn. W PHP natywna funkcja fgetcsv() radzi sobie z prostymi przypadkami, ale przy dużych plikach (powyżej 100 MB) lepiej użyć SplFileObject w trybie strumieniowym — unikniesz załadowania całego pliku do pamięci. W systemach, które budujemy, import CSV zawsze przechodzi przez etap walidacji: sprawdzenie kodowania, liczby kolumn, typów danych i obecności wymaganych pól. Dopiero po walidacji dane trafiają do bazy.

Typowe błędy eksportu i importu

  • Brak wiersza nagłówkowego lub niezgodność nagłówków z danymi (przesunięcie kolumn).
  • Niezamknięte cudzysłowy — jedno pole z cytatem przesuwa wszystkie kolejne kolumny.
  • Znaki nowej linii wewnątrz pola — jeśli pole nie jest otoczone cudzysłowami, parser potraktuje je jako nowy wiersz.
  • Mieszane kodowanie w jednym pliku — zdarza się, gdy dane pochodzą z różnych źródeł i są łączone bez konwersji.
  • Puste wiersze na końcu pliku — niektóre edytory dodają pusty wiersz, co parser interpretuje jako dodatkowy rekord z pustymi polami.
  • Eksport z Excela przez „Zapisz jako CSV" bez sprawdzenia ustawień — Excel użyje separatora z ustawień regionalnych systemu, co może być niezgodne z oczekiwaniami systemu importującego.

Kiedy CSV to za mało

CSV sprawdza się przy płaskich, tabelarycznych danych — lista klientów, katalog produktów, eksport zamówień. Gdy dane mają strukturę zagnieżdżoną (np. zamówienie z wieloma pozycjami, każda z wariantami), CSV wymusza denormalizację i powtarzanie wierszy. W takich przypadkach lepszym wyborem jest JSON (czytelny, obsługiwany natywnie przez większość API), JSON Lines (jeden obiekt JSON per wiersz — łatwy do strumieniowania) albo Apache Parquet (kolumnowy format binarny, idealny do analityki na dużych zbiorach). Przy integracji systemów w czasie rzeczywistym zwykle lepiej postawić na REST/GraphQL API niż na wymianę plików.

Co z tym zrobić u siebie

  1. Ustal standard eksportu: UTF-8 z BOM, średnik jako separator (dla polskich użytkowników), ISO 8601 dla dat.
  2. Dodaj sanityzację CSV injection przy każdym eksporcie danych użytkownika.
  3. Przetestuj import na realnych danych — z polskimi znakami, zerami wiodącymi i datami w różnych formatach.
  4. Napisz walidator importu: sprawdzenie kodowania, liczby kolumn, typów — zanim dane trafią do bazy.
  5. Jeśli CSV nie wystarcza — rozważ JSON, Parquet lub bezpośrednie API. Przy budowie integracji między systemami dobieramy format do skali i wymagań.

Źródła

Tagi artykułu:

Czy podobał Ci się ten artykuł? Szukasz partnera, który pomoże Ci w realizacji nowoczesnych rozwiązań? Jeśli chcesz wdrożyć omawiane rozwiązania w swoim projekcie, skontaktuj się z nami i rozpocznijmy współpracę!

Kontakt