Kondisi apa yang harus dipenuhi untuk file menjadi file teks seperti yang didefinisikan oleh POSIX?

22

POSIX mendefinisikan file teks sebagai:

File yang berisi karakter yang disusun dalam nol atau lebih baris. Baris tidak mengandung karakter NUL dan panjangnya tidak boleh melebihi {LINE_MAX} byte, termasuk karakter <newline>. Meskipun POSIX.1-2017 tidak membedakan antara file teks dan file biner (lihat standar ISO C), banyak utilitas hanya menghasilkan output yang dapat diprediksi atau bermakna ketika beroperasi pada file teks. Utilitas standar yang memiliki batasan seperti itu selalu menentukan "file teks" di bagian STDIN atau INPUT FILES.

Sumber: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403

Namun, ada beberapa hal yang saya temukan tidak jelas:

  1. Haruskah file teks menjadi file biasa? Dalam kutipan di atas tidak secara eksplisit mengatakan file tersebut harus berupa file biasa

  2. Dapatkah file dianggap sebagai file teks jika hanya mengandung satu karakter dan satu karakter (yaitu, satu karakter yang tidak diakhiri dengan baris baru)? Saya tahu pertanyaan ini mungkin terdengar nitpicky, tetapi mereka menggunakan kata "karakter" alih-alih "satu atau lebih karakter". Yang lain mungkin tidak setuju, tetapi jika itu berarti "satu atau lebih karakter" saya pikir mereka harus secara eksplisit mengatakannya

  3. Dalam kutipan di atas, itu membuat referensi ke "baris". Saya menemukan empat definisi dengan baris dalam nama mereka: "Baris Kosong", "Baris Tampilan", "Baris Tidak Lengkap" dan "Baris". Apakah saya harus menyimpulkan bahwa yang mereka maksudkan "Baris" karena mereka tidak memiliki "Kosong", "Tampilan" dan "Tidak Lengkap" - atau apakah keempat definisi ini termasuk sebagai baris dalam kutipan di atas?

Semua pertanyaan yang muncul setelah blok teks ini bergantung pada kesimpulan bahwa "karakter" berarti "satu atau lebih karakter":

  1. Dapatkah saya menyimpulkan dengan aman bahwa jika file kosong, itu bukan file teks karena tidak mengandung satu atau lebih karakter?

Semua pertanyaan yang muncul setelah blok teks ini bergantung pada kesimpulan bahwa dalam kutipan di atas, sebuah baris didefinisikan sebagai "Baris", dan bahwa tiga definisi lainnya yang mengandung "Baris" dalam namanya harus dikecualikan:

  1. Apakah "nol" dalam "nol atau lebih baris" berarti bahwa suatu file masih dapat dianggap sebagai file teks jika mengandung satu atau lebih karakter yang tidak diakhiri dengan baris baru?

  2. Apakah "nol atau lebih baris" berarti bahwa sekali "Baris" tunggal (0 atau lebih karakter plus baris baru) mulai berlaku, itu menjadi ilegal untuk baris terakhir menjadi "Baris Tidak Lengkap" (satu atau lebih non- karakter baris baru di akhir file)?

  3. Apakah "tidak ada [tidak ada baris] yang dapat melebihi {LINE_MAX} byte, termasuk karakter baris baru" berarti bahwa ada batasan untuk jumlah karakter yang diizinkan dalam "Baris" yang diberikan dalam file teks (selain itu, nilai dari LINE_MAX di Ubuntu 18.04 dan FreeBSD 11.1 adalah "2048")?

Harold Fischer
sumber
Pertanyaan bagus, Harold! Membuat diskusi yang bagus tentang terminologi. Seandainya saya bisa menjawab pertanyaan tambahan kali
Sergiy Kolodyazhnyy

Jawaban:

23
  1. Haruskah file teks menjadi file biasa? Dalam kutipan di atas tidak secara eksplisit mengatakan file tersebut harus berupa file biasa

    Tidak; kutipan bahkan secara khusus mencatat input standar sebagai file teks potensial. Utilitas standar lainnya, seperti make, secara khusus menggunakan file karakter khusus /dev/null sebagai file teks .

  2. Dapatkah file dianggap sebagai file teks jika hanya mengandung satu karakter dan satu karakter (yaitu, satu karakter yang tidak diakhiri dengan baris baru)?

    Karakter itu harus berupa <newline>, atau ini bukan baris , jadi file yang ada di dalamnya bukan file teks. File yang mengandung byte 0A persis adalah file teks satu baris. Baris kosong adalah baris yang valid.

  3. Dalam kutipan di atas, itu membuat referensi ke "baris". Saya menemukan empat definisi dengan baris dalam nama mereka: "Baris Kosong", "Baris Tampilan", "Baris Tidak Lengkap" dan "Baris". Haruskah saya menyimpulkan bahwa yang mereka maksudkan "Baris" karena mereka tidak memiliki "Kosong", "Tampilan" dan "Tidak Lengkap"

    Ini bukan kesimpulan, hanya apa yang dikatakannya. Kata "baris" telah diberikan definisi yang sesuai secara kontekstual dan itulah yang sedang dibicarakan.

  4. Dapatkah saya menyimpulkan dengan aman bahwa jika file kosong, itu bukan file teks karena tidak mengandung satu atau lebih karakter?

    File kosong terdiri dari nol (atau lebih) baris dan karenanya merupakan file teks.

  5. Apakah "nol" dalam "nol atau lebih baris" berarti bahwa suatu file masih dapat dianggap sebagai file teks jika mengandung satu atau lebih karakter yang tidak diakhiri dengan baris baru?

    Tidak, karakter ini tidak disusun dalam garis.

  6. Apakah "nol atau lebih baris" berarti bahwa sekali "Baris" tunggal (0 atau lebih karakter plus baris baru) mulai berlaku, itu menjadi ilegal untuk baris terakhir menjadi "Baris Tidak Lengkap" (satu atau lebih non- karakter baris baru di akhir file)?

    Itu tidak ilegal , hanya saja bukan file teks. Utilitas yang membutuhkan file teks untuk diberikan kepadanya mungkin berperilaku buruk jika diberi file itu sebagai gantinya.

  7. Apakah "tidak ada [tidak ada garis] yang dapat melebihi {LINE_MAX} byte, termasuk karakter baris baru" berarti bahwa ada batasan untuk jumlah karakter yang diizinkan dalam "Baris" yang diberikan dalam file teks

    Iya nih.

Definisi ini hanya mencoba untuk menetapkan batas pada apa utilitas berbasis teks ( misalnya,grep ) pasti akan menerima - tidak lebih. Mereka juga bebas untuk menerima hal-hal secara lebih bebas, dan cukup sering mereka lakukan dalam praktik. Mereka diizinkan untuk menggunakan buffer ukuran tetap untuk memproses baris, untuk menganggap baris baru muncul sebelum penuh, dan seterusnya. Anda mungkin membaca terlalu banyak hal.

Michael Homer
sumber
1
Apakah Anda yakin tentang poin 2? Standar secara eksplisit menyatakan " 0 atau lebih baris". Jadi printf "a" > fileakan membuat file teks sesuai dengan definisi itu. Jawaban Anda ke 4 tampaknya bertentangan dengan jawaban Anda ke 2 dan 5, seperti yang Anda sarankan yang touch filemembuat file teks sementara printf "a" > filetidak.
terdon
4
@terdon: Saya tidak melihat kontradiksi dalam jawaban Michael. Pada dasarnya, ia tampaknya mengatakan bahwa file teks POSIX adalah file apa pun yang isinya cocok dengan regexp (.{0,M}\n)*(secara implisit berlabuh dan kedua ujungnya), di mana \ncocok dengan baris baru dan .cocok dengan karakter apa pun yang bukan baris baru, dan Mmerupakan pengganti untuk nilai numerik LINE_MAX-1. Secara khusus, ini menyiratkan bahwa file kosong adalah file teks yang valid yang terdiri dari baris nol, tetapi file teks yang tidak kosong harus diakhiri dengan baris baru (karena jika tidak maka akan berisi baris yang tidak lengkap, dan baris yang tidak lengkap bukan baris ).
Ilmari Karonen
@Michael Homer Mengenai hal file biasa, apakah ada contoh lain selain / dev / null? Ini sebenarnya bukan file teks karena mengandung satu atau lebih karakter nol.
Harold Fischer
1
@ HaroldFischer /dev/nulladalah file kosong. Anda sedang memikirkan /dev/zero.
Michael Homer
@ HaroldFischer, tidak, /dev/nulldibaca kosong, karena Anda tidak mendapatkan data saat Anda membacanya. Saya tidak yakin masuk akal untuk mempertimbangkan file non-reguler di sini, karena banyak dari mereka yang bersifat dinamis. Itu termasuk pipa, soket, perangkat char, yang pada dasarnya hanya mengangkut antarmuka ke / dari beberapa entitas lain. Mereka tidak memegang set data statis apa pun, jadi lebih masuk akal untuk mempertimbangkan properti data yang ditransfer, alih-alih properti file .
ilkkachu
7

Seperti yang didefinisikan oleh POSIX:

Ya, file teks adalah (pada dasarnya):

File yang berisi karakter yang disusun dalam nol atau lebih baris.

Akan bermanfaat untuk memasukkan definisi ini:

3.92 String Karakter

Urutan karakter yang berdekatan diakhiri oleh dan termasuk byte nol pertama.

3.195 Jalur Tidak Lengkap

Urutan satu atau lebih karakter <newline> di akhir file.

3.206 Baris

Urutan nol atau lebih karakter <newline> plus karakter terminasi <newline>.

3.243 Karakter Baris Baru (<newline>)

Karakter yang di aliran keluaran menunjukkan bahwa pencetakan harus dimulai pada awal baris berikutnya. Ini adalah karakter yang ditunjuk oleh '\ n' dalam bahasa C. Tidak ditentukan apakah karakter ini adalah urutan yang tepat yang dikirim ke perangkat output oleh sistem untuk menyelesaikan pergerakan ke baris berikutnya.

3,247 NUL

Karakter dengan semua bit diatur ke nol.

Perhatikan bahwa "File Teks" tidak boleh berisi NUL byte.


Begitu:

  1. Haruskah file teks menjadi file biasa?
    Tidak, itu tidak perlu. "File teks" didefinisikan berdasarkan isi di dalamnya ketika dibaca. Jika file berisi "nol atau lebih baris" itu adalah file teks. Beberapa file, seperti /dev/stdin, mungkin berisi file teks jika dibaca pada satu waktu dan tidak pada saat berikutnya dibaca.
  2. Apakah file dapat dianggap sebagai file teks jika hanya mengandung satu karakter dan satu karakter ...?
    Tidak, itu garis yang tidak lengkap (3.195).
    File teks hanya boleh memiliki "Garis Tidak Lengkap".
  3. Apakah saya harus menyimpulkan bahwa yang mereka maksud adalah "Line" ...?
    Ya kamu harus.
  4. Dapatkah saya menyimpulkan dengan aman bahwa jika file kosong, itu bukan file teks ...?
    Tidak, file kosong (nol karakter) adalah "file teks" yang valid.
    Dari atas: ... nol atau lebih baris ... . Garis nol (nol karakter) adalah "file teks" yang valid.
  5. ... dianggap sebagai file teks jika berisi satu atau lebih karakter yang tidak diakhiri dengan baris baru?
    Tidak, "Jalur Tidak Lengkap" bukan "jalur" yang valid.
  6. Apakah "nol" dalam "nol atau lebih baris" berarti bahwa suatu file masih dapat dianggap sebagai file teks jika mengandung satu atau lebih karakter yang tidak diakhiri dengan baris baru?
    Tidak, baris yang tidak lengkap bukan "Baris". File teks tidak boleh memiliki baris yang tidak lengkap.

  7. ... ada batasan jumlah karakter yang diizinkan dalam "Baris" apa pun yang diberikan dalam file teks ...?
    Ya, tidak lebih dari {LINE_MAX} byte (sebagai lawan dari karakter) harus diizinkan di setiap baris "file teks" yang valid.
    Nilai {LINE_MAX} diberikan dalam file <Limit.h>
    (juga membaca ukuran buffer line yang masuk akal dalam C? ):

    {LINE_MAX}
    Kecuali disebutkan sebaliknya, panjang maksimum, dalam byte, dari garis input utilitas (baik input standar atau file lain), ketika utilitas digambarkan sebagai pemrosesan file teks. Panjangnya termasuk ruang untuk trailing.
    Nilai Minimum yang Dapat Diterima: {_POSIX2_LINE_MAX}

    Untuk sistem berbasis GNU tidak ada batas yang ditentukan (kecuali memori) :

    Makro: int LINE_MAX
    Baris teks terbesar yang dapat didukung oleh utilitas POSIX.2 berorientasi teks. (Jika Anda menggunakan versi GNU dari utilitas ini, maka tidak ada batas sebenarnya kecuali yang dipaksakan oleh memori virtual yang tersedia, tetapi tidak ada cara bahwa perpustakaan dapat memberitahu Anda ini.)

    Tampaknya didefinisikan posix_lim.hsebagai 2048 (setidaknya untuk sistem 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
    

    Itu juga dapat ditemukan menggunakan utilitas POSIX getconf :

    $ getconf LINE_MAX
    2048
    

Terkait: Mengapa file teks harus diakhiri dengan baris baru?

Ishak
sumber
2
Jawaban ini sebagian besar benar, tetapi jawaban yang benar untuk "harus file teks menjadi file biasa" adalah tidak . Setiap jenis file dapat berupa file teks, ini masalah konten, tipe file tidak relevan. The fileutilitas hanya melaporkan jenis file untuk file khusus, tapi itu hanya cara kerja utilitas, penggunaan file - <…atau (Linux) file -s …untuk melihat heuristik pada isi file untuk file khusus. File khusus dapat memiliki konten yang berbeda setiap kali Anda membukanya, sehingga bisa atau menjadi file teks setiap kali. /dev/nullselalu merupakan file teks karena isinya selalu berupa file teks.
Gilles 'SANGAT berhenti menjadi jahat'
1
Daripada menggunakan greppada file, Anda dapat menggunakan getconfuntuk mendapatkan nilai-nilai conf sistem misalnya getconf LINE_MAX, yang dengan cara mengembalikan 2048 (byte) pada sistem saya (Ubuntu 16.04).
heemayl
Saya ingin mencari file di mana variabel didefinisikan, sehingga grep diperlukan, dan melakukan pekerjaan (cukup cepat). Tapi ya, getconfmemungkinkan untuk membaca nilai sekarang dari konfigurasi.
Isaac