Почему текстовый файл, созданный с этим кодом, имеет двоичный код ==? - PullRequest
1 голос
/ 07 июля 2019

В приведенном ниже коде я создаю два файла, один в текстовом формате, а другой в двоичном формате.Значки файлов показывают то же самое.Но характеристики обоих файлов одинаковы, включая размер, набор символов (== двоичный) и поток (октет).Почему нет текстового файла?Потому что, если я создаю текстовый файл явно, кодировка будет ASCII.

Версия компилятора - gcc (Ubuntu 8.3.0-6ubuntu1) 8.3.0.

Операционная система - Пробовал на обоихUbuntu 18.10 и 19.04.

Нет сообщений, отображаемых компилятором.

Команда, используемая для проверки файлов file --mime.

Вывод команды для файла Text1.txt: Text1.txt: application/octet-stream; charset=binary

Вывод команды для файла Text1.txt: Binary: application/octet-stream; charset=binary

Вывод команды od -xa FILENAME одинаков для обоих файлов и составляет:

0000000 0021<br> ! 0000001

#include<stdio.h>
void main(){

FILE *fp;
FILE *fp2;
int a = 10111110;

fp2 = fopen("Text1.txt","w");
fputc('!',fp2);

fp = fopen("Binary","wb");
fputc('!',fp);

}

Ожидаемый вывод - один файл с кодировкой ASCII и один с двоичным, фактический вывод - оба с кодировкой Binary

Ответы [ 2 ]

3 голосов
/ 07 июля 2019

Команда file диагностирует файлы как двоичные, а не как ASCII, поскольку вы записываете в файлы не-ASCII символы из-за неправильного использования fputc.

fputc("!",fp2); неверно. Первый аргумент fputc должен быть int со значением символа. "!" - строковый литерал, представляющий собой массив, который автоматически преобразуется в указатель на его первый символ.

GCC предупреждает вас об этом , говоря «предупреждение: передача аргумента 1 в« fputc »делает целое число из указателя без приведения [-Wint-преобразование]». Вы, очевидно, проигнорировали предупреждение. Не делай этого. Когда компилятор предупреждает вас о чем-то, обратите внимание, диагностируйте проблему и исправьте ее.

В результате указатель преобразуется в int, а этот int передается в fputc. Это может привести к записи в файл некоторого не-ASCII символа, что, в свою очередь, заставляет команду file диагностировать файл как двоичный.

Чтобы исправить это, измените строку "!" на один символ '!', чтобы вы передали один символ fputc с fputc('!',fp2);.

Кроме того, main не должно быть объявлено с void main(). Объявите его с помощью int main(void) или int main(int argc, char *argv[]) или другим способом, определяемым реализацией.

В системах Unix полученные файлы с исправленным кодом будут идентичны. Core Unix не различает текстовые и двоичные файлы, за исключением того, что некоторые приложения могут использовать метаданные (такие как «расширенные атрибуты») для характеристики файлов различными способами. Файлы, полученные из-за неправильного кода, могут быть или не быть идентичными, поскольку идентичные строковые литералы в разных местах могут иметь или не иметь один и тот же адрес, поэтому результирующий указатель может иметь или не иметь одно и то же значение.

0 голосов
/ 07 июля 2019

C обеспечивает различие в принципе между двоичным и текстовым потоками . Данные, пересекающие текстовый поток, могут подвергаться зависящим от реализации преобразованиям:

Символы могут быть добавлены, изменены или удалены при вводе и вывод для соответствия различным соглашениям для представления текста в среда хоста. Таким образом, не должно быть один к одному соответствие между символами в потоке и в внешнее представление. Данные, прочитанные из текстового потока, будут обязательно сравните с данными, которые были ранее выписаны этот поток, только если: данные состоят только из печатных символов и управляющие символы горизонтальной табуляции и новой строки; нет новой строки символу непосредственно предшествуют пробелы; и последнее персонаж - это символ новой строки. Будь космические символы, которые записывается непосредственно перед появлением символа новой строки при чтении in определяется реализацией.

( C2011, 7.21.2 / 2 )

На практике, однако, единственное преобразование, которое вы увидите для байтово-ориентированных потоков в любой системе, с которой вы, вероятно, встретитесь, - это преобразования конца строки в системах (в основном, в Windows), которые используют пары возврата каретки / перевода новой строки для ограничителей строки в тексте. файлы. Потоки текстового режима C преобразуются между этим внешним представлением и внутренним представлением C только для новой строки.

В Linux и современных MacOS на базе BSD этого даже нет - эти операционные системы на практике не делают различий между текстовыми и двоичными файлами, и совсем не удивительно, что ваши два механизма для создания файл выдает идентичные файлы.

Это совершенно отдельный вопрос, как внешняя программа, которая пытается угадать типы файлов, может интерпретировать любой данный файл, особенно очень короткий. Вероятность того, что файл будет обнаружен как текст, выше, если он содержит подлинный текст в виде слов и предложений.

...