4 điểm bởi GN⁺ 2025-03-27 | 3 bình luận | Chia sẻ qua WhatsApp
  • Các định dạng được cho là “vượt trội” để thay thế CSV thường xuyên được giới thiệu, nhưng phần lớn dựa trên những so sánh thiên lệch và bỏ qua các điểm mạnh thực sự của CSV
  • Bài viết này không nhằm nói rằng CSV là hoàn hảo, mà muốn làm nổi bật những ưu điểm bị đánh giá thấp của nó
  • Đi ngược lại bầu không khí coi việc ghét CSV là thứ gì đó trông thật ngầu, bài viết nhắc lại giá trị thật sự của CSV

1. CSV cực kỳ đơn giản

  • Định nghĩa của CSV đúng như tên gọi: “các giá trị được phân tách bằng dấu phẩy”
  • Các hàng được phân tách bằng xuống dòng, các cột bằng dấu phẩy
  • Nếu giá trị chứa dấu phẩy hoặc xuống dòng thì được bao bằng dấu ngoặc kép, còn bản thân dấu ngoặc kép được biểu diễn bằng ngoặc kép đôi
  • Không cần đặc tả phức tạp, ai cũng có thể hiểu và օգտագործել một cách trực quan
  • Tuy vậy, để phân tích chính xác thì vẫn nên dùng parser CSV chuyên dụng

2. CSV là một ý tưởng mang tính tập thể

  • Không có chủ sở hữu, không bị tư hữu hóa
  • Có RFC 4180, nhưng đa số chỉ xem đó là tài liệu tham khảo
  • Đây là một định dạng tự do dựa trên các quy tắc chung được các lập trình viên trên toàn thế giới ngầm chia sẻ

3. CSV là văn bản

  • Giống JSON, YAML, XML, đây là định dạng văn bản thuần mà con người có thể đọc được
  • Có thể mở bằng bất kỳ trình soạn thảo văn bản nào và xem nội dung mà không cần công cụ riêng
  • Cũng có thể tự do lựa chọn cách mã hóa

4. CSV được tối ưu cho streaming

  • Vì có cấu trúc đọc từng dòng nên mức tiêu thụ bộ nhớ rất thấp
  • Chỉ với đoạn mã đơn giản cũng có thể xử lý vài GB dữ liệu chỉ bằng vài KB bộ nhớ
  • Các định dạng hướng cột như Parquet khó xử lý theo kiểu streaming và cần buffering phức tạp
  • Điểm bất lợi là ngay cả khi chỉ muốn xem một cột cụ thể, bạn vẫn phải đọc toàn bộ hàng

5. CSV rất dễ nối thêm dữ liệu

  • Việc mở tệp ở chế độ append(a+) và thêm hàng mới vào cuối là cực kỳ dễ
  • Ngược lại, các định dạng hướng cột như Parquet khiến việc thêm hàng trở nên kém hiệu quả và phức tạp

6. CSV hỗ trợ kiểu động

  • Không có kiểu cố định nên có thể diễn giải dữ liệu một cách linh hoạt
  • Ví dụ: JavaScript không thể biểu diễn chính xác số nguyên 64-bit, nhưng CSV có thể được dùng mà không bị ràng buộc bởi hạn chế đó
  • Đây là lợi thế về khả năng tương thích giữa các ngôn ngữ và tính linh hoạt
  • Tuy nhiên, nếu diễn giải sai thì có thể phát sinh lỗi → cần thận trọng khi sử dụng
  • Khi cần hiệu năng cao, cũng có thể xử lý trực tiếp ở mức nhị phân mà không giải mã văn bản

7. CSV ngắn gọn

  • Header chỉ tồn tại ở đầu tệp nên hầu như không có sự lặp lại về định dạng
  • JSON và XML có overhead lớn do lặp lại khóa
  • Cách biểu diễn chuỗi vốn đã gọn, và overhead của chính định dạng (dấu phẩy, dấu ngoặc kép, v.v.) cũng rất nhỏ

8. CSV bị đảo ngược vẫn hợp lệ

  • CSV vẫn là CSV hợp lệ ngay cả khi đảo ngược theo từng byte
  • Điều này có được nhờ cách escape bằng ngoặc kép đôi, vốn là một cơ chế escape dạng palindrome
  • Nhờ đặc tính này, có thể đọc phần cuối của tệp CSV rất hiệu quả
  • Ví dụ: khi khôi phục một tiến trình bị gián đoạn, có thể chỉ đọc vài dòng cuối của tệp để khởi động lại

9. Excel ghét CSV

  • Nếu Excel thấy một định dạng bất tiện, thì biết đâu đó lại là dấu hiệu cho thấy bạn đang đi đúng hướng

3 bình luận

 
ng0301 2025-03-29

Đơn giản là tốt nhất!

 
ethanhur 2025-03-27

Tệ hơn mới là tốt hơn!

 
GN⁺ 2025-03-27
Ý kiến Hacker News
  • Lý do thích các tệp CSV và INI là vì chúng đơn giản, dựa trên văn bản, không có kiểu dữ liệu được mã hóa trong định dạng và chỉ được cấu thành từ chuỗi

    • Dù có nhược điểm là không có tiêu chuẩn chính thức, chúng vẫn làm tốt nhiệm vụ của mình
    • Đã lưu lại phần phê bình INI từ góc nhìn TOML
    • Tôi nghĩ dòng đầu tiên của bài phê bình TOML cũng áp dụng cho CSV: nó là một liên minh của nhiều phương ngữ
  • CSV thanh lịch nhưng có một khuyết điểm chí mạng - dấu ngoặc kép tạo ra hiệu ứng “phi cục bộ”

    • Ví dụ, chỉ một dấu ngoặc kép ở byte 1 có thể thay đổi ý nghĩa của dấu phẩy ở byte 1000000
    • Điều này dẫn đến hai hệ quả bất tiện
      • Khó song song hóa việc xử lý CSV
      • Hỏng dữ liệu ảnh hưởng rất lớn đến khả năng đọc của tệp (thiếu hoặc thừa một dấu ngoặc kép có thể phá hỏng toàn bộ)
    • Vì vậy dạo này, với việc tuần tự hóa dữ liệu bảng đơn giản, tôi thích dùng escaping đơn giản thay vì CSV
  • Điểm hay nhất của CSV là ai cũng có thể viết một parser trong 30 phút

    • Có thể dễ dàng nhập dữ liệu từ đầu thập niên 90 vào các dịch vụ web hiện đại
    • Điểm tệ nhất của CSV cũng là ai cũng có thể viết một parser trong 30 phút
    • Rất dễ xuất hiện triển khai sai, dữ liệu sai và hành vi kỳ lạ không được định nghĩa
    • JSON và YAML cũng có những vấn đề tương tự
    • XML hơi xấu xí một chút, nhưng có vẻ là thứ vững chắc nhất
  • Người thích CSV chắc chưa từng bị yêu cầu xử lý việc ngăn chặn CSV injection trong môi trường doanh nghiệp

    • Trên web có rất ít tài nguyên tốt về vấn đề này
    • Tài nguyên tốt nhất là <a href="https://georgemauer.net/2017/10/07/csv-injection.html" rel="nofollow">ở đây</a>
  • Có nhiều lý do để thích CSV

    • Có thể viết chương trình bằng C để xuất trực tiếp nhiều thứ sang CSV
    • Có thể viết middleware đơn giản để dễ dàng chuyển từ hầu như mọi cơ sở dữ liệu hay “thứ” phổ biến sang CSV
    • Có thể đưa CSV vào Excel rồi làm mọi thứ mình muốn
    • Tôi cũng thích tệp ini. Có thể sửa trực tiếp bằng Notepad
    • Tuy vậy, tôi vẫn ước có một khung tổng quát/cấu trúc chung nào đó
  • Gần đây tôi đang phát triển một giải pháp dựa trên Raspberry Pi

    • Bản triển khai đầu tiên dùng cơ sở dữ liệu SQLite, nhưng bị hỏng chỉ sau vài ngày qua các chu kỳ bật/tắt nguồn
    • Tôi đã xem xét các tệp Parquet, nhưng chúng không thân thiện với tác vụ append-only
    • Tôi đã triển khai cách ghi sự kiện vào tệp IPC và định kỳ “flush” sang tệp Parquet
    • Nó hoạt động và hiệu quả, nhưng không dễ triển khai cho đúng
    • Với lập trình viên thông thường, CSV (hoặc JSONL) vẫn là tốt nhất
  • Điều kém thú vị ở CSV là các parser và serializer viết vội thường lặp lại những lỗi phổ biến khi xử lý dấu ngoặc kép

    • Tôi đã dè chừng CSV trong thời gian dài, nhưng điều đó thay đổi sau khi học Python và dùng mô-đun csv chuẩn rất tốt của nó
  • Nếu đây thực sự là một bức thư tình, hẳn nó đã được viết bằng định dạng CSV

  • Phản biện chống lại JSON không mấy thuyết phục

    • Không nhất thiết phải thêm tên cho mọi trường
    • Khi so CSV với JSON, JSON chỉ lớn hơn một chút, nhưng dấu ngoặc biểu thị khả năng một thứ có thể đơn giản hoặc phức tạp
    • Vì CSV quá đơn giản nên người ta thường không dùng thư viện phân tích/coding
    • Parser JSON luôn xuất ra giá trị như mong đợi, và ngôn ngữ có lẽ sẽ dùng parser dựa trên SIMD rất hiệu quả
    • Cũng có vấn đề về chuẩn hóa. Tệp CSV có thể dùng dấu phẩy, khoảng trắng, dấu chấm phẩy, dấu gạch đứng..., dùng CR, LF, CRLF, có cho phép escape dấu ngoặc kép hay không, v.v.
    • JSON không có những vấn đề này
    • JSON có kiểu dữ liệu. Có 6 kiểu vẫn tốt hơn là không có kiểu nào
    • JSON không hoàn hảo, nhưng nhìn chung tốt hơn CSV
  • Là người thích các định dạng hiện đại, khi phân vân tôi dùng CSV hoặc JSONL

    • Vì chủ yếu là văn bản thuần nên có thể dễ dàng tìm bằng grep và hỗ trợ streaming
    • Hầu hết các tính năng được liệt kê trong bài cũng được JSONL chia sẻ
    • Nén bằng gzip hay zstd đều rất tốt
    • Việc nén làm mất đi phần nào lợi thế của văn bản thuần, nhưng ripgrep vẫn có thể tìm trong các tệp đã nén
    • Một ưu điểm khác của JSONL là dễ chia thành các tệp nhỏ hơn