CSV, kimsenin sevmediği ama herkesin kullandığı formatlardan biridir. 1970'lerden beri var, hâlâ gezegendeki her elektronik tablo uygulamasının varsayılan dışa aktarma formatı ve şu anda muhtemelen veri iş akışınızın bir yerinde bulunuyor. Format önemsiz derecede basit görünür — sadece virgülle ayrılmış değerler — ancak doğru şekilde ayrıştırmak şaşırtıcı derecede kolay yanlış yapılabilir. Nasıl gerçekten çalıştığını, nerede zorlaştığını ve Python ile JavaScript'te kendinize zarar vermeden nasıl işleyeceğinizi inceleyelim.
CSV Gerçekte Nedir
CSV, Virgülle Ayrılmış Değerler (Comma-Separated Values) anlamına gelir. Bir CSV dosyası düz metin — ikili kodlama yok, meta veri yok, satırlar ve sütunların ötesinde yapı yok. Her satır bir kayıttır, satırdaki her değer bir ayırıcıyla (genellikle virgül) ayrılır ve ilk satır geleneksel olarak sütun adlarını içeren başlık satırıdır. Gerçek bir CSV şöyle görünür:
order_id,customer,product,quantity,unit_price,shipped
1001,Alice Nguyen,USB-C Hub,2,34.99,true
1002,Bob Martinez,Mechanical Keyboard,1,129.00,false
1003,Alice Nguyen,HDMI Cable,3,12.50,true
1004,Carol Smith,Webcam 1080p,1,79.95,falseHepsi bu — altı sütun, dört veri satırı ve bir başlık. Açılı ayraç yok, kaşlı ayraç yok,
henüz tırnak işareti gerekmiyor. Bu basitlik tam da CSV'nin devam etmesinin nedenidir: yeryüzündeki
hemen her araç onu açabilir, okuyabilir ve üretebilir. Excel, Google Sheets, PostgreSQL'in COPY
komutu, pandas, R'nin read.csv()'si — hepsi kutudan çıkar çıkmaz CSV desteğiyle gelir.
Ödünleşim, formatın neredeyse hiç yapısı olmamasıdır: tür yok, iç içe geçme yok, şema yok.
Siz aksi kararlaştırana kadar her değer bir dizedir.
RFC 4180 — Gerçekten Uygulanmayan Standart
Bir spesifikasyon var: RFC 4180, 2005'te yayımlandı. CRLF satır sonları, çift tırnak kaçışı ve gömülü virgüllerin nasıl işleneceği gibi konuları tanımlar. Ancak şu var — RFC 4180 bilgilendiricidir, standart değildir. Zaten yaygın olan uygulamayı açıklar, kanunlaştırmaz. Kimse onu izlemek zorunda değildir ve uygulamada hemen hiç kimse tam olarak izlemez.
Sonuç, CSV diyalekti kaosudur. CRLF yerine LF kullanan dosyalarınız, ilk satırın başlık olup olmadığı belirsiz dosyalarınız, sonda yeni satır olan ve olmayan dosyalarınız, Excel'in başına UTF-8 BOM eklediği dosyalarınız var. CSV hakkındaki Wikipedia makalesi, pratikte değişen her şeyin sağlam bir özetine sahiptir. En güvenli yaklaşım: kendiniz üretmediğiniz bir CSV dosyası hakkında hiçbir şey varsaymayın ve virgülleri naif bir şekilde bölmek yerine her zaman uygun bir ayrıştırıcı kullanın.
Tırnak Kuralları: Değerlerin İçinde Virgül Göründüğünde
"Sadece virgülleri böl" yaklaşımının çöktüğü yer burasıdır. Bir değer virgül içeriyorsa ne olur? Ya da yeni satır? Ya da çift tırnak işareti? RFC 4180 — ve çoğu gerçek ayrıştırıcı — alanı çift tırnak içine alarak bunu işler. İşte kuralların tam seti:
- Bir alan virgül, yeni satır veya çift tırnak içeriyorsa, tüm alanı çift tırnak içine alın
- Bir alan çift tırnak içeriyorsa, onu ikiye katlayarak kaçış uygulayın (
"") - Tırnak içindeki alanlar birden fazla satıra yayılabilir — yeni satır değerin bir parçası olur
- Tırnak içindeki boşluklar anlamlıdır ve korunmalıdır
order_id,customer,notes,unit_price
1005,David Lee,"Wants gift wrapping, express shipping",45.00
1006,Emma Brown,"Said: ""please handle with care""",89.99
1007,Frank Wu,"Address:
123 Main St
Apt 4B",15.50Bu örnekte: David'in notes'u virgül içeriyor, bu yüzden tırnak içinde. Emma'nın notu
çift tırnak içeriyor, bu yüzden dış tırnakların içinde ikiye katlanıyor. Frank'in adresi birden fazla
satıra yayılıyor — satır sonları değerin bir parçası. Herhangi bir dildeki naif bir line.split(',')
bu üçünü de tamamen mahveder. Bu yüzden gerçek bir ayrıştırıcıya ihtiyaç duyuyorsunuz.
split doğru yapamaz.Ayırıcı Varyantlar: Sekmeler, Noktalı Virgüller, Kanallar
Adına karşın, CSV virgül kullanmak zorunda değildir. Birkaç yaygın varyant farklı ayırıcılar kullanır ve hepsini pratikte göreceksiniz:
- TSV (Sekmeyle Ayrılmış Değerler) — ayırıcı olarak
\tkullanır. Biyoinformatik (BLAST çıktısı, VCF dosyaları), veritabanı dışa aktarmaları ve değerlerin sıklıkla virgül içerdiği her yerde yaygındır - Noktalı virgülle ayrılmış — virgülün ondalık ayırıcı olduğu bölgelerde (Almanya, Fransa, AB'nin çoğu) Excel'in varsayılanıdır. Bir Avrupalı meslektaştan CSV alıp tek bir büyük sütun aldıysanız, nedeni budur
- Kanalla ayrılmış —
|kullanır. Sekmelerin ana çerçeve sistemleri tarafından kesilebileceği eski bankacılık ve sigorta veri dışa aktarmalarında yaygındır - Sabit genişlik — teknik olarak CSV değildir, ancak genellikle aynı kategoriye dahil edilir. Sütunlar sınırlandırılmak yerine sabit genişliklere kadar doldurulur
Çoğu CSV ayrıştırıcı, ayırıcıyı açıkça belirtmenize olanak tanır. Başkalarının tüketeceği bir CSV yazarken ayırıcınızı belgeleyin. Üretmediğiniz birini okurken, varsayım yapmadan önce ilk birkaç satırı kontrol edin. CSV Formatter, standart olmayan ayırıcılara sahip dosyaları incelemenize ve yeniden biçimlendirmenize yardımcı olabilir.
Python'da CSV Ayrıştırma
Python'ın standart kütüphanesi,
csv modülünü
içerir ve gerçekten iyidir. En sık kullanacağınız iki sınıf, satır-olarak-liste erişimi için
csv.reader ve satır-olarak-sözlük erişimi için csv.DictReader'dır
(ki bu neredeyse her zaman istediğiniz şeydir).
import csv
# csv.reader — each row is a list of strings
with open('orders.csv', 'r', encoding='utf-8', newline='') as f:
reader = csv.reader(f)
header = next(reader) # consume the header row
for row in reader:
order_id, customer, product, quantity, price, shipped = row
print(f"Order {order_id}: {quantity}x {product} for {customer}")
# csv.DictReader — each row is an OrderedDict keyed by the header
with open('orders.csv', 'r', encoding='utf-8', newline='') as f:
reader = csv.DictReader(f)
for row in reader:
if row['shipped'] == 'false':
print(f"Pending: {row['order_id']} — {row['customer']}")Her zaman eklenmesi gereken iki şey: encoding='utf-8' (veya dosyanın gerçekte
ne kullandığı) ve newline=''. Bu ikincisi kritiktir — csv modülü kendi
yeni satır işlemeini yapar ve ham baytlara ihtiyaç duyar. newline='' olmadan, Windows'ta
fazladan boş satırlar alabilirsiniz.
Yazma csv.writer ile aynı derecede basittir:
import csv
orders = [
{'order_id': 1008, 'customer': 'Grace Kim', 'product': 'Laptop Stand', 'quantity': 1, 'unit_price': 49.99, 'shipped': False},
{'order_id': 1009, 'customer': 'Henry Park', 'product': 'USB-C Hub', 'quantity': 2, 'unit_price': 34.99, 'shipped': True},
]
with open('new_orders.csv', 'w', encoding='utf-8', newline='') as f:
fieldnames = ['order_id', 'customer', 'product', 'quantity', 'unit_price', 'shipped']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(orders)
# To use a different delimiter (e.g. tab-separated)
with open('new_orders.tsv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f, delimiter='\t')
writer.writerow(['order_id', 'customer', 'product'])
writer.writerow([1008, 'Grace Kim', 'Laptop Stand'])csv modülü tüm tırnakları otomatik olarak işler — bir alan virgül veya yeni satır
içeriyorsa, bunu düşünmenize gerek kalmadan çift tırnak içine alır. Kütüphane kullanmanın tüm amacı budur.
JavaScript / Node.js'de CSV Ayrıştırma
JavaScript'in yerleşik bir CSV ayrıştırıcısı yoktur. Cazip olan şu:
// ❌ Don't do this — breaks immediately on quoted fields
const rows = csvText.split('\n').map(line => line.split(','));Herhangi bir değer virgül, tırnak içinde yeni satır veya kaçış uygulanan çift tırnak içerdiği anda bu başarısız olur. Gerçek bir şey için kütüphane kullanın. PapaParse en iyi seçimdir — hızlıdır, tüm uç durumları işler, hem tarayıcıda hem de Node.js'de çalışır ve büyük dosyalar için akış desteği sunar.
import Papa from 'papaparse';
import fs from 'fs';
// Parse a CSV string
const csvText = fs.readFileSync('orders.csv', 'utf8');
const result = Papa.parse(csvText, {
header: true, // first row becomes object keys
skipEmptyLines: true, // ignore blank lines at end of file
dynamicTyping: true, // converts "true"/"false" to booleans, numbers to numbers
});
console.log(result.data);
// [
// { order_id: 1001, customer: 'Alice Nguyen', product: 'USB-C Hub', quantity: 2, unit_price: 34.99, shipped: true },
// { order_id: 1002, customer: 'Bob Martinez', product: 'Mechanical Keyboard', quantity: 1, unit_price: 129, shipped: false },
// ...
// ]
// Check for parse errors
if (result.errors.length > 0) {
console.error('Parse errors:', result.errors);
}
// Generate CSV from an array of objects
const orders = [
{ order_id: 1008, customer: 'Grace Kim', product: 'Laptop Stand', quantity: 1, unit_price: 49.99 },
{ order_id: 1009, customer: 'Henry Park', product: 'USB-C Hub', quantity: 2, unit_price: 34.99 },
];
const csvOutput = Papa.unparse(orders);
fs.writeFileSync('export.csv', csvOutput, 'utf8');dynamicTyping seçeneği kullanışlıdır ancak bilmeye değer — "34.99" gibi
şeyleri otomatik olarak sayıya dönüştürür. Bu genellikle istediğiniz şeydir, ancak order_id
gibi bir alan CSV'de sayı olduğunda ama onu dize olarak istediğinizde sizi şaşırtabilir. Katı dize
çıktısına ihtiyacınız varsa kapatın.
CSV ve diğer formatlar arasında hızlı dönüşümler için CSV'den JSON'a aracı, kod yazmadan tarayıcıda en yaygın durumları işler — tek seferlik veri dönüşümleri için kullanışlıdır. Veriyi XML tabanlı bir sisteme beslemeniz gerekiyorsa CSV'den XML'e de mevcuttur.
Kesinlikle Karşılaşacağınız Yaygın Tuzaklar
İyi bir ayrıştırıcıyla bile, CSV'nin birkaç iyi bilinen mayını vardır. İşte en sık karşılaşılanlar:
- Excel'den BOM baytları. Excel bir CSV'yi "UTF-8" olarak dışa aktardığında, genellikle
başına UTF-8 BOM (
EF BB BFonaltılı veya karakter olarak\ufeff) ekler. Bu, ilk sütun başlığınınorder_idyerineorder_idgibi görünmesine neden olur. Python'da bunu otomatik olarak kaldırmak için dosyayıutf-8yerineencoding='utf-8-sig'ile açın. PapaParse bunu şeffaf bir şekilde işler. - CRLF vs LF satır sonları. RFC 4180 CRLF (
\r\n) belirtir, ancak Unix araçları LF (\n) üretir ve eski Mac dosyaları yalnızca CR (\r) kullanır. Bu nedenle Python'ıncsvmodülünewline=''gerektirir — üçünü de dahili olarak işler. Ham baytları okuyup manuel olarak bölüyorsanız,\r'yi açıkça kaldırmanız gerekir. - Kodlama sorunları. CSV, HTML'nin
<meta charset>'i veya XML'nin<?xml encoding="..."?>'i gibi kendi kodlamasını beyan etmenin bir yoluna sahip değildir. Excel dosyaları genellikle UTF-8 yerine Windows-1252'de (a.k.a. CP1252) kaydeder, bu da aksan işaretli karakterleri bozar.éyerineégibi karakterler görüyorsanız, bir UTF-8 dosyasının Latin-1 olarak çözümlendiği veya tam tersi bir durum söz konusudur. Kodlamayı her zaman dosyayı üreten kişiyle bant dışında belirleyin. - Tarih gibi görünen sayılar. Excel açarken veya kaydederken
1-2veya03/04gibi değerleri sessizce tarihlere dönüştürür. Ürün kodlarını veya sürüm numaralarını dışa aktarıyorsanız, bunu önlemek için Excel'de başına tek tırnak ekleyin ('1-2) — veya dosyayı üreten kişiye bunu yapmasını söyleyin. - Sondaki virgüller. Bazı dışa aktarıcılar her satırın sonuna sondaki virgülü ekler, bu da hayalet boş bir sütun oluşturur. Sağlam bir ayrıştırıcı bunu görmezden gelir; naif bir bölme fazladan boş bir dize öğesi oluşturur.
Garip görünen bir dosyayla çalışıyorsanız, CSV Doğrulayıcı, dosyayı işlemeye çalışmadan önce iyi biçimlendirilmiş olup olmadığını ve kodlama veya yapısal sorunları hızlıca söyleyebilir.
CSV vs JSON vs Excel — Ne Zaman Ne Kullanılır
Bu üç format pratikte çok örtüşür, ancak her birinin net bir avantajı vardır:
- CSV kullanın sistemler arasında düz, tablo halindeki verileri taşırken — veritabanı dışa aktarmaları, analitik ardışık düzenler, elektronik tablo içe aktarmaları, toplu veri yükleme. Evrensel olarak desteklenir, boyut olarak küçüktür ve git'te önemsiz şekilde karşılaştırılabilir. Kısıtlama: düzdür. İç içe geçme yok, tür yok, ilişki yok.
- JSON kullanın veri hiyerarşik olduğunda veya şema önemli olduğunda. Birden fazla satır öğesi olan bir sipariş, iç içe geçmiş nesnelerle bir yapılandırma dosyası, bir API yanıtı — bunlar doğal olarak JSON'dır. CSV sizi veriyi normalden çıkmaya veya kendi iç içe geçme kuralınızı icat etmeye zorlar. JSON spesifikasyonu temiz ve net; format türleri korur (sayılar, boolean'lar, null, diziler, nesneler).
- Excel (.xlsx) kullanın çıktı makineler için değil insanlar içinse. Biçimlendirme, formüller, birden fazla sayfa, grafikler — son tüketici bir iş kullanıcısıysa, Excel genellikle doğru seçimdir. Asla sistemler arasında bir değiş tokuş formatı olarak kullanmayın. OOXML spesifikasyonu çok büyüktür ve format sürümler arasında kırılgandır.
Pratik bir kural var: verileri doğal olarak bir elektronik tabloda görüntülerseniz, CSV muhtemelen uygundur. Bir ağaçta veya kod düzenleyicisinde görüntülerseniz JSON kullanın. Filtreleyip sıralayacak bir iş paydaşına gönderiyorsanız Excel kullanın.
Özet
CSV tasarım gereği basit ve pratikte yanıltıcı şekilde zordur. Formatın uygulanmış bir standardı
yoktur, birden fazla ayırıcı varyantında gelir ve her manuel ayrıştırma girişimini bozan tırnak kurallarına
dayanır. Düzeltme her zaman aynıdır: gerçek bir ayrıştırıcı kullanın (Python'ın yerleşik csv
modülü veya JavaScript'te PapaParse), kodlamayı her zaman açıkça belirtin ve Excel'den BOM baytlarına
dikkat edin. Güvenilir bir ayrıştırıcıya sahip olduğunuzda, CSV aslında harika bir formattır — üretmesi
hızlı, herhangi bir metin düzenleyicisinde incelemesi kolay ve her yerde desteklenir. CSV dosyalarıyla
günlük çalışma için
CSV'den JSON'a, CSV Formatter ve
CSV Doğrulayıcı araçları tek satır kod yazmadan yaygın işlemleri işler.