Форум программистов, компьютерный форум CyberForum.ru

string в бинарный файл - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
Delix
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 22
12.04.2013, 13:59     string в бинарный файл #1
Есть структура:
C++
1
2
3
struct Anketa {
    std::string name, family, brith_Date, tel;
};
Надо что бы они записывали в бинарный файл данные и затем можно было считать.

Целиком структуру не получается запихать в бинарник, из-за string, точнее получается, но при закрытии и открытии программы он уже не считает.

В обычный файл проблем нету записать и считать.
вот мои попытки, но ничего толкового не выходит. Помогите))
Спасибо.
C++
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
void Spravochnick::outputFile(const std::string& fname) {
        Node<Anketa>* temp = list.head();
        std::ofstream file_obj(fname.c_str());
        for (int i = 0; i < list.size(); i++){
            
            file_obj.write((char*)(temp->t.name.size()), sizeof(temp->t.name.size()));
            file_obj.write(temp->t.name.c_str(), temp->t.name.size());
            file_obj.write((char*)(temp->t.family.size()), sizeof(temp->t.family.size()));
            file_obj.write(temp->t.family.c_str(), temp->t.family.size());
            file_obj.write((char*)(temp->t.brith_Date.size()), sizeof(temp->t.brith_Date.size()));
            file_obj.write(temp->t.brith_Date.c_str(), temp->t.brith_Date.size());
            file_obj.write((char*)(temp->t.tel.size()), sizeof(temp->t.tel.size()));
            file_obj.write(temp->t.tel.c_str(), temp->t.tel.size());
 
//            В ОБЫЧНЫЙ ФАЙЛ
//            file_obj << temp->t.name << std::endl;
//            file_obj << temp->t.family << std::endl;
//            file_obj << temp->t.brith_Date << std::endl;
//            file_obj << temp->t.tel << std::endl;
            
            temp=temp->_next;
        }
        file_obj.close();
}
 
void Spravochnick::inputFile(const std::string& fname) {
    int s1;
        std::ifstream file_obj(fname.c_str());
        do {    
            Node<Anketa>* temp = new Node<Anketa>;
 
            file_obj.read((char**)&s1, sizeof(int));
            file_obj.read(temp->t.name.c_str(), s1);
//            file_obj.read((char*)(temp->t.family.size()), sizeof(temp->t.family.size()));
//            file_obj.read(temp->t.family.c_str(), temp->t.family.size());
//            file_obj.read((char*)(temp->t.brith_Date.size()), sizeof(temp->t.brith_Date.size()));
//            file_obj.read(temp->t.brith_Date.c_str(), temp->t.brith_Date.size());
//            file_obj.read((char*)(temp->t.tel.size()), sizeof(temp->t.tel.size()));
//            file_obj.read(temp->t.tel.c_str(), temp->t.tel.size());
            
//            В ОБЫЧНЫЙ ФАЙЛ
//            file_obj >> temp->t.name;
//            file_obj >> temp->t.family;
//            file_obj >> temp->t.brith_Date;
//            file_obj >> temp->t.tel;
            list.addTail(temp->t);
        } while (!file_obj.eof());
        list.delTail();
        file_obj.close();
}
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Catstail
Модератор
 Аватар для Catstail
21492 / 10245 / 1670
Регистрация: 12.02.2012
Сообщений: 17,129
12.04.2013, 14:14     string в бинарный файл #2
Могу посоветовать: напиши две функции: записать_строку и прочитать_строку. При записи в двоичный файл сначала определяешь длину строки (как целое); записываешь длину, а потом - соотв. количество байтов строки. Чтение выполняется так: читаешь длину, создаешь пустую строку нужной длины, читаешь строку.
Байт
 Аватар для Байт
13974 / 8805 / 1227
Регистрация: 24.12.2010
Сообщений: 15,949
12.04.2013, 14:23     string в бинарный файл #3
Delix, я бы это место
C++
1
 file_obj.write((char*)(temp->t.name.size()), sizeof(temp->t.name.size()));
записал иначе
C++
1
2
 int sz = temp->t.name.size();
file_obj.write(&sz, sizeof(int));
И аналогично для всех мест, где ты пишешь длины.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
12.04.2013, 14:31     string в бинарный файл #4
Delix, Вцелом все верно. Сначала записываем размер, потом содержимое, при считывании сначала считываем размер, потом выделяем нужное кол-во памяти, считываем содержимое. А вообще лучше пользоваться тем, что уже есть, к примеру boost::serialization
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
12.04.2013, 15:08     string в бинарный файл #5
попытка реализации
C++
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
#include <iostream>
#include <fstream>
#include <string>
 
struct Anketa
{
    std::string name, family, birthdate, tel;
};
 
std::ostream& operator<<(std::ostream& ost, Anketa const& a)
{
    return ost << a.name << '\n' << a.family << '\n' << a.birthdate << '\n' << a.tel;
}
 
int main()
{
    std::ofstream ofs("out.txt", std::ios::binary);
    std::string::size_type length;
    if(ofs.is_open())
    {
        Anketa arr[] = {Anketa{"name1", "family1", "birthdate1", "tel1"},
                        Anketa{"name2", "family2", "birthdate2", "tel2"},
                        Anketa{"n3", "f3", "bd3", "t3"}};
        for(auto const& val : arr)
        {
            length = val.name.size();
            ofs.write((char const*)&length, sizeof(length)).write(val.name.data(), length);
            length = val.family.size();
            ofs.write((char const*)&length, sizeof(length)).write(val.family.data(), length);
            length = val.birthdate.size();
            ofs.write((char const*)&length, sizeof(length)).write(val.birthdate.data(), length);
            length = val.tel.size();
            ofs.write((char const*)&length, sizeof(length)).write(val.tel.data(), length);
        }
        ofs.close();
        std::ifstream ifs("out.txt", std::ios::binary);
        if(ifs.is_open())
        {
            Anketa tmp;
            while(ifs.read((char*)&length, sizeof(length)))
            {
                tmp.name.resize(length);
                ifs.read(&tmp.name[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.family.resize(length);
                ifs.read(&tmp.family[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.birthdate.resize(length);
                ifs.read(&tmp.birthdate[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.tel.resize(length);
                ifs.read(&tmp.tel[0], length);
                std::cout << tmp << "\n\n";
            }
            ifs.close();
        }
        else
            std::cerr << "Unable to open input file\n";
    }
    else
        std::cerr << "Unable to open output file\n";
    return 0;
}
а вообще да, кто-нибудь, вбросьте на boost
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
12.04.2013, 15:22     string в бинарный файл #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Пример с бустом.

C++
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
#include <iostream>
#include <string>
#include <sstream>
 
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
 
struct Anketa
{
    std::string name, family, birthdate, tel;
    
private:
   friend class boost::serialization::access;
   
   template<typename Archive>
   void serialize(Archive& a, unsigned int)
   {
      a & name;
      a & family;
      a & birthdate;
      a & tel;
   }
};
 
int main()
{
   std::stringstream ss;
   boost::archive::binary_oarchive oarch(ss);
   const Anketa array[] = {
      Anketa{"name", "fam", "birth", "number"},
      Anketa{"name1", "fam1", "birth1", "number1"}
   };
   for (const auto& a : array)
   {
      oarch << a;
   }
   
   boost::archive::binary_iarchive iarch(ss);
   for (size_t i = 0; i < 2; ++i)
   {
      Anketa a;
      iarch >> a;
      std::cout << a.name << " " << a.family << " "
      << a.birthdate << " " << a.tel << std::endl;
   }
}
http://liveworkspace.org/code/by438$3
Delix
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 22
15.04.2013, 09:58  [ТС]     string в бинарный файл #7
igorrr37, по вашему варианту:
C++
1
2
3
4
5
6
7
8
length = temp->t.name.size();
            file_obj.write((char const*)&length, sizeof(length)).write(temp->t.name.data(), length);
            length = temp->t.family.size();
            file_obj.write((char const*)&length, sizeof(length)).write(temp->t.family.data(), length);
            length = temp->t.brith_Date.size();
            file_obj.write((char const*)&length, sizeof(length)).write(temp->t.brith_Date.data(), length);
            length = temp->t.tel.size();
            file_obj.write((char const*)&length, sizeof(length)).write(temp->t.tel.data(), length);
C++
1
2
3
4
5
6
7
8
9
10
11
12
temp->t.name.resize(length);
            file_obj.read(&temp->t.name[0], length);
            file_obj.read((char*)&length, sizeof(length));
            temp->t.family.resize(length);
            file_obj.read(&temp->t.family[0], length);
            file_obj.read((char*)&length, sizeof(length));
            temp->t.brith_Date.resize(length);
            file_obj.read(&temp->t.brith_Date[0], length);
            file_obj.read((char*)&length, sizeof(length));
            temp->t.tel.resize(length);
            file_obj.read(&temp->t.tel[0], length);
            file_obj.read((char*)&length, sizeof(length));
файл создает без проблем, а вот при попытке считать с файла, всё виснет, вся система, не могу даже остановить процесс программы, приходится перезагружать

С бустом интересно, но надо так попытаться понять.
Спасибо всем тем, кто отзывается

Добавлено через 2 часа 29 минут
C++
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
void Spravochnick::outputFile(const std::string& fname) {
    Node<Anketa>* temp = list.head();
    std::ofstream file_obj(fname.c_str());
    std::string::size_type length;
    int sz;
    for (int i = 0; i < list.size(); i++){
 
        sz = temp->t.name.size();
        file_obj.write((const char*)&sz,sizeof(int));
        file_obj.write(temp->t.name.data(), sz);
        
        sz = temp->t.family.size();
        file_obj.write((const char*)&sz,sizeof(int));
        file_obj.write(temp->t.family.data(), sz);
        
        sz = temp->t.brith_Date.size();
        file_obj.write((const char*)&sz,sizeof(int));
        file_obj.write(temp->t.brith_Date.data(), sz);
        
        sz = temp->t.tel.size();
        file_obj.write((const char*)&sz,sizeof(int));
        file_obj.write(temp->t.tel.data(), sz);
 
        temp=temp->_next;
    }
    file_obj.close();
}
C++
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
void Spravochnick::inputFile(const std::string& fname) {
    char sz_char;
    int sz_int;
    std::ifstream file_obj(fname.c_str());
    std::string::size_type length;
    do {    
        Node<Anketa>* temp = new Node<Anketa>;
        
        file_obj.read((char*)&sz_char, sizeof(int));
        sz_int = (int)sz_char;
        file_obj.read((char*)temp->t.name.data(), sz_int);
        
        file_obj.read((char*)&sz_char, sizeof(int));
        sz_int = (int)sz_char;
        file_obj.read((char*)temp->t.family.data(), sz_int);
        
        file_obj.read((char*)&sz_char, sizeof(int));
        sz_int = (int)sz_char;
        file_obj.read((char*)temp->t.brith_Date.data(), sz_int);
        
        file_obj.read((char*)&sz_char, sizeof(int));
        sz_int = (int)sz_char;
        file_obj.read((char*)temp->t.tel.data(), sz_int);
        
            list.addTail(temp->t);
    } while (!file_obj.eof());
    list.delTail();
    file_obj.close();
}
Сейчас ситуация такая, запись происходит и по откладчику происходит и считывание, хотя не много не правильное. Но при вызове функции AddTail(temo->t) уже почему то пустая, т.е. добавляет пустой элемент, опять с указателями напутал видимо.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.04.2013, 10:02     string в бинарный файл #8
Delix, По первых - писать лучше размер size_t, а не int-а, т.е.

C++
1
file_obj.write((const char*)&sz,sizeof(size_t));
При этом сам sz тоже должен быть size_t.

Второе:
C++
1
file_obj.read((char*)&sz_char, sizeof(int));
Это вам кто такому научил? Считывайте сразу в размер и sizeof(size_t).
Третье:
C++
1
file_obj.read((char*)temp->t.name.data(), sz_int);
Некорректно. Так делать нельзя. data() это константная функция, вы меняете внутренний буфер строки, а это запрещено. Выделяйте память нормально, потом создавайте из этого строку.
Delix
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 22
15.04.2013, 11:30  [ТС]     string в бинарный файл #9
ForEveR,
1, Хорошо, исправляюсь
2. Сам учусь, поэтому столько косяков
3. Да, уже понял, Спасибо
Сейчас такой вариант, запись:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        sz = temp->t.name.size();
        file_obj.write((const char*)&sz,sizeof(size_t));
        file_obj.write(temp->t.name.data(), sz);
        
        sz = temp->t.family.size();
        file_obj.write((const char*)&sz,sizeof(size_t));
        file_obj.write(temp->t.family.data(), sz);
        
        sz = temp->t.brith_Date.size();
        file_obj.write((const char*)&sz,sizeof(size_t));
        file_obj.write(temp->t.brith_Date.data(), sz);
        
        sz = temp->t.tel.size();
        file_obj.write((const char*)&sz,sizeof(size_t));
        file_obj.write(temp->t.tel.data(), sz);
чтение:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        file_obj.read((char*)sz, sizeof(size_t));
        char *temp_name = new char[sz + 1];
        file_obj.read(temp_name, sz);
        temp->t.name = temp_name;
        delete[] temp_name;
        
        file_obj.read((char*)sz, sizeof(size_t));
        char *temp_family = new char[sz + 1];
        file_obj.read(temp_family, sz);
        temp->t.family = temp_family;
        delete[] temp_family;
        
        file_obj.read((char*)sz, sizeof(size_t));
        char temp_bd[sz + 1];
        file_obj.read(temp_bd, sz);
        temp->t.brith_Date = temp_bd;
        delete[] temp_bd;
        
        file_obj.read((char*)sz, sizeof(size_t));
        char temp_tel[sz + 1];
        file_obj.read(temp_tel, sz);
        temp->t.tel = temp_tel;
        delete[] temp_tel;
запись происходит нормально, но чтение рушится после первой строки, точнее дебаггер даже ошибки не выдает, а после первой строчки не работает continue, т.е. с объявлением массива намудрил? Или с чтением в sz...

Добавлено через 20 минут
дебаггер виснет на этом месте, а при обычном запуске всё полчается, но вот так почему-то
Кликните здесь для просмотра всего текста
leo3? turtle
20_10_1980�3?
tel: 01
raph turtle
20_10_1980�3?
tel: 02

Откуда берет эти символы лишние?

Добавлено через 18 минут
например вот,
должно считывать 20_10_1980, считывает:
temp_bd 0x606050 "20_1-\\b0_1980\\377\\177"

Добавлено через 34 секунды
Причем, некоторые данные считываются нормально :\
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.04.2013, 11:40     string в бинарный файл #10
Delix, Пишите же через data() он не учитывает '\0' следовательно
C++
1
char *temp_name = new char[sz + 1];
+1 здесь лишнее.
C++
1
char temp_bd[sz + 1];
Через new надо.
Ну и присвоение к строке, т.к. без '\0' должно выглядеть так:
C++
1
temp->t.family = std::string(temp_family, sz);
Delix
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 22
15.04.2013, 11:50  [ТС]     string в бинарный файл #11
ForEveR, Благодарю, вот такой конечный вариант, который работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        file_obj.read((char*)&sz, sizeof(size_t));
        char *temp_name = new char[sz + 1];
        file_obj.read(temp_name, sz);
        temp->t.name = std::string(temp_name, sz);
        delete[] temp_name;
        
        file_obj.read((char*)&sz, sizeof(size_t));
        char *temp_family = new char[sz + 1];
        file_obj.read(temp_family, sz);
        temp->t.family = std::string(temp_family, sz);
        delete[] temp_family;
        
        file_obj.read((char*)&sz, sizeof(size_t));
        char *temp_bd = new char[sz + 1];
        file_obj.read(temp_bd, sz);
        temp->t.brith_Date = std::string(temp_bd, sz);
        delete[] temp_bd;
        
        file_obj.read((char*)&sz, sizeof(size_t));
        char *temp_tel = new char[sz + 1];
        file_obj.read(temp_tel, sz);
        temp->t.tel = std::string(temp_tel, sz);
        delete[] temp_tel;
Спасибо огромное Надо углубляться в тему
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.04.2013, 12:33     string в бинарный файл #12
Delix, Логичнее написать некую вспомогательную функцию.

C++
1
2
3
4
5
6
7
8
9
10
std::string read_next_field(std::ifstream& ifs)
{
   std::size_t sz = 0;
   file_obj.read(reinterpret_cast<char*>(&sz), sizeof(sz));
   char* temporary = new char[sz];
   file_obj.read(temporary, sz);
   const std::string field(temporary, sz);
   delete[] temporary;
   return field;
}
Okonenko Stanis
6 / 6 / 1
Регистрация: 06.02.2013
Сообщений: 71
19.04.2013, 09:23     string в бинарный файл #13
- Скажите пожалуйста igorrr37 на какой платформе сделан Ваш пример записи/чтения
структуры Anketa? И в каком стандарте C++? Ведь на BCB6 такая инициализация массива
структур Anketa явно не пройдет ...
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
19.04.2013, 10:34     string в бинарный файл #14
mingw 4.7.1, стандарт c++11
вот для шестого борланда
C++
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
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
 
struct Anketa
{
    std::string name, family, birthdate, tel;
};
 
std::ostream& operator<<(std::ostream& ost, Anketa const& a)
{
    return ost << a.name << '\n' << a.family << '\n' << a.birthdate << '\n' << a.tel;
}
 
int main()
{
    std::ofstream ofs("out.txt", std::ios::binary);
    std::string::size_type length;
    if(ofs.is_open())
    {
        Anketa arr[3];
        arr[0].name = "name1";
        arr[0].family = "family1";
        arr[0].birthdate = "birthdate1";
        arr[0].tel = "tel1";
 
        arr[1].name = "name2";
        arr[1].family = "family2";
        arr[1].birthdate = "birthdate2";
        arr[1].tel = "tel2";
 
        arr[2].name = "name3";
        arr[2].family = "family3";
        arr[2].birthdate = "birthdate3";
        arr[2].tel = "tel3";
        for(size_t i = 0; i < sizeof(arr) / sizeof(*arr); ++i)
        {
            length = arr[i].name.size();
            ofs.write((char const*)&length, sizeof(length)).write(arr[i].name.data(), length);
            length = arr[i].family.size();
            ofs.write((char const*)&length, sizeof(length)).write(arr[i].family.data(), length);
            length = arr[i].birthdate.size();
            ofs.write((char const*)&length, sizeof(length)).write(arr[i].birthdate.data(), length);
            length = arr[i].tel.size();
            ofs.write((char const*)&length, sizeof(length)).write(arr[i].tel.data(), length);
        }
        ofs.close();
        std::ifstream ifs("out.txt", std::ios::binary);
        if(ifs.is_open())
        {
            Anketa tmp;
            while(ifs.read((char*)&length, sizeof(length)))
            {
                tmp.name.resize(length);
                ifs.read(&tmp.name[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.family.resize(length);
                ifs.read(&tmp.family[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.birthdate.resize(length);
                ifs.read(&tmp.birthdate[0], length);
                ifs.read((char*)&length, sizeof(length));
                tmp.tel.resize(length);
                ifs.read(&tmp.tel[0], length);
                std::cout << tmp << "\n\n";
            }
            ifs.close();
        }
        else
            std::cerr << "Unable to open input file\n";
    }
    else
        std::cerr << "Unable to open output file\n";
    system("pause");
    return 0;
}
Okonenko Stanis
6 / 6 / 1
Регистрация: 06.02.2013
Сообщений: 71
20.04.2013, 10:34     string в бинарный файл #15
- Огромное спасибо igorrr37! Все работает в BCB6 отлично. Не подскажете-ли еще
такой момент? Можно-ли в двоичном файле сохраненных структур Anketa (у Вас это - Out.txt)
найти и ввести конкретную структуру Anketa, а не все подряд с самого начала?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.04.2013, 12:35     string в бинарный файл
Еще ссылки по теме:

C++ Запись string в бинарный файл
Std:string в бинарный файл и обратно C++
Запись string в бинарный файл C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
20.04.2013, 12:35     string в бинарный файл #16
Здесь размер структуры в файле неопределённый, так как она содержит std::string. Считывай весь файл в вектор структур, обрабатывай этот вектор и перезаписывай файл.
Yandex
Объявления
20.04.2013, 12:35     string в бинарный файл
Ответ Создать тему
Опции темы

Текущее время: 01:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru