Cách tốt nhất để xử lý các tệp được phân tách


16

Vì vậy, thông thường, tệp CSV sử dụng dấu phẩy và ký tự trả về làm dấu phân cách trường và dòng.

Điều này gặp vấn đề rõ ràng với văn bản có thể chứa cả hai ký tự này.

Rõ ràng có những lựa chọn ở đó (thoát khỏi chúng) nhưng làm thế nào để mọi người xử lý việc này? Sử dụng các ký tự khác nhau - ống hoặc dấu ngã? Thoát khỏi chúng? Không sử dụng các tệp được phân tách, sau tất cả là năm 2010 và bây giờ chúng ta có XML?

Nhìn vào nỗ lực ít nhất cho một cơ hội tốt không nhìn thấy vấn đề.

(Nói rõ hơn, đây là một câu hỏi vì tò mò hơn là một thứ gì đó vững chắc hơn - đó là thứ tôi đã tình cờ hết lần này đến lần khác chơi với dữ liệu, luôn làm tròn nó nhưng nó thường cảm thấy một chút, tốt, bẩn, và tự hỏi kinh nghiệm của người khác là gì).


Hãy suy nghĩ cẩn thận về việc sử dụng CSV - thật dễ dàng và dễ xử lý (xem câu trả lời cho các quy tắc thoát thông thường), nhưng nó gần như không thể hoạt động như bình thường - nếu bạn chỉ giao tiếp với các chương trình của riêng mình thì tốt, nhưng nếu bạn muốn nhập ở nơi khác thì hơi lạ vì các chương trình khác nhau tuân theo các quy tắc thoát khác nhau.
Michael Kohne

@Michael - Hoàn toàn đúng. Vấn đề là ở chỗ nó có mặt ở khắp mọi nơi mà hầu như bạn sẽ luôn nghĩ đến khi đó là một lựa chọn rất hấp dẫn, và trong trường hợp nhiều hệ thống cũ thì đó là lựa chọn duy nhất.
Jon Hopkins

Các thư viện trưởng thành tồn tại trong nhiều ngôn ngữ (chắc chắn là những ngôn ngữ phổ biến) để đọc và ghi các tệp phân cách ký tự. Họ sẽ xử lý hầu hết mọi tình huống. Viết trình phân tích cú pháp CSV của riêng ai đó dường như là một kiểu chống mẫu phổ biến.
quentin-starin

Câu trả lời:


13

Theo Wikipedia :

Các trường có dấu phẩy nhúng phải được đặt trong các ký tự trích dẫn kép.

Và hơn thế nữa:

Các trường có các ký tự trích dẫn kép được nhúng phải được đặt trong các ký tự trích dẫn kép và mỗi ký tự trích dẫn kép được nhúng phải được thể hiện bằng một cặp ký tự trích dẫn kép.

Tôi không biết ai đã phát minh ra điều đó, nhưng nó thực sự cho thấy rằng cuối cùng bạn phải trốn thoát. Đó là giải pháp vững chắc duy nhất. Mọi thứ khác chỉ là băng keo trên đầu băng keo: có thể hoạt động ngay bây giờ, nhưng cuối cùng bạn sẽ gặp phải trường hợp bạn cần một ngoại lệ ngoại trừ ngoại lệ và không mất nhiều thời gian trước quy tắc bóng bùn của bạn là cách phức tạp hơn một giải pháp nhân vật thoát đơn giản đã có.

Có vẻ như trước tiên, người tạo CSV đã cố gắng tránh thoát dấu phẩy bằng cách đưa ra cú pháp đặc biệt được trích dẫn hai lần, cho phép lưu dấu phẩy, nhưng sau đó ai đó cũng muốn lưu các ký tự trích dẫn kép, vì vậy họ phải thoát vào thời điểm đó - vui vẻ sử dụng trích dẫn như một nhân vật thoát. Nếu họ quyết định trốn thoát ngay từ đầu, cú pháp sẽ đơn giản hơn bây giờ.


3
Những gì nên và những gì .. thường khác nhau :)
Tim Post

Tôi nghĩ rằng giải pháp là khá ok. Đối với dữ liệu đơn giản, CSV hoạt động tốt, đối với dữ liệu phức tạp, sau đó trích dẫn là cần thiết và thoát "dấu vết" trở lại BASIC.
Ernelli

1
@Ernelli: Bây giờ tôi nghĩ về nó nhiều hơn, nó thực sự có thể là một sự thỏa hiệp hợp lý giữa khả năng đọc và đơn giản của con người. Vấn đề thoát ra là nó trông xấu xí đối với con người , mặc dù máy tính không thể phân tích được. Do đó, việc đặt trước thoát chỉ dành cho các trường hợp hiếm hoi ("các trường có ký tự trích dẫn kép được nhúng") tạo ra kết quả thường trông khá dễ đọc. Đây là một giải pháp tốt, giả sử rằng dấu phẩy trong tên trường được sử dụng thường xuyên hơn dấu ngoặc kép trong tên trường.
Joonas Pulakka

2

Tôi giả sử bạn có một cái gì đó như thế này:

Foo,Baz,,,"Foo,Baz"

Nếu các chuỗi chứa dấu phân cách không được trích dẫn hoặc thoát, bạn không có cách phân tích tệp đáng tin cậy thực sự .

Tuy nhiên, bạn có thể kiểm tra dữ liệu để phân tích và rút ra kết luận như:

  • Phao được phân tách bằng dấu phẩy nên được coi là một chuỗi
  • Nếu dòng trước hoặc sau này chứa ít dấu phân cách hơn, hãy bỏ qua phân tích cú pháp dòng này và đăng nhập nó
  • Đối xử 'như "

Bạn phải viết một trình phân tích cú pháp để xử lý những thứ như vậy, nhưng nó không phải phức tạp.

Theo kinh nghiệm của tôi, việc nhập các khối lớn từ một cái gì đó như Excel luôn dẫn đến việc phải quay lại và xem lại một số trò kỳ quặc. Thách thức của bạn là để cung cấp cho chương trình của bạn chỉ đủ cảm giác chung về các dữ liệu để nó không làm một chèn điên. Sau đó xem lại những gì đã được ghi lại và rửa / rửa / lặp lại.

Tôi đã từng xử lý một Câu hỏi thường gặp nội bộ cho một công ty nhỏ sử dụng tất cả các máy trạm Ubuntu. Một phần của Câu hỏi thường gặp đã đưa ra 'phím tắt vỏ' và nó được phân định cho tôi. Chà, các câu trả lời cũng thường được phân định bằng đường ống (ví dụ grep foo | gì đó) và không được trích dẫn hoặc thoát. Tôi cảm thấy đau đó :)


2

Không có gì sai với CSV đến một điểm

CSV hoạt động tốt đối với dữ liệu được xác định cứng nhắc không có khả năng thay đổi định dạng và không gây ra nhiều bất ngờ cho trình phân tích cú pháp người nhận.

Đây là một danh sách tiện dụng của các vấn đề lớn:

  1. Thoát "" s trong "" (trường chứa dấu phân cách trường)
  2. "" chứa CRLFs (trường chứa dấu phân cách dòng)
  3. Unicode (định dạng văn bản cơ bản có thể không đủ)
  4. Các đầu cuối dòng khác nhau cho các HĐH khác nhau (là CR hoặc CRLF hoặc LF hoặc NUL?)
  5. Nhận xét nội tuyến (dòng có tiền tố #, //, - ,; v.v.)
  6. Quản lý phiên bản (phiên bản mới nhất của tệp chứa nhiều hoặc ít trường)
  7. Phân biệt giữa NULL và dữ liệu trống (, "", trống nhưng ,, là null?)

Bạn có thể tiếp cận điều này với một tiêu đề siêu dữ liệu mô tả cách các trường nên được phân tích cú pháp, nhưng sau đó bạn cũng có thể chỉ sử dụng XML. Đó là do loại lộn xộn CSV dạng tự do mà nó được phát minh. Cách tiếp cận XML dường như quá nặng nề đối với những gì có thể, trên mặt của nó, là một vấn đề đơn giản.

Một thay thế phổ biến là chiến lược "phân định nhân vật kỳ lạ". Điều này giải quyết được rất nhiều vấn đề thoát ở trên vì bạn sử dụng một cái gì đó như | (pipe) ký tự để phân định trường và CRLF để chấm dứt bản ghi. Điều này không xoay quanh vấn đề trường nhiều dòng (trừ khi bạn sử dụng bộ đếm trường) nhưng bạn có được các dòng được định dạng độc đáo cho con người.

Nhìn chung, nếu bạn chỉ tìm kiếm một cách đơn giản để xử lý loại tệp này thì trong thế giới Java, bạn có thể chỉ cần ném OpenCSV vào nó. Bằng cách đó, bạn trừu tượng hóa tất cả các vấn đề thành một khung được thiết lập.


2

CSV vẫn là một định dạng hợp lệ trong nhiều tình huống, đặc biệt là vì nó vẫn phải là cách dễ nhất để khách hàng ghi dữ liệu cần được nhập vào ứng dụng của bạn. Rất ít khách hàng của chúng tôi thích giao dịch với XML, có lẽ vì nó rất dài dòng và có tất cả các dấu ngoặc góc "đáng sợ" đó. Thật đơn giản hơn nhiều khi họ bọc bộ não của mình xung quanh một danh sách đơn giản các mục được phân tách bằng một ký tự đã thỏa thuận và cũng đồng ý rằng cùng một ký tự sẽ không được phép trong nội dung của một trường.

Điều đó nói rằng, bạn vẫn phải xử lý chính xác đầu vào và kiểm tra các tình huống trong đó họ sử dụng các ký tự không hợp lệ. Tôi đã bắt đầu sử dụng Trình trợ giúp tệp cho nhu cầu phân tích cú pháp CSV của mình.


1

tôi thường bám sát tiêu chuẩn và thoát khỏi chúng. trong hầu hết các ngôn ngữ lập trình đều có hỗ trợ dựng sẵn tốt hoặc có sẵn thư viện tốt.

tùy thuộc vào tình huống định dạng nào sẽ được sử dụng và CSV là định dạng hợp lý để trao đổi cấu trúc định dạng dữ liệu đơn giản.


0

Quên CSV, sử dụng JSON . Dễ viết, dễ phân tích. XML là như vậy năm 2005 .


6
và có cùng một vấn đề khi bạn muốn sử dụng một ký tự là một phần của định dạng JSON (như {hoặc,)
Salandur

Salandur: Không hề! Có quy tắc chính xác làm thế nào để thoát! Nhưng {và, thậm chí không cần phải thoát, bởi vì bên trong là chuỗi, chúng không mơ hồ!
user281377

1
Tốt và tốt, nhưng tôi không nhớ excel có tính năng "Xuất ra JSON" :) Có những lúc bạn phải phân tích những thứ kỳ quặc, nếu chỉ để đưa chúng vào một định dạng dễ chịu hơn.
Tim Post

1
Và JSON hoàn toàn tuyệt vời khi vượt qua hàng triệu đối tượng có cùng hình dạng. Oh, đợi đã.
Frank Shearar

1
JSON không cải thiện CSV về câu hỏi này và thiếu khả năng tương tác với nhiều ứng dụng (như đã đề cập, không thể nhập hoặc xuất từ ​​Office, SQL DB, v.v.). JSON rất tốt cho các hoạt động phía máy khách nội bộ, trọng lượng nhẹ nhưng XML tốt hơn nhiều cho việc truyền dữ liệu giữa các ứng dụng.
Dan Diplo

0

Thông thường, những gì tôi thấy mình đang làm là nhận TSV (giá trị được phân tách bằng tab) thay vì tệp CSV, kéo tệp vào Emacs và xem một trong số một vài ký tự không phổ biến mà KHÔNG BAO GIỜ sử dụng ($ thường là một lựa chọn tốt ở đây), và sau đó tôi chuyển đổi tất cả các tab thành $.

Từ đó, GNU AWK có thể được yêu cầu sử dụng $ làm dấu phân cách trường và Bob là chú của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.