Как считывать структуру из файла?
ну вы все так делаете. и да выше вам это уже посоветовали, работайте с бинарным пердставлением так проще в том случае если вы работаетте с файлом только в программе. Ну единственное замечание передавайте свою структуру как парметр для функции записи и чтения, а не объявляйте ее локально иначе все, что вы читаете доступно только в вашей функции.
21 мар 2017 в 11:11
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вот ваша структура
struct School < unsigned long mark; char subject[20]; char surname[20]; short age; >;
Вот так лучше писать и читать
void setInfo(School& school) < ofstream fout("out.txt", ostream::binary); //инициализация потока файла //Заполнили структурку cout > school.mark; cout > school.subject; cout > school.surname; cout > school.age; //записали fout.write((char*)&school, sizeof(School)); fout.close(); > void getInfo(School& school) < ifstream fin("out.txt", ios::in); while (!fin.eof()) < fin.read((char*)&school, sizeof(School)); >fin.close(); > int main() < School school; //так пишем setInfo(school); //так читаем getInfo(school); >
это что касается считывания из файла , далее для работы с множественными объектами струтктуры необходио использовать контейнеры, напрмиер vector или list .
вот пример функции которая запишет в файл все ваши объекты
void recAllSchoolObj(vector vSchool) < ostream fout("out.txt", ostream::binary) for(int i =0; ifout.close(); >
вот пример который прочитает
void readAllSchoolObj(vector vSchool) < School school; istream fin("out.txt"); while(!fin.eof) < fin.read((char*)&school, sizeof(School)); vSchool.push_back(school); >fin.close; >
поиск всех фамилий с одной оценкой
void findMark(vector vSchool, unsigned long mark) < cout>
Как читать структуры из файла c
Хотя функции getc()/putc() позволяют вносить в файл отдельные символы, но фактически мы имеем дело с бинарными файлами. Если мы записываем в файл строку, то в принципе мы даже можем открыть записанный файл любом текстовом редакторе и понять, что там было записано. Но не всегда данные могут представлять строки. И чтобы более наглядно разобраться с работой с бинарными файлами, рассмотрим еще одни пример — с записью-чтением структуры из файла.
#include #include struct person < char name[16]; int age; >; int save(char * filename, struct person *p); int load(char * filename); int main(void) < char * filename = "person.dat"; struct person tom = < "Tom Smith", 21 >; save(filename, &tom); load(filename); return 0; > // запись структуры в файл int save(char * filename, struct person *p) < FILE * fp; char *c; int size = sizeof(struct person); // количество записываемых байтов fp = fopen(filename, "wb"); //открываем файл для бинарной записи if (!fp) // если не удалось открыть файл < printf("Error occured while opening file \n"); return 1; >// устанавливаем указатель на начало структуры c = (char *)p; // посимвольно записываем в файл структуру for (int i = 0; i < size; i++) < putc(*c++, fp); >fclose(fp); return 0; > // загрузка из файла структуры int load(char * filename) < FILE * fp; char *c; int i; // для считывания одного символа // количество считываемых байтов int size = sizeof(struct person); // выделяем память для считываемой структуры struct person * ptr = malloc(size); fp = fopen(filename, "rb"); // открываем файл для бинарного чтения if (!fp) < printf("Error occured while opening file \n"); return 1; >// устанавливаем указатель на начало блока выделенной памяти c = (char *)ptr; // считываем посимвольно из файла while ((i = getc(fp))!=EOF) < *c = i; c++; >fclose(fp); // вывод на консоль загруженной структуры printf("%-20s %5d \n", ptr->name, ptr->age); free(ptr); return 0; >
В данном случае запись и чтение структуры выделены в отдельные функции: save() и load() соответственно.
Для записи в функции save() через параметр struct person *p получаем указатель на сохраняемую структур. Фактически его значением является начальный адрес блока памяти, где располагается структура.
Функция putc записывает отдельный символ в файл, однако нам надо записать структуру. Для этого мы создаем указатель на символ (который по сути представляет один байт) и устанавливаем этот указатель на начало блока памяти, выделенного для структуры.
c = (char *)p;
То есть в данном случае мы получаем адрес в памяти первого байта из блока памяти, которая выделена для структуры. И затем мы можем пройтись по всему этому блоку и получить отдельные байты и занести их в файл:
for (int i = 0; i
И в данном случае нам не важно, какие поля имеет структура, какой она имеет размер. Мы работаем с ней как с набором байт и заносим эти байты в файл. После занесения каждого отдельного байта в файл указатель c в блоке памяти перемещается на один байт вперед.
При чтении файла в функции load() используется похожий принцип только в обратную сторону.
Во-первых, для считывания структуры из файла мы выделяем блок динамической памяти для хранения прочитанных данных:
struct person * ptr = (struct person *) malloc(size);
После этого указатель ptr будет указывать на первый адрес блока из 20 байт (наша структура занимает 20 байт = 16 символов и 4 байта для числа int ).
Затем так как при прочтении мы получаем символы, устанавливаем указатель на первый байт выделенного блока и в цикле считываем данные из файла в этот блок:
c = (char *)ptr; // считываем посимвольно из файла while ((i = getc(fp))!=EOF)
Здесь стоит обратить внимание на то, что в данном случае на самом деле считываем даже не символ, а числовой код символа в переменную типа int и только потом передаем значение указателю c. Это сделано для корректной обработки окончания файла EOF. Это значение может представлять любое отрицательное число. И если бы мы сохранили отрицательное число (например, возраст пользователя был бы отрицательным), то оно было бы некорректно интерпретировано при чтении как конец файла, и итоговый результа был бы неопределенным. Поэтому более правильно считывать именно числовой код символа в переменную int, а затем числовой код передавать в char.
Запись и чтение массива структур
Выше приведен пример по работе с одной структурой. Но, как правило, при работе с файлами мы оперируем не одной структурой, а каким-то набором структур. Поэтому усложним задачу и сохраним и считаем из файла массив структур:
#include #include struct person < char name[20]; int age; >; int save(char * filename, struct person *st, int n); int load(char * filename); int main(void) < char * filename = "people.dat"; struct person people[] = < , , , >; int n = sizeof(people) / sizeof(people[0]); save(filename, people, n); load(filename); return 0; > // запись в файл массива структур int save(char * filename, struct person * st, int n) < char *c; // для записи отдельных символов // число записываемых байтов int size = n * sizeof(struct person); FILE * fp = fopen(filename, "wb"); if (!fp) < printf("Error occured while opening file\n"); return -1; >// записываем количество структур c = (char *)&n; for (int i = 0; i < sizeof(n); i++) < putc(*c++, fp); >// посимвольно записываем в файл все структуры c = (char *)st; for (int i = 0; i < size; i++) < putc(*c, fp); c++; >fclose(fp); return 0; > // загрузка из файла массива структур int load(char * filename) < char *c; // для считывания отдельных символов int m = sizeof(int); // сколько надо считать для получения размера массива int n; // количество структур в массиве FILE * fp = fopen(filename, "r"); if (!fp) < printf("Error occured while opening file\n"); return -1; >// выделяем память для хранения количества данных int *ptr_count = malloc(m); // считываем количество структур c = (char *)ptr_count; // пока не считаем m байт, сохраняем байт в выделенный блок для размера массива while (m > 0 && (*c = getc(fp)) != EOF) < c++; m--; >//получаем число элементов n = *ptr_count; free(ptr_count); // освобождаем память // выделяем память для считанного массива структур struct person * ptr = malloc(n * sizeof(struct person)); // устанавливаем указатель на блок памяти, выделенный для массива структур c = (char *)ptr; // считываем посимвольно из файла while ((*c= getc(fp))!=EOF) < c++; >// перебор загруженных элементов и вывод на консоль printf("\nFound %d people\n\n", n); for (int i = 0; i < n; i++) < printf("%-5d %-10s %5d \n", i + 1, (ptr + i)->name, (ptr + i)->age); // или так // printf("%-5d %-10s %5d \n", i + 1, ptr[i].name, ptr[i].age); > free(ptr); fclose(fp); return 0; >
Данная задача усложнена тем, что нам надо хранить массив структур, количество которых точно может быть неизвестно. Один из вариантов рещения этой проблемы состоит в сохранении некоторой метаинформации о файле в начале файла. В частности, в данном случае в начале файла сохраняется число записанных структур.
Запись во многом аналогична записи одной структуры. Сначала устанавливаем указатель на число n , которое представляет количество структур, и все байты этого числа записываем в файл:
c = (char *)&n; for (int i = 0; i
Затем подобным образом записываем все байты из массива структур — устанавливаем указатель на первый байт массива структур и записываем size байт в файл:
// посимвольно записываем в файл все структуры c = (char *)st; for (int i = 0; i
При чтении нам придется файктически считывать из файла два значения: количество структур и их массив. Поэтому при чтении два раза выделяется память. Вначале для количества элементов:
int *ptr_count = malloc(m);
Затем мы считываем первые 4 байта из файла для получения числа:
c = (char *)ptr_count; while (m > 0 && (*c = getc(fp)) != EOF) < c++; m--; >//получаем число элементов n = *ptr_count;
Затем аналогичные действия проделываем для массива структур.
struct person * ptr = malloc(n * sizeof(struct person)); // устанавливаем указатель на блок памяти, выделенный для массива структур c = (char *)ptr; // считываем посимвольно из файла while ((*c= getc(fp))!=EOF)
И результатом программы должен быть вывод считанных данных:
Found 4 people 1 Tom 23 2 Alice 27 3 Bob 31 4 Kate 29
Считывание структуры с файла
написала программу формирования структуры студент (факультет, кафедра, ФИО, специальность: код и расшифровка, курс, группа) и поиска информации по ФИО в формате: имя, специальность:код и расшифровка, курс, группа (вывод и на экран, и в файл). С использованием односвязного списка.
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
#include #include #include #include typedef struct stud { char faculty[5]; char department[5]; int idx; char name[100]; struct { int code; char text[100]; } specialization; int course; char group[10]; struct stud *next; } stud; int main() { stud* head = NULL; stud* tail = NULL; char nameBuf[100], s[100]; int idx = 1; FILE *finp, *fres; if ((finp = fopen ("lab5-input.txt", "w")) == 0) { puts ("Error with input file!"); return 0; } if ((fres = fopen ("lab5-result.txt", "w")) == 0) { puts ("Error with result file!"); return 0; } do { printf ("%i --- \n", idx); // enter name printf ("Enter student name (empty string to quit): "); gets (nameBuf); if (strlen (nameBuf) > 0) { // add new record if (head == NULL) { tail = head = (stud*) malloc (sizeof (stud)); } else { tail = tail->next = (stud*) malloc (sizeof (stud)); } // enter other data strcpy (tail->name, nameBuf); printf ("Enter faculty: "); scanf ("%s",tail->faculty); printf ("Enter department:"); scanf ("%s",tail->department); printf ("Enter specialization (code and description): "); scanf ("%i %s", &(tail->specialization.code), tail->specialization.text); printf ("Enter course: "); scanf ("%i", &(tail->course)); printf ("Enter group: "); scanf ("%s", tail->group); gets (s); tail->idx = idx++; tail->next = NULL; } } while (strlen (nameBuf) > 0); stud* cur = head; fprintf (finp, "---------------------------------STUDENTS-------------------------------|\n"); fprintf (finp, "|FACULTY|DEPARTMENT| NAME | SPECIAL |COURSE|GROUP|\n"); fprintf (finp, "| | | | CODE | TEXT | | |\n"); fprintf (finp, "------------------------------------------------------------------------|\n"); while (cur != NULL) %10s fprintf (finp, "-------------------------------------------------------------------------------- \n"); int perms; do { // enter name printf ("\nEnter necessary student's name (empty string to quit): "); gets (nameBuf); if (strlen (nameBuf) > 0) { stud* cur = head; while ((cur != NULL) && (strcmp(cur->name, nameBuf)!=0)) { stud* pocket = cur->next; cur = pocket; } if (cur == NULL) printf ("No such student! \n"); else if (strcmp (cur->name, nameBuf) == 0) %10s } } while (strlen (nameBuf) > 0); fclose(finp); return 0; }
Нужно переделать программу на считывание структуры из файла. Файл вида:
Вложения
lab5.txt (112 байт, 234 просмотров) |
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Считывание структуры из текстового файла
Привет. Как можно структуру считать из текстового файла, что бы потом можно было обрабатывать.
Считывание из структуры файла выдает неправильное значение
Всем привет.Такая проблема.У меня задача считать и вывести значение из файла(бинарного) с известной.
Считывание структуры из файла
У меня задача: Я ввожу в файл название пиццы, стандарт, признак качества, ФИО кассира и т.д Мне.
Считывание из файла структуры
Помогите пожалуйста, программа крашится, вот такая ошибка Debug Assertion Failed! Program: <.
Регистрация: 16.12.2012
Сообщений: 22
1 2 3 4 5
if ((finp = fopen ("lab5-input.txt", "w")) == 0) { puts ("Error with input file!"); return 0; }
такое открытие уничтожит все ваши данные вместо «w» используйте «a+»или «r+»
Добавлено через 22 минуты
надо реализовать чтение из файла результирующего после работы приведенного кода или вообще реализовать чтение и запись структуры в файл?
Регистрация: 03.11.2012
Сообщений: 8
Я не совсем поняла по поводу «w»: я ведь открываю файл, в котором нет ничего, а после ручного ввода записываю туда информацию
А по поводу второго вопроса: извините, я и вправду некорректно сформулировала задание. Было задание сформировать структуру и выводить информацию по запросу «ФИО», которое необходимо было реализовать двумя способами: 1)ручной ввод (которое получилось сделать); 2)считывать данные из файла, с которым и возникли проблемы
то есть эти две части не связаны между собой
Добавлено через 15 часов 19 минут
может у кого-то есть хоть какой-нибудь пример считывания структуры из файла так, чтобы информация об одном человеке указывалась в одной строке( хотя бы через массив, но лучше с использованием односвязного списка. очень надо, помогите
12243 / 7373 / 1734
Регистрация: 25.07.2009
Сообщений: 13,521
Сообщение было отмечено Памирыч как решение
Решение
Красоту сами наведёте.
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 50 51 52 53 54 55 56 57 58 59 60 61
#include #include #define FILE_NAME "lab5.txt" typedef struct stud { char faculty[5]; char department[5]; int idx; /* это поле для чего? */ char name[100]; struct { int code; char text[100]; } specialization; int course; char group[10]; struct stud *next; } stud_t; /* так как-то привычнее */ int main(void) { stud_t * head = NULL, * tail = NULL, * current, tmp; FILE * f; if ( ! ( f = fopen(FILE_NAME, "r") ) ) { perror("fopen"); exit(1); } while ( fscanf(f, "%4s %4s %99s %d %99s %d %9s", tmp.faculty, tmp.department, tmp.name, &tmp.specialization.code, tmp.specialization.text, &tmp.course, tmp.group) == 7 ) { if ( ! ( current = malloc(sizeof(stud_t)) ) ) { perror("malloc"); exit(1); } *current = tmp; current->next = NULL; if ( ! head ) head = current; else tail->next = current; tail = current; } if ( ferror(f) || fclose(f) ) { perror("ferror or fclose"); exit(1); } printf("faculty department name code text course group\n"); for ( current = head; current; current = current->next ) printf("%s %s %s %d %s %d %s\n", current->faculty, current->department, current->name, (current->specialization).code, (current->specialization).text, current->course, current->group); while ( head ) { tail = head->next; free(head); head = tail; } return 0; }
[andrew@andrew files]$ gcc -o stud_from_file stud_from_file.c [andrew@andrew files]$ ./stud_from_file faculty department name code text course group fpm math ivanov 5010206 ehd 2 pm12 htf bio sidorov 4050607 qer 1 he12 rtf phys kovalenko 3020406 pol 2 ph11 [andrew@andrew files]$
Как читать структуры из файла c
Есть у меня некая структура (struct).
Требуется создать файл, куда писать данные в виде этих структур. А также читать. А также перемещаться по файлу.
Как это сделать? (Плиз с ма-аленьким примером или в какую сторону копать).
Заранее спасибо.
Запись и чтение структур в/из файл(а)
От: | IT | linq2db.com |
Дата: | 11.10.02 04:19 | |
Оценка: | 100 (18) +2 -2 | |
#Имя: | FAQ.cpp.struct2file |
Почему ламерский? Нормальный вопрос, который обычно встречается большинству программеров.
ПА>Есть у меня некая структура (struct).
ПА>Требуется создать файл, куда писать данные в виде этих структур. А также читать. А также перемещаться по файлу.
ПА>Как это сделать? (Плиз с ма-аленьким примером или в какую сторону копать).
Всё зависит от многих вещей, как всегда
Для начала давай объявим твою структуру:
struct mystruct < int i; char buf[20]; double d; >;
Теперь, допусти, нам нужно положить её в файл средствами C/C++.
Семейсво функций FILE рассматривать не будет в связи с её архаичносью, и начнём сразу с варианта, который не входит в стандарт, но присутствует во многих компиляторах.
#include #include #include #include #include struct mystruct < int i; char buf[5]; double d; >; int main(int argc, char* argv[]) < // открываем файл int fh = _open("file.dat",_O_RDWR | _O_BINARY); if (fh == -1) < // или при необходимости создаём новый fh = _creat("file.dat",_S_IREAD | _S_IWRITE); if (fh == -1) // не шмагла :xz: return 1; > // готовим структуру для записи mystruct ms; memset(&ms,0,sizeof ms); ms.i = 1; ms.d = 2; // позиционируемся в конец файла _lseek(fh,0,SEEK_END); // добавляем новую структуру _write(fh,&ms,sizeof ms); // позиционируемся в начало _lseek(fh,0,SEEK_END); // читаем первую записанную структуру _read(fh,&ms,sizeof ms); return 0; >
Эта программа открывает файл (либо создаёт его при необходимости) и добавляет в него новую структуру, затем читает первый экземпляр.
Всё казалось бы нормально, но если ты посмотришь размер созддаваемого файла, то он всегда будет кратен 24 байтам (вариант Visual C++), хотя размер структуры равен 4+5+8=17 байт. Это происходит потому, что компиляторы по умолчанию выравнивают размер структур в целях оптимизации. Следовательно, наша первая задача отменить это поведение по умолчанию. Стандартных средств сделать это нет, но как правило компиляторы содержат специальную опцию коммандной строки и/или прагму, позволяющую это делать.
Ещё одной неверной деталью в нашем примере является использование типа переменной int. Для разных версий операционных систем размер инта может быть разным и лучше явно указать размер используемого типа — short или long.
Изменим описание структуры:
#pragma pack(push,1) struct mystruct < long i; char buf[5]; double d; >; #pragma pack(pop)
Теперь запись в файл даст вполне ожидаемый результат.
Здесь можно отметить ещё одну деталь. В качестве строки я использовал массив char[5]. Использование классов типа CString std::string не приведёт ни к чему хорошему. Фактически ты сохранишь не саму строку, а содержимое класса, который её реализует. Допустим, класс CMyString реализован следующим образом:
class CMyString < public: int len; char *str; // . >;
Объявление такой структуры как
struct mystruct < long i; CMyString str; double d; >;
будет фактически соответствовать следующему варианту:
struct mystruct < long i; int str_len; char *str_str; double d; >;
Т.е. в месте, где ты ожидаешь строку будет указатель на буфер в памяти, который (в смысле не буфер, а указатель на него) ты благополучно и сохранишь в файле.
Теперь рассмотрим вариант с потоками. Вообще-то, лучше конечно использовать новую версию , но у меня она до сих не вызывает никакого доверия. По-этому, воспользуемся старым вариантом:
#include #include #pragma pack(push,1) struct mystruct < long i; char buf[5]; double d; >; #pragma pack(pop) int main(int argc, char* argv[]) < // создаём или открываем файл fstream f("file.dat",ios::binary|ios::in|ios::out); // готовим структуру для записи mystruct ms; memset(&ms,0,sizeof ms); ms.i = 1; ms.d = 2; // позиционируемся в конец файла f.seekp(0,ios::end); // добавляем новую структуру f.write((unsigned char*)&ms,sizeof ms); // позиционируемся в начало f.seekp(0,ios::beg); // читаем первую записанную структуру f.read((unsigned char*)&ms,sizeof ms); return 0; >
Ниже вариант использования Windows API вместо фуекций CRTL:
#include #pragma pack(push,1) struct mystruct < long i; char buf[5]; double d; >; #pragma pack(pop) int main(int argc, char* argv[]) < // создаём или открываем файл HANDLE fh = ::CreateFile( TEXT("file.dat"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // готовим структуру для записи mystruct ms; memset(&ms,0,sizeof ms); ms.i = 1; ms.d = 2; // позиционируемся в конец файла ::SetFilePointer(fh,0,0,FILE_END); // добавляем новую структуру DWORD dw=0; ::WriteFile(fh,&ms,sizeof ms,&dw,NULL); // позиционируемся в начало ::SetFilePointer(fh,0,0,FILE_BEGIN); // читаем первую записанную структуру ::ReadFile(fh,&ms,sizeof ms,&dw,NULL); return 0; >
Еще можно привести вариант исользования класса CFile из MFC, но, в принципе, он будет не очень сильно отличаться.
Может я немного увлёкся, но главное чтобы было понятно
ЗЫ. Далше тебя ждут другие вопросы:
- Как узнать количество записанных структу в файле?
Правильный ответ — не вычислять это по размеру файла, а добавить в начало заголовок (специальную структуру), содержащую необходимую служебную информацию: фактический размер файла, версию формата, число записей, смещение к первому блоку и т.п. - Как добавлять записи переменной длины?
Можно к каждой записи добавить свой заголовок, описывающий её структуру. - Как удалять ненужные записи из файла?
Можно просто помечать их как удалённые, а в последствии организовать упаковку файла. Можно организовать список удалённых страниц и использовать их в дальнейшем вместо добавления новых в конец. - Как обеспечить совместный доступ к файлу из нескольких программ.
Блокировки, отдельный сервер доступа и ещё куча всяких вариантов. - Как сделать динамическую структуру записей в файле.
У-у-у.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Про файлы.
От: | Панкратов Александр |
Дата: | 11.10.02 04:43 |
Оценка: |
Огромное спасибо, очень исчерпывающе.
IT>После всего этого возникает вполне законный вопрос — а может лучше сразу взять стандартную базу данных?
IT>Шутю я, шутю.
Если бы речь шла об обычных виндах — я бы так и сделал
Однако все происходит в WinCE. Да еще на обкоцанном варианте Casio. Поэтому с ADOCE возникают некоторые проблемы.
Re[2]: Переносимость short и long ?
От: | Vi2 | http://www.adem.ru |
Дата: | 11.10.02 04:52 | |
Оценка: |
Здравствуйте IT, Вы писали:
IT>Ещё одной неверной деталью в нашем примере является использование типа переменной int. Для разных версий операционных систем размер инта может быть разным и лучше явно указать размер используемого типа — short или long.
Интересно, неужели для разных версий операционных систем размеры short или long, в отличие от int, одинаковы?
Насколько я помню, есть sizeof(short int)
Так что и использование short или long не даст переносимости.
Vita Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: Про файлы.
От: | orangy | http://twitter.com/orangy |
Дата: | 11.10.02 06:19 | |
Оценка: | 6 (1) |
Здравствуйте Панкратов Александр, Вы писали:
IT>>После всего этого возникает вполне законный вопрос — а может лучше сразу взять стандартную базу данных?
ПА>Однако все происходит в WinCE. Да еще на обкоцанном варианте Casio. Поэтому с ADOCE возникают некоторые проблемы.
Тогда у тебя возникает еще ряд проблем:
— CE система юникодная, осторожнее со строками при записи и чтении
— не помню какой Endian на Casio (это кажется был MIPS), осторожнее с переносом файлов с win32
— нельзя игнорировать alignment, точнее он должен быть на 4 байта. MIPS не позволяет адресовать 32-битное число по невыровненному адресу
это важно, если ты собираешься читать массивами структур
I would recommend using WINAPI CreateFile, ReadFile, . functions тьфу блин, совсем зарапортавался.
Используй WINAPI CreateFile, ReadFile, . — в winCE другого может и не быть, лучше всего завернуть это дело в портабельную оболочку.
Всегда указывай полный путь до файла, в WinCE нет понятия «текущая директория», если нужно — возьми у текущего модуля.
TCHAR buf[_MAX_PATH+30];
GetModuleFileName(hInstance, buf, _MAX_PATH);
Если объёмы данных небольшие — используй XML. Была где-то библиотека портированная для CE, поищи.
Янус 1.0 alpha 10: Orangy
«Develop with pleasure!»
Re[3]: Переносимость short и long ?
От: | Павел Кузнецов |
Дата: | 11.10.02 08:13 |
Оценка: |
Здравствуйте Vi2, Вы писали:
IT>>Ещё одной неверной деталью в нашем примере является использование типа переменной int. Для разных версий операционных систем размер инта может быть разным и лучше явно указать размер используемого типа — short или long.
Здесь IT был не вполне точен.
Vi2>Интересно, неужели для разных версий операционных систем размеры short или long, в отличие от int, одинаковы?
Не только для разных операционных систем, но и для разных компиляторов на одной операционной системе размеры short, long и int могут различаться.
Vi2>Насколько я помню, есть sizeof(short int)
Кроме указанного соотношения есть еще требования к минимальному диапазону представляемых значений:
short -32767 . . . +32767 (минимум 16 бит) int -32767 . . . +32767 (минимум 16 бит) long -2147483647 . . . +2147483647 (минимум 32 бита)
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Переносимость short и long ?
От: | IT | linq2db.com |
Дата: | 11.10.02 11:31 | |
Оценка: |
Здравствуйте Vi2, Вы писали:
Vi2>Интересно, неужели для разных версий операционных систем размеры short или long, в отличие от int, одинаковы?
Ну если считать Windows 3.1 и Windows 95 разными версиями то да К тому же MS выпустила там чего-то 64 разрядное кажется, там уже и long поплывёт.
Vi2>Насколько я помню, есть sizeof(short int)
Vi2>Так что и использование short или long не даст переносимости.
Ладно придираться, я только обозначил проблему.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Запись и чтение структур в/из файл(а)
От: | AndrewS42 |
Дата: | 06.06.05 06:58 |
Оценка: |
Здравствуйте, IT, Вы писали:
IT>Всё зависит от многих вещей, как всегда
Это точно! Несмотря на то, что топику уже несколько лет, я хотел бы вставить свои 5 копеек в обсуждаемую тему, тем более, что эта тема находится в статьях сайта, а значит не имеет срока давности.
Наиболее правильным и переносимым (но медленным) будет вообще не сохранять в файл структуру целиком. Более того, не желательно даже int записывать в файл напрямую. Одна из причин уже была озвучена в топике: несовпадающие размеры int в разных компиляторах даже на одной платформе. Другая причина кроется в переносимости. Не факт, что ваша программа (или даже её отдельный модуль) никогда не переедут под UNIX. В отличие от Windows, UNIX существует на большом зоопарке платформ. Некоторые из них имеют big-endian представления чисел (первым идёт старший байт). Если на такой платформе сохранить int в файл как есть, а затем прочитать этот файл на Intel-платформе, то мы получим совершенно другое число. Например (пусть размер int будет 32 бита), если на big-endian сохранили 0x12345678, то в little-endian прочитаем 0x78563412.
Для большинства эти детали не существенны, так как не так уж и много программистов (надо признаться, и я в том числе) пишут сразу для нескольких платформ. Но, по крайней мере, задуматься о потенциальных проблемах переносимости надо.
Как же сохранять данные в файл, чтобы и файл, и программа его читающая были переносимы? Ответ уже был в этом топике: сохранять всё в xml или другом текстовом файле. Однако, если объём данных велик, и от двоичных данных никуда не деться, то сохранять все данные следует побайтно. Пример сохранения 32-битного int (предполагаем, что система, где char имеет размер, не равный 8 бит, нам не попадётся):
#include const char filename[] = "file.dat"; void read_int(FILE* f, int* d) < unsigned char buf[4]; unsigned char* p = buf; fread(buf, sizeof(buf), 1, f); // portable *d = *p++; *d += *p++ // fread(d, sizeof(*d), 1, f); // not portable > // read_int void write_int(FILE* f, int d) < unsigned char buf[4]; unsigned char* p = buf; *p++ = d & 0xff; *p++ = (d >> 8) & 0xff; *p++ = (d >> 16) & 0xff; *p = (d >> 24) & 0xff; fwrite(buf, sizeof(buf), 1, f); // portable // fwrite(&d, sizeof(d), 1, f); // not portable > // write_in void help() < fprintf(stderr, "Usage: fileio \n" ); exit(1); > // help() int main(int argc, char *argv[]) < const int data = 0x12345678; FILE* fi; FILE* fo; int tmp; char err_msg[255]; if (argc != 2) help(); if (! strcmp(argv[1], "w")) < fo = fopen(filename, "w"); if (! fo) < sprintf(err_msg, "Can not open file '%s'", filename); perror(err_msg); exit(1); > write_int(fo, data); fclose(fo); > else if (! strcmp(argv[1], "r")) < fo = fopen(filename, "r"); if (! fo) < sprintf(err_msg, "Can not open file '%s'", filename); perror(err_msg); exit(1); > read_int(fo, &tmp); fclose(fo); printf("Readed %#08x. Must be %#08x\n", tmp, data); > else help(); return 0; > // main()
Если гложут вопросы быстродействия, особенно в свете того, что big-endian систем не много и ради этой редкости мы замедляем считывание файлов, то необходимо ввести условную компиляцию: на little-endian системе читать int целиком, на big-endian – побайтно. Опять же, нельзя забывать про отличия размера int на разных платформах.
Хочу отметить, что я далеко не гуру в этом вопросе, и все мои замечания основаны лишь на изучении и портировании Open source ПО на компьютер RM200 (RISC-процессор R4000 (big-endian), ОС SINIX).
Всего Вам
Андрей
Re[2]: Запись и чтение структур в/из файл(а)
От: | MaximE |
Дата: | 06.06.05 07:20 |
Оценка: |
[]
> Как же сохранять данные в файл, чтобы и файл, и программа его читающая были переносимы? Ответ уже был в этом топике: сохранять всё в xml или другом текстовом файле. Однако, если объём данных велик, и от двоичных данных никуда не деться, то сохранять все данные следует побайтно. Пример сохранения 32-битного int (предполагаем, что система, где char имеет размер, не равный 8 бит, нам не попадётся):
Автор: MaximE
Дата: 02.04.05
Автор: MaximE
Дата: 06.04.05
—
Maxim Yegorushkin