Những điều kiện nào phải được đáp ứng để một tệp trở thành tệp văn bản theo định nghĩa của POSIX?


22

POSIX định nghĩa một tệp văn bản là:

Một tệp chứa các ký tự được tổ chức thành không hoặc nhiều dòng. Các dòng không chứa các ký tự NUL và không có ký tự nào có thể vượt quá {LINE_MAX} byte, bao gồm cả ký tự <newline>. Mặc dù POSIX.1-2017 không phân biệt giữa tệp văn bản và tệp nhị phân (xem tiêu chuẩn ISO C), nhiều tiện ích chỉ tạo ra đầu ra có thể dự đoán hoặc có ý nghĩa khi hoạt động trên tệp văn bản. Các tiện ích tiêu chuẩn có các hạn chế như vậy luôn chỉ định "tệp văn bản" trong phần STDIN hoặc INPUT PHIM.

Nguồn: http://pub.opengroup.org/onlinepub/9699919799/basingefs/V1_chap03.html#tag_03_403

Tuy nhiên, có một số điều tôi thấy không rõ ràng:

  1. Phải là một tệp văn bản là một tệp thông thường? Trong đoạn trích trên, không nói rõ ràng tệp phải là tệp thông thường

  2. Một tệp có thể được coi là một tệp văn bản nếu chỉ chứa một ký tự và một ký tự (nghĩa là một ký tự không bị chấm dứt với một dòng mới)? Tôi biết câu hỏi này nghe có vẻ khó chịu, nhưng họ sử dụng từ "ký tự" thay vì "một hoặc nhiều ký tự". Những người khác có thể không đồng ý, nhưng nếu họ có nghĩa là "một hoặc nhiều nhân vật" thì tôi nghĩ họ nên nói rõ ràng

  3. Trong đoạn trích trên, nó làm tham chiếu đến "dòng". Tôi đã tìm thấy bốn định nghĩa với dòng trong tên của chúng: "Dòng trống", "Dòng hiển thị", "Dòng không đầy đủ" và "Dòng". Tôi có nên suy luận rằng chúng có nghĩa là "Dòng" vì thiếu sót "Trống", "Hiển thị" và "Chưa hoàn thành" - hay cả bốn định nghĩa này đều được coi là một dòng trong đoạn trích ở trên?

Tất cả các câu hỏi xuất hiện sau khối văn bản này phụ thuộc vào việc suy ra rằng "ký tự" có nghĩa là "một hoặc nhiều ký tự":

  1. Tôi có thể suy luận một cách an toàn rằng nếu một tệp trống, thì đó không phải là tệp văn bản vì nó không chứa một hoặc nhiều ký tự?

Tất cả các câu hỏi xuất hiện sau khối văn bản này phụ thuộc vào suy luận rằng trong đoạn trích trên, một dòng được định nghĩa là "Dòng" và ba loại định nghĩa khác có chứa "Dòng" trong tên của chúng phải được loại trừ:

  1. Liệu "zero" trong "zero hoặc nhiều dòng" có nghĩa là một tệp vẫn có thể được coi là tệp văn bản nếu nó chứa một hoặc nhiều ký tự không được kết thúc bằng dòng mới?

  2. Có phải "không hoặc nhiều dòng" có nghĩa là một khi một "Dòng" (0 hoặc nhiều ký tự cộng với một dòng mới kết thúc) xuất hiện, thì việc dòng cuối cùng trở thành "Dòng không hoàn chỉnh" (một hoặc nhiều dòng không phải là không hợp lệ) ký tự dòng mới ở cuối tập tin)?

  3. Có phải "không [không có dòng] nào có thể vượt quá độ dài {LINE_MAX} byte, bao gồm cả ký tự dòng mới" có nghĩa là có giới hạn về số lượng ký tự được cho phép trong bất kỳ "Dòng" nào trong tệp văn bản (như là một giá trị của LINE_MAX trên Ubuntu 18.04 và FreeBSD 11.1 là "2048")?


Câu hỏi hay, Harold! Làm cho một cuộc thảo luận tuyệt vời về thuật ngữ. Ước gì tôi có thể nâng cao câu hỏi thêm lần
Sergiy Kolodyazhnyy

Câu trả lời:


23
  1. Phải là một tệp văn bản là một tệp thông thường? Trong đoạn trích trên, không nói rõ ràng tệp phải là tệp thông thường

    Không; đoạn trích thậm chí đặc biệt lưu ý đầu vào tiêu chuẩn như một tệp văn bản tiềm năng. Tiện ích tiêu chuẩn khác, chẳng hạn như make, đặc biệt sử dụng các nhân vật tập tin đặc biệt /dev/null như một tập tin văn bản .

  2. Một tệp có thể được coi là một tệp văn bản nếu chỉ chứa một ký tự và một ký tự (nghĩa là một ký tự không bị chấm dứt với một dòng mới)?

    Ký tự đó phải là <dòng mới> hoặc đây không phải là một dòng và vì vậy tệp trong đó không phải là tệp văn bản. Một tệp chứa chính xác byte 0A là một tệp văn bản một dòng. Một dòng trống là một dòng hợp lệ.

  3. Trong đoạn trích trên, nó làm tham chiếu đến "dòng". Tôi đã tìm thấy bốn định nghĩa với dòng trong tên của chúng: "Dòng trống", "Dòng hiển thị", "Dòng không đầy đủ" và "Dòng". Tôi có nên suy luận rằng họ có nghĩa là "Dòng" vì thiếu sót "Không", "Hiển thị" và "Chưa hoàn thành"

    Nó không thực sự là một suy luận, nó chỉ là những gì nó nói. Từ "dòng" đã được đưa ra một định nghĩa phù hợp theo ngữ cảnh và vì vậy đó là những gì nó đang nói về.

  4. Tôi có thể suy luận một cách an toàn rằng nếu một tệp trống, thì đó không phải là tệp văn bản vì nó không chứa một hoặc nhiều ký tự?

    Một tệp trống bao gồm các dòng 0 (hoặc nhiều hơn) và do đó là một tệp văn bản.

  5. Liệu "zero" trong "zero hoặc nhiều dòng" có nghĩa là một tệp vẫn có thể được coi là tệp văn bản nếu nó chứa một hoặc nhiều ký tự không được kết thúc bằng dòng mới?

    Không, những nhân vật này không được tổ chức thành dòng.

  6. Có phải "không hoặc nhiều dòng" có nghĩa là một khi một "Dòng" (0 hoặc nhiều ký tự cộng với một dòng mới kết thúc) xuất hiện, thì việc dòng cuối cùng trở thành "Dòng không hoàn chỉnh" (một hoặc nhiều dòng không phải là không hợp lệ) ký tự dòng mới ở cuối tập tin)?

    Nó không bất hợp pháp , nó chỉ không phải là một tập tin văn bản. Một tiện ích yêu cầu một tệp văn bản được cung cấp cho nó có thể hành xử bất lợi nếu được cung cấp tệp đó thay thế.

  7. Liệu "không [không có dòng] nào có thể vượt quá độ dài {LINE_MAX} byte, bao gồm cả ký tự dòng mới" có nghĩa là có giới hạn số lượng ký tự được phép trong bất kỳ "Dòng" nào trong tệp văn bản

    Vâng.

Định nghĩa này chỉ là cố gắng đặt ra một số giới hạn về những gì một tiện ích dựa trên văn bản ( ví dụ,grep ) chắc chắn sẽ chấp nhận - không có gì nữa. Họ cũng được tự do chấp nhận mọi thứ một cách tự do hơn, và họ thường làm trong thực tế. Họ được phép sử dụng bộ đệm có kích thước cố định để xử lý một dòng, giả sử một dòng mới xuất hiện trước khi nó đầy, v.v. Bạn có thể đang đọc quá nhiều vào mọi thứ.


1
Bạn có chắc chắn về điểm 2? Tiêu chuẩn nêu rõ " 0 hoặc nhiều dòng". Vì vậy, printf "a" > filesẽ tạo ra một tập tin văn bản theo định nghĩa đó. Câu trả lời của bạn cho 4 dường như mâu thuẫn với câu trả lời của bạn cho 2 và 5, vì bạn đề nghị touch filetạo một tệp văn bản trong khi printf "a" > filekhông.
terdon

4
@terdon: Tôi không thấy bất kỳ mâu thuẫn nào trong câu trả lời của Michael. Về cơ bản, anh ta dường như đang nói rằng tệp văn bản POSIX là bất kỳ tệp nào có nội dung khớp với biểu thức chính quy (.{0,M}\n)*(được neo hoàn toàn và cả hai đầu), \nphù hợp với một dòng mới và .khớp với bất kỳ ký tự nào không phải là dòng mới và Mlà một trình giữ chỗ cho giá trị số LINE_MAX-1. Cụ thể, điều này ngụ ý rằng một tệp trống là một tệp văn bản hợp lệ bao gồm các dòng 0, nhưng bất kỳ tệp văn bản không trống nào cũng phải kết thúc bằng một dòng mới (vì nếu không nó sẽ chứa một dòng không hoàn chỉnh và một dòng không hoàn chỉnh không phải là một dòng ).
Ilmari Karonen

@Michael Homer Liên quan đến điều tập tin thông thường, có những ví dụ khác ngoài / dev / null? Nó không thực sự là một tệp văn bản vì nó chứa một hoặc nhiều ký tự null.
Harold Fischer

1
@HaroldFischer /dev/nulllà một tập tin trống. Bạn đang nghĩ về /dev/zero.
Michael Homer

@HaroldFischer, không, /dev/nullđọc là trống rỗng, vì trong bạn không nhận được dữ liệu khi bạn đọc nó. Tôi không chắc có ý nghĩa gì khi xem xét các tệp không thường xuyên ở đây, vì nhiều trong số chúng có tính chất động. Điều đó bao gồm đường ống, ổ cắm, thiết bị char, về cơ bản chỉ là giao diện vận chuyển đến / từ một số thực thể khác. Họ không giữ bất kỳ tập hợp dữ liệu tĩnh nào, vì vậy sẽ hợp lý hơn khi xem xét các thuộc tính của dữ liệu được truyền, thay vì các thuộc tính của tệp .
ilkkachu

7

Theo định nghĩa của POSIX:

Có, một tệp văn bản là (về cơ bản):

Một tệp chứa các ký tự được tổ chức thành không hoặc nhiều dòng.

Nó cũng hữu ích để bao gồm các định nghĩa này:

Chuỗi ký tự 3,92

Một chuỗi các ký tự liền kề được kết thúc bởi và bao gồm byte null đầu tiên.

3.195 Đường không đầy đủ

Một chuỗi gồm một hoặc nhiều ký tự không phải <dòng mới> ở cuối tệp.

Đường 3.206

Một chuỗi gồm 0 hoặc nhiều ký tự không phải <dòng mới> cộng với ký tự <dòng mới> kết thúc.

3.243 Nhân vật dòng mới (<dòng mới>)

Một ký tự trong luồng đầu ra chỉ ra rằng in sẽ bắt đầu ở đầu dòng tiếp theo. Đó là ký tự được chỉ định bởi '\ n' trong ngôn ngữ C. Không xác định được liệu ký tự này có phải là chuỗi chính xác được hệ thống truyền đến một thiết bị đầu ra để thực hiện chuyển động sang dòng tiếp theo hay không.

3.247 NUL

Một ký tự có tất cả các bit được đặt thành không.

Lưu ý rằng "Tệp văn bản" sẽ không chứa byte NUL.


Vì thế:

  1. Phải là một tệp văn bản là một tệp thông thường?
    Không, nó không cần phải như vậy. Một "tệp văn bản" được định nghĩa theo nghĩa của những gì nó chứa khi đọc. Nếu một tệp chứa "không hoặc nhiều dòng" thì đó là tệp văn bản. Một số tệp, như /dev/stdin, có thể chứa tệp văn bản nếu được đọc cùng một lúc và không đọc vào lần tiếp theo.
  2. Một tập tin có thể được coi là một tập tin văn bản nếu chỉ chứa một ký tự và một ký tự không?
    Không, đó là một dòng không đầy đủ (3.195).
    Một tệp văn bản sẽ chỉ có "Dòng không đầy đủ".
  3. Tôi có nên suy luận rằng họ có nghĩa là "Line" không?
    Vâng, bạn nên.
  4. Tôi có thể suy luận một cách an toàn rằng nếu một tệp trống, thì đó không phải là tệp văn bản.
    Không, một tệp trống (ký tự không) là "tệp văn bản" hợp lệ.
    Từ trên xuống: Không có hoặc nhiều dòng . Dòng không (ký tự không) là "Tệp văn bản" hợp lệ.
  5. Nếu xem xét một tập tin văn bản nếu nó chứa một hoặc nhiều ký tự không được kết thúc bằng dòng mới?
    Không, "Đường không đầy đủ" không (về mặt kỹ thuật) là "đường" hợp lệ.
  6. Liệu "không" trong "không hoặc nhiều dòng" có nghĩa là một tệp vẫn có thể được coi là tệp văn bản nếu nó chứa một hoặc nhiều ký tự không được kết thúc bằng dòng mới?
    Không, một dòng không đầy đủ không phải là một "Dòng". Một tệp văn bản sẽ không có dòng không đầy đủ.

  7. Có giới hạn số lượng ký tự được cho phép trong bất kỳ "Dòng" nào trong tệp văn bản không?
    Có, không được phép nhiều hơn {LINE_MAX} byte (trái ngược với ký tự) trong bất kỳ dòng nào của "tệp văn bản" hợp lệ.
    Giá trị của {LINE_MAX} được đưa ra trong tệp <giới hạn.h>
    (cũng đọc kích thước bộ đệm dòng Sensible trong C? ):

    {LINE_MAX}
    Trừ khi có ghi chú khác, độ dài tối đa tính bằng byte của dòng đầu vào của tiện ích (đầu vào tiêu chuẩn hoặc tệp khác), khi tiện ích được mô tả là xử lý tệp văn bản. Chiều dài bao gồm chỗ cho dấu.
    Giá trị tối thiểu chấp nhận được: {_POSIX2_LINE_MAX}

    Đối với hệ thống dựa trên GNU, không có giới hạn đã đặt (ngoại trừ bộ nhớ) :

    Macro: int LINE_MAX
    Dòng văn bản lớn nhất mà các tiện ích POSIX.2 hướng văn bản có thể hỗ trợ. (Nếu bạn đang sử dụng các phiên bản GNU của các tiện ích này, thì không có giới hạn thực tế ngoại trừ áp đặt bởi bộ nhớ ảo có sẵn, nhưng không có cách nào mà thư viện có thể cho bạn biết điều này.)

    Nó dường như được định nghĩa là năm posix_lim.h2048 (ít nhất là đối với các hệ thống GNU linux 64 bit):

    $ grep -ri 'POSIX2_LINE_MAX' /usr/include/ 
    
    /usr/include/x86_64-linux-gnu/bits/xopen_lim.h:#define NL_LANGMAX       _POSIX2_LINE_MAX
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define _POSIX2_LINE_MAX                2048
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define LINE_MAX                _POSIX2_LINE_MAX
    

    Nó cũng có thể được tìm thấy bằng cách sử dụng tiện ích POSIX :

    $ getconf LINE_MAX
    2048
    

Liên quan: Tại sao các tệp văn bản nên kết thúc bằng một dòng mới?


2
Câu trả lời này hầu hết là đúng, nhưng câu trả lời đúng cho tập tin văn bản phải là một tập tin văn bản là một tập tin thông thường là không . Bất kỳ loại tệp nào cũng có thể là tệp văn bản, đó là vấn đề về nội dung, loại tệp không liên quan. Các filetiện ích chỉ báo cáo các loại tập tin cho các tập tin đặc biệt, nhưng đó chỉ là cách thức hoạt động tiện ích, sử dụng file - <…hoặc (Linux) file -s …để xem công nghệ tự động của nó đối với các nội dung tập tin cho một tập tin đặc biệt. Một tệp đặc biệt có thể có các nội dung khác nhau mỗi lần bạn mở nó, vì vậy nó có thể hoặc là một tệp văn bản mỗi lần. /dev/nullluôn luôn là một tệp văn bản vì nội dung của nó luôn luôn là một tệp văn bản.
Gilles 'SO- ngừng trở nên xấu xa'

1
Thay vì sử dụng greptrên các tệp, bạn có thể sử dụng getconfđể nhận các giá trị conf hệ thống getconf LINE_MAX, ví dụ , bằng cách này trả về 2048 (byte) trên hệ thống của tôi (Ubuntu 16.04).
heemayl

Tôi muốn tìm tệp nơi xác định biến, do đó grep là cần thiết và thực hiện công việc (khá nhanh). Nhưng có, getconfcho phép đọc giá trị hiện tại của cấu hình.
Isaac
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.