Лого на страниците (малко). Система Orphus
Ако забележите грешка, маркирайте израза с мишката и натиснете Control+Enter. Благодаря!
Александър Иванов
Текстов файл, бинарен файл
 
Дори хора с доста практика на компютър се объркват — кой файл е текстов и кой е бинарен? Текстът, дето си го работя с Word, текстов файл ли е, щом съдържа текст?
А разликата е важна, особено за филолога изследовател, чийто данни най-често се съхраняват в обикновени текстови файлове.
Хайде да не се лъжем — в компютрите няма други файлове, освен бинарни.
По една проста причина — бинарно (двоично) е елементарното устройство за запомняне на данни. То може да е реализирано по много различни начини — по един начин е реализирано то в оперативната памет или на „флашката“, по друг начин е на магнитния диск, по трети начин — на оптичния диск. Но при всички случаи има две състояния, та затова е „бинарно“, тоест — двоично.
Ама не сте наясно какво е двоично устройство?
Вземете една монета, сложете я на масата — вие виждате или ези, или тура. И докато не я обърнете, това няма да се промени. Ето ви аналог на бинарно запомнящо устройство.
Цялата мощ на съвременната информатика се крепи върху възможността разнообразна по вид информация да се „разглоби“ (кога успешно, кога не толкова) и да се запише в азбука с две букви, тоест в бинарно запомнящо устройство. Щом сме минимизирали буквите в азбуката (докарали сме ги до две), значи сме минимизирали и информацията, записвана с една буква и можем да използваме тази минимална информация като единица за измерване — един бит. Как се минимизира азбуката ще пиша допълнително, защото това е важно.
По чисто културни причини в съвременната информатика е прието битовете (тоест, елементарните запомнящи устройства) да се разглеждат в група по осем. Такава група наричат байт.
Ама защо точно по осем? — питате вие.
Ами по традиция, по културна традиция ще ви отговоря аз.
Няма логически, няма научни, няма технически причини за това. Просто някога фирмата IBM е приела да се групират по осем и тази традиция днес изглежда неразрушима — в байтове се измерва паметта на компютрите, в байтове се определя позицията (тоест — адресът) на един или друг елемент в оперативната памет на компютъра, в байтове се измерва и дължината на файла ви, на „хапки“ от по един байт върви и информацията по интернет (вярно, там предпочитат да наричат байта октет).
От гледище на операционната система всеки файл представлява просто поредица от байтове и тя го чете като поток (англ. stream) от байтове. Тоест, от гледище на операционната система всеки файл е „бинарен“. Това е общият подход — в крайна сметка операционната система „не знае“ каква информация има в този файл и как да я тълкува. Пък и не е нейна работа — на операционната система сме възложили предимно обслужващи функции.
 
На практика нещата са малко по-сложни. Операционните системи са находчив и оптимизиран софтуер, те четат от дисковете цели блокове от байтове (затова дисковете се определят като блоково устройство), запазват ги в оперативната памет (буферират ги, казват информатиците) — идеята е, когато приложната програма поиска информация от файл, операционната система да й я предостави по възможност от бързата оперативна памет, а не от бавния диск. Операционната система брои и помни колко заявки за четене е получила за всеки блок в буфера, та ако се наложи да се освобождава оперативна памет, премахват се блоковете, към които има по-малко заявки. Разумно.
Хубаво е да знаете, че когато записвате файл, не е задължително промените да бъдат записани върху диска веднага. Операционната система не бърза да извърши това сравнително бавно действие, а пази промените в буфера. Затова преди да си извадите „флашката“, трябва да извършите действия за „затварянето“ й — Safely Remove или нещо подобно. Така предупреждавате операционната система, че искате да си откачите външното устройство и тя вече наистина записва променената информация от буферите. Пак затова не е препоръчително да си изключвате компютъра от контакта, без да сте спрели операционната система — може да загубите информация.
Но тези сложнотии не променят това, което казах — операционната система предоставя на приложните програми информацията от файла като поток от байтове.
Но има едно изключение. Май всички операционни системи могат да бъдат „предупредени“ от приложната програма, че файлът, който ще се обработва, е текстов.
До не много отдавна една буква се представяше с един байт. Представяйте си засега нещата така. По-долу ще обяснявам какво се е променило.
Та като предупредите операционната система, че ще четете от текстов файл, тя събира в някакъв буфер в паметта поредицата от байтове (букви), като следи за байт (или комбинация от байтове), който означава „край на реда“.
Когато го намери, тя „подава“ на приложната програма байтовете дотук (тоест, събрания дотук текстов ред). И така нататък — до края на файла. Разбира се, когато текстът се записва във файл, в края на всеки ред трябва да се запише и знакът за край на реда.
Картинката илюстрира това:
text file
Квадратчетата трябва да означават байтовете във файла. Във всеки байт може да се запише един и само един символ. Обърнете внимание на дребната подробност, че шпацията е символ — точно като буквите. Няма как иначе да се запомни във файла. Обръщам внимание върху това, защото филолозите до неотдавна си мислеха, че шпацията е „нищо“ и не я осъзнаваха като символ. Комбинацията от символи \n е типичен начин да се отбележи управляващ байт с код 10, който в подобните на UNIX системи се използва като знак за край на реда. След втория ред няма символ за край на реда, защото тук свършва файлът. Ако имаше символ за край на реда, файлът щеше да притежава трети ред, празен.
И тук започват усложненията — в различните операционни системи различни байтове или комбинации от байтове се тълкуват като знак за края на реда.
В Windows (и в DOS) знакът за край на реда е поредица от два байта — CR (Carriage return, това е името на байта с код 13) плюс LF (Line feed, с код номер 10).
В Linux (и в подобните на UNIX операционни системи) се възприема като знак за край на реда само байтът LF (код 10). В недалечно минало операционната система на Макинтош използваше само байт CR (с код 13) като знак за края на реда, но от версията OS X, която е подобна на UNIX, също се използва байт LF (код 10).
Доскоро можеше да гледате на тази информация като на академично знание без практическо приложение, но интернет промени нещата. Ще дам пример.
Изпращам ви текстов файл по интернет. Аз работя в Linux и краят на реда в текста е отбелязан с LF (код 10). Да предположим, че вие работите с Windows. Записвате си някъде файла (той е с разширение .txt) и щраквате два пъти върху него с левия клавиш на мишката. Вашата операционна система (Windows) разпознава по разширението на файла, че това е текстов файл, стартира подразбиращия се текстов редактор (в Windows това е Notepad), отваря с него файла и… вие виждате на екрана пълна каша!
Какво се случва?
Текстовият редактор (Notepad) търси комбинацията от два байта за край на реда, не ги намира и показва на екрана каквото може…
Впрочем, Notepad е по-скоро изключение. Добре възпитаните съвременни текстови редактори „разбират“ различните начини за маркиране на края на редовете и дори умеят да ги редактират.
Да помислим сега какви действия са възможни с текстовия файл. Очевидно невъзможно е някаква приложна програма да прочете само десетия или само стотния ред. Предходните редове са с различна дължина и програмата трябва да изчете всички предходни редове, за да открие десетия или стотния. Затова програмистите наричат текстовия файл и файл с последователен достъп (до данните).
Очевидно е също така, че ако променим съдържанието на намерения ред — независимо от това дали го скъсяваме или го удължаваме, трябва да преместим, тоест да препишем и всички останали редове до края на файла, за да запазим тази промяна.
В миналото, когато оперативната памет на компютрите беше малка, тези особености на текстовия файл създаваха затруднения. Днес, колкото и да е старичък компютъра ви, без всякакви затруднения може да обработвате като един текстов файл Библията или „Записките...“ на Захари Стоянов.
Искам да обърна внимание върху една важна подробност — в текстовия файл се записва само информация за символите (букви, цифри, пунктуационни знакове и пр.) и маркер за край на редовете. Нищо друго. Няма курсив, няма „по-черни“ букви, няма информация за шрифта и за размера му (кегела). Само гол текст казват нашите програмисти; plain text на английски.
И това е много, много хубаво за филолога изследовател!
Голият текст ни освобождава от полиграфическата информация в печатния текст, която или има естетически функции, или подпомага зрително да се възприеме структурата на текста, но на нея не отговарят никакви езикови факти. Така голият текст с простата си структура — поредица от символи — максимално облекчава извличането на езикова информация.
 
* * *
И сега мога да кажа така — бинарен е всеки файл, чиято организация не е като на текстовия файл, тоест не съдържа поредица от байтове (букви), ограничени от символа за край на реда. Това е широкото разбиране на термина бинарен файл — всичко, което не е текстов файл, е бинарен файл.
Следователно файлът с картинка, звуковият файл, файлът с филмче са бинарни файлове. Бинарни файлове са и архивите, които създавате с програми като zip, rar, bzip2, 7z, бинарни са и файловете, които създавате с програмите от тъй наречените офис пакети: MSOffice, LibreOffice, OpenOffice, Calligra, GnomeOffice и пр.
Файловете, с които работят програмите за създаване и поддръжка на бази от данни, също са бинарни, макар често да съдържат текстова информация. Те илюстрират друга структура на файл, която накратко ще разясня.
Представете си таблица с три колони, в която всеки ред съдържа такава информация:
 
<Име> <Фамилия> <Телефон>
В жаргона на базите от данни всеки такъв ред от таблицата се нарича запис, а всеки запис е съставен от еднакви на брой и с еднаква ширина полета — в примера това са полетата за име, за фамилия и за телефон.
Очевидна трудност пред създателя на базата от данни е да прецени каква да бъде ширината на всяко едно от полетата. Например в полето <име> може да се наложи да запишем Ана или Иван, ама може да се наложи да запишем и Александрина. Затова обикновено полетата се правят по-широчки, а неизползваните в тях байтове се запълват с NUL (байт NUL не е цифрата 0, разгледайте кодовата таблица ASCII, например, тук). Та проблемът е, че файл с такава организация е голям, а полезната информация в него е по-малко. Ама цената си струва.
Във файла записите се записват, разбира се, последователно. Никакъв разделител между тях не е необходимо да се поставя, защото всички записи (и полетата в тях) са с определена и неизменна дължина. А това създава възможност приложната програма да поиска от операционната система, например, стотния запис. Операционната система няма да чете целия файл, а ще пресметне дължината на предишните 99 записа и ще изчете само стотния. Нещо повече — приложната програма може да измени съдържанието на записа (без да променя дължината на полетата!) и да поръча на операционната система да го запише във файла. Пак без да се преписва целият файл.
Затова файлове с такава организация (на записи и полета в записа) наричат файлове с произволен достъп — има се предвид, че те дават достъп за четене и писане в който и да било (в произволен) запис от файла.
Освен всичко друго тази организация на данните дава възможност много клиенти да работят с базата едновременно. Е, при известни мерки за защита — нали е глупаво двама души да редактират едновременно един запис.
И накрая, програмистите често използват термина бинарен файл с по-тясно, по-специализирано значение — така те наричат програмните файлове и програмните библиотеки, в които се съдържа изпълним от процесора на компютъра код. Руснаците дори използват като термин бинарник с това значение.
 
* * *
Е, добре, значи в текстовия файл (гол текст) няма никаква информация за форматиране на текста.
Ама ако искаме да отпечатаме текста — било на принтера, било в книга, — ако искаме да го покажем в интернет или да го пригодим за някакво мобилно устройство, трябва да впишем в текста информация за форматирането му.
На картинката отдолу показвам как изглежда цитатът в началната страница на miryan.org, ако го изчетем като текстов файл с cream или с друг текстов редактор.
 
cream and html
 
Това, както се досещате, е на стандартния форматиращ език за интернет — HTML (съкращение от HyperText Markup Language). Тук HyperText означава просто, че в текста се съдържат препратки към други текстове, картинки, страници. В недалечно минало за хипертекста бяха изписани безброй научни съобщения, статии и даже дисертации, пък днес той се оказва ежедневие.
Markup Language трябва да си го превеждаме като език за форматиране (на текста).
Marking up е работата на техническия редактор в старите печатници — той отбелязваше в полето на ръкописа, обикновено с цветен молив, инструкции за печатницата: как да се оформи текстът и заглавията, кое да се курсивира и пр. Та в информатиката просто заемат тази стара практика, ама на набора от инструкции придават статут на „език“.
Маркерите за форматиране на английски се наричат tags, та и на български често говорят за „тагове“. Маркерите най-често са по двойки: отварящ и затварящ, например <em> и </em> са двойка маркери за курсивиран текст (мнемоника от англ. emphasis ’изтъкване, подчертаване’). А двойката маркери <a> и </a> въвежда „хипертекстова“ препратка (мнeмоника от anchor, гръцкото ’котва’). И както виждате, след отварящия маркер трябва да се допишат някои допълнения — най-малко трябва да се допише към какво се препраща.
На картинката се вижда още нещо — тъй нареченото „оцветяване на синтаксиса“. Умните съвременни текстови редактори разпознават типа на текста във файла (по разширението към името на файла) и оцветяват по различен начин „служебната информация“. Това се прави за удобство на човека, само на екрана, и не се отразява във файла — той си остава „гол текст“.
В съвременната информатика има голямо множество от форматиращи езици. Любознателният читател може като начало да погледне страницата Typesetting в уикипедията.
Ако пък искате да сътрудничите на Читанката или пък да свалите от там форматиран текст, не е зле да погледнете страницата Описание на формата SFB и по-общите обяснения Защо SFB?. SFB е много опростен форматиращ език, а от текстовете, форматирани с него, сътрудниците на библиотеката произвеждат файловете във формат HTML, fb2 и epub — това са формати за електронни книги и могат да се четат практически на всякакви устройства.
Информатиците бързо разбраха, че подобна структура с двойки (отварящи и затварящи) маркери може да се използва не само за форматиране на текста, но и за структурирането му. В това отношение сега е най-популярен XML (eXtensible Markup Language). Примерът с телефонната база от данни в предишния раздел може да изглежда в XML горе-долу така:
<telephones>
    <person>
        <name>Пешо</name>
        <fname>Тошев</fname>
        <tel>0884-xxx-xxx</tel>
    </person>
    <person>
        <name>Мими</name>
        <fname>Пеева</fname>
        <tel>0888-xxx-xxx</tel>
    </person>
</telephones>
 
Ясно е, че такова структуриране на текста предполага предварителна класификация. Само че в науката класификацията е резултат от изследвания, от много изследвания. При това резултатът, обикновено, е оспорван и обсъждан.
Ето защо аз мисля, че макар XML форматът да е много използван и любим на информатиците (прочетете внимателно за структурата на BulTreeBank, например, разгледайте примерите), той не е подходящ за филолога изследовател. Далече по-просто е да се използва гол текст (вижте и Добре редактиран текст).
Е, добре. Един файл от типа HTML или XML текстов файл ли е, или не е?
Обикновено го разглеждат като текстов файл. Да, такъв файл може да се отвори в текстовия редактор и да се редактира. Но има една малка особеност — файл от типа HTML или XML може да бъде записан без каквито и да било маркери за край на реда. И пак ще си върши работата.
Я помислете — защо е възможно това?
 
* * *
В примера за текстов файл по-горе ви помолих временно да си представяте, че в един байт записваме една буква. И наистина, до не много отдавна това беше така. В Command Prompt на Windows това и сега обикновено е така.
Само че в един байт могат да се запомнят точно 256 различни символа и нито един повече. Въпрос на комбинаторика.
А това създаваше затруднения. В текстов файл на кирилица по никакъв начин не можеше да се изпише дори една гръцка думичка, например. Като прибавим и хаоса от стандарти (само за кирилица имаше поне четири), става ясно защо следяхме с голям интерес от самото начало на 90-те години работата на консорциума Unicode.
А идеята не беше сложна: просто символите да се запомнят не в поле от един байт (осем бита), а в поле от два байта (16 бита). Това веднага прави 65 536 различни комбинации (2 на степен 16), тоест възможност за 65 536 различни символа. Така горе-долу изглежда ядрото на стандарта, Basic Multilingual Plane (Plane 0). Стандартът неколкократно е разширяван, та в съвременния си вид предвижда 1 114 112 символа.
Няма да се впускам сега в подробности за стандарта Unicode — това си е за отделен разказ. Но за две неща трябва да разкажа.
Първо, макар символите да се кодират в Unicode с един, с два, че и с четири байта, структурата на текстовия файл остава същата — поредица от символи и маркер за край на реда. С техническите подробности се занимава операционната система или приложната програма.
Второ, понеже човечеството много обича да си прави живота сложен, в различните компютърни архитектури, изградени с различни процесори, поредици от байтове се четат по различен начин. Това най-добре се илюстрира с пример:
Ето информация за буквата голяма носовка (голям юс):
ѫ — CYRILLIC SMALL LETTER BIG YUS, U+046B
 
Ако не виждате символа, значи използвате шрифт, в който този символ просто не е реализиран. Поставете по-добри шрифтове и определете в настройките на браузъра си да използва тях. Например, набора шрифтове FreeFont на GNU.
С главни букви е изписано името на литеремата. В Unicode не използват термина литерема, а abstract character, но имат предвид същото — инварианта на различните реализации (литерите) на символа.
С израза U+046B се отбелязва поредният номер (кодът) на символа. В терминологията на Unicode: code point. Номерирането на символите започва от 0 (управляващия символ NUL). Префиксът U+ показва, че се посочва пореден номер (код) на символ от Unicode. Числовата стойност 046B е представена в шестнадесетичен запис на число.
Предимство на шестнадесетичния запис на числа е, че съдържанието на един байт се представя с точно две цифри. Е, понеже цифрите в арабския/индийския запис на числа са само десет, шестте букви от A до F се използват като цифри — и това ще трябва да го обяснявам някъде. Така 04 е съдържанието на старшия байт, а 6B — на младшия.
В някои компютърни архитектури процесорът очаква в оперативната памет тези два байта да бъдат разположени така: на някакъв адрес старшият байт, на следващия (по-голям) адрес — младшият: 04 6B. Да, ама в други архитектури (включително в Intel, каквато най-вероятно е архитектурата и на вашия компютър), процесорът очаква точно обратното — първо да е записан в паметта младшият байт, а след това старшият: 6B 04.
И сега, щом записваме символите в текстовия файл с два, че дори и с четири байта, явно трябва да има инструкция в каква последователност са записани те. Затова в началото на файла се поставя маркер за поредността на байтовете в текстовия файл. Този маркер се нарича BOM (Byte Order Mark).
Ако първите два байта във файла са FEFF, това означава, че поредността на байтовете е старши-младши, ако първите два байта са FFFE, това означава, че поредността е младши-старши.
U+FEFF е код на прозрачен символ, който се използва само при лигатури, следователно по никакъв начин не може да е в началото на текста; на код U+FFFE просто не е предвиден никакъв символ.
За да е животът по-весел, разбира се, има и още разновидности. Но принципа, мисля, все пак разясних.
 
В терминологията, която използват, информатиците съвсем недвусмислено са изразили отношението си към този философски проблем.
Когато байтовете се разполагат в паметта от старшия към младшия, те говорят за big-endian, а когато байтовете са разположени от младшия към старшия, за little-endian.
Ама това е пряка препратка към Джонатан Суифт — в Лилипутия се води дълга и кръвопролитна война за това, от кой край трябва да се чупи яйцето: от тъпия, както повелява традицията, или от острия? Big-endians нарича Суифт „тъповръхците“.
Пък вие, ако обичате още по-сложното, потърсете в интернет информация и за middle-endian. Щото и такава щуротия има.
За някои техники, които ще са необходими на филолога глотометрист, аз разказвам малко повече в cream в режим „експерт“, 20. BOM (Byte Order Mark).
 
* * *
Имайте още малко търпение.
Символите, стандартизирани в Unicode, не могат да се използват в „суров вид“. Най-малко поради това, че са с различна дължина — едни могат да се поберат в един байт, а за други трябват четири. Налага се да се вземат предвид и други съображения: компресиране на текста, премахване на байтове NUL (поради софтуерни съображения), по-лесен трансфер по мрежата и между различни компютърни системи.
Стандартизирани са редица процедури (алгоритми) за представяне на символите от Unicode в текстов файл или в оперативната памет на компютъра. Общото наименование за тези процедури на английски е encoding (кодиране). Сега ще спомена накратко само две от тях, най-често срещаните.
UTF-16. Това е кодирането на текста в съвременните версии на Windows. UTF означава Unicode Transformation Format и е префикс към цяло семейство кодиращи алгоритми, а 16 показва от колко бита е минималното поле за един символ. Така 2 байта (16 бита) се използват за всички символи от план 0 (Basic Multilingual Plane), а 4 байта (2 x 16 бита) за останалите символи. Може да срещнете и запис UTF-16LE, където суфиксът LE е от little-endian. Използването на BOM (маркер за реда на байтовете) е задължително.
UTF-8. Много разпространен алгоритъм за кодиране в интернет, според някои сведения използва се в повече от 80 процента от страниците. Това е и стандартното кодиране в операционните системи, приличащи на UNIX, включително и в линукс. Както личи от цифрата 8, минималното поле за един символ е един байт. Така се кодират символите с кодове от 0 до 127, тоест кодирането на тази област от символи съвпада със старата кодова таблица ASCII. Останалите символи от Unicode се кодират с два, три или четири байта, като в първия байт се записва информация колко е дълга поредицата от байтове. Така UTF-8 е „саморазпознаващо“ се кодиране и не се нуждае от BOM, Но маркерът може да се постави. Той е от три байта: EF BB BF — всъщност това е символът U+FEFF, представен в UTF-8. Уиндоуските програми се нуждаят от този маркер, за да разпознаят кодирането на текста в UTF-8.
 
Препратки с допълнителна информация за любознателните:
Unicode — хубава статия в уикипедията, която въвежда в историята и в структурата на стандарта.
Glossary of Unicode Terms — терминологичен речник на Unicode.
Unicode Frequently Asked Questions — разяснения за Unicode в общо взето разбираем вид.
Byte order mark — по-подробна статия по въпроса в уикипедията.
ASCII — много подробна страница за 7-битовия стандарт ASCII, върху който май стъпват всички съвременни кодови таблици; много подробни обяснения за управляващите символи (англ. control characters) с различните начини за въвеждането и изобразяването им.
Unicode block — статия в уикипедията, която съдържа таблица на всички блокове в Unicode. Под блок в Unicode се разбира общо взето мястото, където са събрани символите от една писменост (script), ама, за съжаление, не съвсем и не винаги. Филологът бързо ще се убеди, че кирилицата, например, е пръсната в четири блока. Вижте и раздела Glagolitic. В края на страницата има и таблица на плановете —това са блокове от по 65536 (2 на степен 16) символа.
cziborra.com — Страница на Роман Чибора, който представя много подробно положението с кодовите таблици в края на 90-те години. Вижте специално разделите ISO 8859 Alphabet Soup и Cyrillic Charset Soup. Тук soup очевидно трябва да го превеждаме като чорба.