Сложные типы данных в си

Устранение неполадок при открытии файлов SI

Общие проблемы с открытием файлов SI

Autodesk Softimage 2015 не установлен

Дважды щелкнув по файлу SI вы можете увидеть системное диалоговое окно, в котором сообщается «Не удается открыть этот тип файла». В этом случае обычно это связано с тем, что на вашем компьютере не установлено Autodesk Softimage 2015 для %%os%%. Так как ваша операционная система не знает, что делать с этим файлом, вы не сможете открыть его дважды щелкнув на него.

Совет: Если вам извстна другая программа, которая может открыть файл SI, вы можете попробовать открыть данный файл, выбрав это приложение из списка возможных программ.

Установлена неправильная версия Autodesk Softimage 2015

В некоторых случаях у вас может быть более новая (или более старая) версия файла Softimage Image File, не поддерживаемая установленной версией приложения. При отсутствии правильной версии ПО Autodesk Softimage 2015 (или любой из других программ, перечисленных выше), может потребоваться загрузить другую версию ПО или одного из других прикладных программных средств, перечисленных выше. Такая проблема чаще всего возникает при работе в более старой версии прикладного программного средства с файлом, созданным в более новой версии, который старая версия не может распознать.

Совет: Иногда вы можете получить общее представление о версии файла SI, щелкнув правой кнопкой мыши на файл, а затем выбрав «Свойства» (Windows) или «Получить информацию» (Mac OSX).

Резюме: В любом случае, большинство проблем, возникающих во время открытия файлов SI, связаны с отсутствием на вашем компьютере установленного правильного прикладного программного средства.

Даже если на вашем компьютере уже установлено Autodesk Softimage 2015 или другое программное обеспечение, связанное с SI, вы все равно можете столкнуться с проблемами во время открытия файлов Softimage Image File. Если проблемы открытия файлов SI до сих пор не устранены, возможно, причина кроется в других проблемах, не позволяющих открыть эти файлы. Такие проблемы включают (представлены в порядке от наиболее до наименее распространенных):

Чтение и запись текстовых файлов

Последнее обновление: 07.06.2017

При работе с текстовыми файлами граздо проще работать с данными не как с отдельными символами, а как со строками с помощью
функций gets() и puts().

Функция puts() записывает в файл строку, то есть набор символов, который завершается символом ‘\0’. Она имеет следующий прототип:

int fputs(const char *s, FILE *stream);

Первый параметр функции — записываемая строка, а второй — указатель на файловый поток. В качестве результата функция возвращает неотрицательное целое число.
При ошибках в процессе записи возвращается значение EOF.

При записи строки нулевой символ ‘\0’ в файл не записывается.

Функция fgets() считывает из файла одну строку и имеет следующий прототип:

char * fgets(char *s, int n, FILE *sream);

Первый параметр представляет строку, в которую производится считывание. Второй параметр — число указывает, сколько символов необходимо считывать.
И третий параметр представляет файловый поток, из которого производится считывание.

При вызове функция считывает из файла не более n-1 символов. Функция прекращает чтение, когда прочтет n-1 символов или встретит
символ переноса строки \n. Все считанные символы записываются в строку s, в том числе символ \n. И также конец каждой строки дописывается нулевой символ ‘\0’.

При успешном завершении функция возвращает указатель s, а при ошибке или достижении конца файла возвращается значение NULL.

Применим функции в программе:

#include <stdio.h>

int main(void)
{
	char * message = "Hello \n world!\n An apple a day keeps the doctor away";
	char * filename = "D://data5.txt";
	char cc;
	FILE *fp;
	
	// запись в файл
	if((fp= fopen(filename, "w"))==NULL)
	{
		perror("Error occured while opening file");
		return 1;
	}
	// записываем строку
    fputs(message, fp);

	fclose(fp);
	
	// чтение из файла
	if((fp= fopen(filename, "r"))==NULL)
	{
		perror("Error occured while opening file");
		return 1;
	}
	// пока не дойдем до конца, считываем по 256 байт
	while((fgets(cc, 256, fp))!=NULL)
	{
		printf("%s", cc);
	}
	
	fclose(fp);
	return 0;
}

Вначале открываем файл на запись и с помощью вызова записываем в файл искомую строку.
Затем открываем файл на чтение и в цикле считываем из файла по 256 символов и выводим их на консоль с помощью вызова .
Когда данные в файле закончатся, функция возвратит NULL, и произойдет выход из цикла.

Другой пример работы с текстовыми файлами — копирование содержимого из одного файла в другой:

#include <stdio.h>

int main(void)
{
	char * filename1 = "D://data1.txt";
	char * filename2 = "D://data2.txt";
	char cc;
	FILE *f1, *f2;
	
	if((f1= fopen(filename1, "r"))==NULL)
	{
		perror("Error occured while opening file");
		return 1;
	}
	if((f2= fopen(filename2, "w"))==NULL)
	{
		perror("Error occured while opening file");
		return 1;
	}
	
	// пока не дойдем до конца, считываем по 256 байт
	while((fgets(cc, 256, f1))!=NULL)
	{
		// записываем строку
		fputs(cc, f2);
		printf("%s", cc);
	}
	
	fclose(f1);
	fclose(f2);
	
	return 0;
}

НазадВперед

fwrite

В языке программирования Си функции и соответственно реализуют файловые операции ввода и вывода. и объявлены в .

Запись в файл при помощи fwrite

fwrite определяется как

int fwrite ( const char * array, size_t size, size_t count, FILE * stream );

Функция записывает блок данных в поток. Таким образом запишется массив элементов в текущую позицию в потоке. Для каждого элемента запишется байт. Индикатор позиции в потоке изменится на число байт, записанных успешно. Возвращаемое значение будет равно в случае успешного завершения записи. В случае ошибки возвращаемое значение будет меньше .

Следующая программа открывает файл пример.txt, записывает в него строку символов, а затем его закрывает.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    FILE *fp;
    size_t count;
    char const *str = "привет\n";

    fp = fopen("пример.txt", "wb");
    if(fp == NULL) {
        perror("ошибка открытия пример.txt");
        return EXIT_FAILURE;
    }
    count = fwrite(str, sizeof(char), strlen(str), fp);
    printf("Записано %lu байт. fclose(fp) %s.\n", (unsigned long)count, fclose(fp) ==  ? "успешно"  "с ошибкой");

    fclose(fp);
    return ;
}

Режимы открытия файлов

Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе  предусмотрены константы, которые определяют режим открытия файлов (см. Таблица 1).

Таблица 1 — режимы открытия файлов
Константа Описание
ios_base::in открыть файл для чтения
ios_base::out открыть файл для записи
ios_base::ate при открытии переместить указатель в конец файла
ios_base::app открыть файл для записи в конец файла
ios_base::trunc удалить содержимое файла, если он существует
ios_base::binary открытие файла в двоичном режиме

Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове функции .

1
2

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

Объекты класса , при связке с файлами по умолчанию содержат режимы открытия файлов  . То есть файл будет создан, если не существует. Если же файл существует, то его содержимое будет удалено, а сам файл будет готов к записи. Объекты класса связываясь с файлом, имеют по умолчанию режим открытия файла    — файл открыт только для чтения. Режим открытия файла ещё называют — флаг, для удобочитаемости в дальнейшем будем использовать именно этот термин. В таблице 1 перечислены далеко не все флаги, но для начала этих должно хватить.

Обратите внимание на то, что флаги ипо описанию очень похожи, они оба перемещают указатель в конец файла, но флаг  позволяет производить запись, только в конец файла, а флаг  просто переставляет флаг в конец файла и не ограничивает места записи. Разработаем программу, которая, используя операцию , будет вычислять характеристики основных типов данных в С++ и записывать их в файл

Характеристики:

Разработаем программу, которая, используя операцию , будет вычислять характеристики основных типов данных в С++ и записывать их в файл. Характеристики:

  1. число байт, отводимое под тип данных
  2. максимальное значение, которое может хранить определённый тип данных.

Запись в файл должна выполняться в таком формате:

1
2
3
4
5
6
7
8
9
10
11
12

Необходимо открыть файл в режиме записи, с предварительным усечением текущей информации файла (строка 14). Как только файл создан и успешно открыт (строки 16 — 20), вместо оператора , в строке 22 используем объект . таким образом, вместо экрана информация о типах данных запишется в файл.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

Нельзя не заметить, что изменения в программе минимальны, а всё благодаря тому, что стандартный ввод/вывод и файловый ввод/вывод используются абсолютно аналогично. В конце программы, в строке 45 мы явно закрыли файл, хотя это и не обязательно, но считается хорошим тоном программирования. Стоит отметить, что все функции и манипуляторы используемые для форматирования стандартного ввода/вывода актуальны и для файлового ввода/вывода. Поэтому не возникло никаких ошибок, когда оператор был заменён объектом .

Текстовые файлы

Последнее обновление: 21.06.2017

Запись в текстовый файл

Чтобы открыть текстовый файл на запись, необходимо применить режим w (перезапись) или a (дозапись). Затем для записи применяется метод write(str),
в который передается записываемая строка. Стоит отметить, что записывается именно строка, поэтому, если нужно записать числа, данные других типов, то их
предварительно нужно конвертировать в строку.

Запишем некоторую информацию в файл «hello.txt»:

with open("hello.txt", "w") as file:
    file.write("hello world")

Если мы откроем папку, в которой находится текущий скрипт Python, то увидем там файл hello.txt. Этот файл можно открыть в любом текстовом редакторе и при желании изменить.

Теперь дозапишем в этот файл еще одну строку:

with open("hello.txt", "a") as file:
    file.write("\ngood bye, world")

Дозапись выглядит как добавление строку к последнему символу в файле, поэтому, если необходимо сделать запись с новой строки, то можно использовать эскейп-последовательность «\n».
В итоге файл hello.txt будет иметь следующее содержимое:

hello world
good bye, world

Еще один способ записи в файл представляет стандартный метод print(), который применяется для вывода данных на консоль:

with open("hello.txt", "a") as hello_file:
    print("Hello, world", file=hello_file)

Для вывода данных в файл в метод print в качестве второго параметра передается название файла через параметр file. А первый параметр представляет записываемую
в файл строку.

Чтение файла

Для чтения файла он открывается с режимом r (Read), и затем мы можем считать его содержимое различными методами:

  • readline(): считывает одну строку из файла

  • read(): считывает все содержимое файла в одну строку

  • readlines(): считывает все строки файла в список

Например, считаем выше записанный файл построчно:

with open("hello.txt", "r") as file:
    for line in file:
        print(line, end="")

Несмотря на то, что мы явно не применяем метод для чтения каждой строки, но в при переборе файла этот метод автоматически вызывается
для получения каждой новой строки. Поэтому в цикле вручную нет смысла вызывать метод readline. И поскольку строки разделяются символом перевода строки «\n», то чтобы исключить излишнего переноса на другую строку в функцию
print передается значение .

Теперь явным образом вызовем метод для чтения отдельных строк:

with open("hello.txt", "r") as file:
    str1 = file.readline()
    print(str1, end="")
    str2 = file.readline()
    print(str2)

Консольный вывод:

hello world
good bye, world

Метод readline можно использовать для построчного считывания файла в цикле while:

with open("hello.txt", "r") as file:
    line = file.readline()
    while line:
        print(line, end="")
        line = file.readline()

Если файл небольшой, то его можно разом считать с помощью метода read():

with open("hello.txt", "r") as file:
    content = file.read()
    print(content)

И также применим метод readlines() для считывания всего файла в список строк:

with open("hello.txt", "r") as file:
    contents = file.readlines()
    str1 = contents
    str2 = contents
    print(str1, end="")
    print(str2)

При чтении файла мы можем столкнуться с тем, что его кодировка не совпадает с ASCII. В этом случае мы явным образом можем указать кодировку с помощью
параметра encoding:

filename = "hello.txt"
with open(filename, encoding="utf8") as file:
    text = file.read()

Теперь напишем небольшой скрипт, в котором будет записывать введенный пользователем массив строк и считывать его обратно из файла на консоль:

# имя файла
FILENAME = "messages.txt"
# определяем пустой список
messages = list()

for i in range(4):
    message = input("Введите строку " + str(i+1) + ": ")
    messages.append(message + "\n")

# запись списка в файл
with open(FILENAME, "a") as file:
    for message in messages:
        file.write(message)

# считываем сообщения из файла
print("Считанные сообщения")
with open(FILENAME, "r") as file:
    for message in file:
        print(message, end="")

Пример работы программы:

Введите строку 1: hello
Введите строку 2: world peace
Введите строку 3: great job
Введите строку 4: Python
Считанные сообщения
hello
world peace
great job
Python

НазадВперед

Буферизация данных

Как уже говорилось ранее, когда мы выводим данные, они сначала помещаются в буфер. Очистка буфера осуществляется

  • 1) Если он заполнен
  • 2) Если поток закрывается
  • 3) Если мы явно указываем, что необходимо очистить буфер (здесь тоже есть исключения:)).
  • 4) Также очищается, если программа завершилась удачно. Вместе с этим закрываются и все файлы. В случае ошибки выполнения этого может не произойти.

Форсировать выгрузку буфера можно с помощью вызова функции fflush(File *). Рассмотрим два примера – с очисткой и без.

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

void main() {
	FILE *file;
	char c;

	file = fopen("C:/c/test.txt", "w");
	
	do {
		c = getch();
		fprintf(file, "%c", c);
		fprintf(stdout, "%c", c);
		//fflush(file);
	} while(c != 'q');

	fclose(file);
	getch();
}

Раскомментируйте вызов fflush. Во время выполнения откройте текстовый файл и посмотрите на поведение.

Буфер файла можно назначить самостоятельно, задав свой размер. Делается это при помощи функции

void setbuf (FILE * stream, char * buffer);

которая принимает уже открытый FILE и указатель на новый буфер. Размер нового буфера должен быть не меньше чем BUFSIZ (к примеру, на текущей рабочей станции BUFSIZ равен 512 байт).
Если передать в качестве буфера NULL, то поток станет небуферизированным. Можно также воспользоваться функцией

int setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

которая принимает буфер произвольного размера size. Режим mode может принимать следующие значения

  • _IOFBF — полная буферизация. Данные записываются в файл, когда он заполняется. На считывание, буфер считается заполненным, когда запрашивается операция ввода и буфер пуст.
  • _IOLBF — линейная буферизация. Данные записываются в файл когда он заполняется, либо когда встречается символ новой строки. На считывание, буфер заполняется до символа новой строки, когда запрашивается операция ввода и буфер пуст.
  • _IONBF – без буферизации. В этом случае параметры size и buffer игнорируются.

Пример: зададим свой буфер и посмотрим, как осуществляется чтение из файла. Пусть файл короткий (что-нибудь, типа Hello, World!), и считываем мы его посимвольно

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

void main() {
	FILE *input = NULL;
	char c;
	char buffer = {0};

	input = fopen("D:/c/text.txt", "rt");
	setbuf(input, buffer);

	while (!feof(input)) {
		c = fgetc(input);
		printf("%c\n", c);
		printf("%s\n", buffer);
		_getch();
	}

	fclose(input);
}

Видно, что данные уже находятся в буфере. Считывание посимвольно производится уже из буфера.

Пример использования

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

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  char buffer5 = {};  /* инициализируем нулями */
  int i, rc;
  FILE *fp = fopen("мойфайл", "rb");
  if (fp == NULL) {
    perror("Ошибка при открытии \"мойфайл\"");
    return EXIT_FAILURE;
  }
  for (i = ; (rc = getc(fp)) != EOF && i < 5; bufferi++ = rc);
  fclose(fp);
  if (i == 5) {
    puts("Прочитанные байты...");
    printf("%x %x %x %x %x\n", buffer], buffer1], buffer2], buffer3], buffer4]);
  } else
    fputs("Ошибка чтения файла.\n", stderr);
  return EXIT_SUCCESS;
}

Классы файлового ввода/вывода

Есть три основных класса файлового ввода/вывода в языке C++:

   ifstream (является дочерним классу istream);

   ofstream (является дочерним классу ostream);

   fstream (является дочерним классу ).

С помощью этих классов можно выполнить однонаправленный файловый ввод, однонаправленный файловый вывод и двунаправленный файловый ввод/вывод. Для их использования нужно всего лишь подключить заголовочный файл fstream.

В отличие от потоков cout, cin, cerr и clog, которые сразу же можно использовать, файловые потоки должны быть явно установлены программистом. То есть, чтобы открыть файл для чтения и/или записи, нужно создать объект соответствующего класса файлового ввода/вывода, указав имя файла в качестве параметра. Затем, с помощью оператора вставки () или оператора извлечения (), можно записывать данные в файл или считывать содержимое файла. После проделывания данных действий нужно закрыть файл — явно вызвать метод close() или просто позволить файловой переменной ввода/вывода выйти из области видимости (деструктор файлового класса ввода/вывода закроет этот файл автоматически вместо нас).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector