Форум программистов, компьютерный форум CyberForum.ru
CyberForum.ru - форум программистов и сисадминов > > >
Восстановить пароль Регистрация
 
 
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
05.03.2012, 02:01     Десериализация. Конец потока обнаружен до завершения разбора   #1
При десереализации возникает следующая ошибка: Объект, не помечен, как сериализуемый. Конец потока обнаруен до завершения разбора.

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

Сериализация производится по следующей цепочке: объект - сериализация (в Stream) - массив байтов - двоичный файл

Код C#
1
2
3
4
5
// В stream содержится результат сериализации объекта
FileStream TestFileStream = new FileStream("tree.bin",FileMode.Create);
byte[] array2 = stream.ToArray();
TestFileStream.Write(array2, 0, array2.Length);
TestFileStream.Close();
Десереализация Двоичный файл - массив байтов (byte[]) - stream - десереализация (объект)

Код C#
1
2
3
4
5
6
7
8
9
10
FileStream TestFileStream = new FileStream("tree.bin", FileMode.Open);
byte[] array2 = new byte[TestFileStream.Length];
TestFileStream.Read(array2, 0, array2.Length);
 
MemoryStream stream2 = new MemoryStream();
stream2.Write(array2, 0, array2.Length);
try
{
  treeNode = (TreeNode)deserializer.Deserialize(stream2);
}
P.S. При использовании двоичного файла происходит такая же ошибка

P.P.S. Знаю, что так проще

Код C#
1
2
FileStream TestFileStream = new FileStream("tree.bin", FileMode.Open);
treeNode = (TreeNode)deserializer.Deserialize(TestFileStream);
Но нужно использовать массив байтов, см. выше почему
AdAgent
Объявления
05.03.2012, 02:01    Десериализация. Конец потока обнаружен до завершения разбора
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.03.2012, 02:01    Десериализация. Конец потока обнаружен до завершения разбора

Посмотрите здесь:

C# Обращение к элементу WinForms из потока, отличного от потока, в котором это элемент был создан

C# .NET 4.x Записать число в начало потока вернувшись с конца потока после записи нескольких элементов...

C# Нет полного завершения потока

C# Как из одного потока узнать состояние другого потока

C# Основной поток не дожидается завершения работы вторичного потока

C# WPF .NET 4.x Не получается с вторичного потока обратиться напрямую к объекту из главного потока

freeba
Модератор
878 / 728 / 40
Регистрация: 02.04.2010
Сообщений: 1,746
Записей в блоге: 2
05.03.2012, 13:23     Десериализация. Конец потока обнаружен до завершения разбора   #2
Так и не нашел объявления deserializer. Весь код в студию - куски как-то не представляют всей картины.
m0nax
Форумчанин
920 / 693 / 30
Регистрация: 12.01.2010
Сообщений: 1,468
05.03.2012, 14:12     Десериализация. Конец потока обнаружен до завершения разбора   #3
Код C#
1
2
MemoryStream stream2 = new MemoryStream();
stream2.Write(array2, 0, array2.Length);
замени на
Код C#
1
MemoryStream stream2 = new MemoryStream(array2);
и все заработает
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
05.03.2012, 16:45  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #4
Цитата Сообщение от m0nax Посмотреть сообщение
замени на
Код C#1 MemoryStream stream2 = new MemoryStream(array2);
и все заработает
Конец потока обнаружен до завершения разбора. Не помогло

Добавлено через 1 минуту
Код полностью

Чтение. Чтение
Код 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
            BinaryFormatter deserializer = new BinaryFormatter();
            TreeNode treeNode = null;
            FileStream TestFileStream = new FileStream("tree.bin", FileMode.Open);
            byte[] array2 = new byte[TestFileStream.Length];
            TestFileStream.Read(array2, 0, array2.Length);
 
            //MemoryStream stream2 = new MemoryStream();
            //stream2.Write(array2, 0, array2.Length);
 
            MemoryStream stream2 = new MemoryStream(array2);
 
            try
            {
                treeNode = (TreeNode)deserializer.Deserialize(stream2);
            }
            catch (SerializationException ex)
            {
                MessageBox.Show(errorMessage + "Невозможно десериализовать объект. Объект не помечен, как сериализуемый. "
                    + ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(errorMessage + "Невозможно десериализовать объект. " + ex.Message);
            }
 
            if (treeNode != null)
            {
                trvTree.Nodes.Add(treeNode);
                trvTree.ExpandAll();
            }
Добавлено через 1 минуту
Запись
Код C#
1
2
3
4
FileStream TestFileStream = new FileStream("tree.bin",FileMode.Create);
byte[] array2 = stream.ToArray();
TestFileStream.Write(array2, 0, array2.Length);
TestFileStream.Close(); 
freeba
Модератор
878 / 728 / 40
Регистрация: 02.04.2010
Сообщений: 1,746
Записей в блоге: 2
05.03.2012, 20:19     Десериализация. Конец потока обнаружен до завершения разбора   #5
Попробуйте так:
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static object SerializeFileToObject(string PathFile)
        {
            Stream stream;
            try //Перестраховка, путь задается OpenFileDialog
            {
                stream = File.OpenRead(PathFile);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation); return null;
            }
 
            object ret = new BinaryFormatter() { }.Deserialize(stream);
            stream.Close();
 
            return ret;
        }
Возможно FileStream'у не нравятся какие либо байты.
AdAgent
Объявления
05.03.2012, 20:19    Десериализация. Конец потока обнаружен до завершения разбора
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
05.03.2012, 22:52  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #6
нет, не помогло, а { } для чего?
freeba
Модератор
878 / 728 / 40
Регистрация: 02.04.2010
Сообщений: 1,746
Записей в блоге: 2
05.03.2012, 23:49     Десериализация. Конец потока обнаружен до завершения разбора   #7
привычка )))

Очень странно. Попробуйте тогда сериализовать в Stream, а не только извелкать им.
Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
06.03.2012, 10:08     Десериализация. Конец потока обнаружен до завершения разбора   #8
ужас, что вы тут наворотили?
вот, как ни странно, но все работает:
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var tn = new TreeNode();
var node1 = tn.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
 
using (var fs = File.Create("test.bin"))
{
    new BinaryFormatter().Serialize(fs, tn);
    fs.Flush();
}
 
using (var fs = File.Open("test.bin", FileMode.Open))
{
    var node = (TreeNode)new BinaryFormatter().Deserialize(fs);
    treeView1.Nodes.Add(node);
}
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
06.03.2012, 12:28  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #9
Цитата Сообщение от Konctantin Посмотреть сообщение
ужас, что вы тут наворотили?
вот, как ни странно, но все работает:
Посмотрите внимательнее пост 1. P.P.S.
freeba
Модератор
878 / 728 / 40
Регистрация: 02.04.2010
Сообщений: 1,746
Записей в блоге: 2
06.03.2012, 14:46     Десериализация. Конец потока обнаружен до завершения разбора   #10

Не по теме:

Konctantin, бЭйсик стайл



Потихоньку начинаем гадать на кофейной гуще. Выкладывайте объект который надо сериализовать, а потом десеариализовать в поток байтов. А мы уж как нибудь по-упражняемся...
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
06.03.2012, 19:09  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #11
Объект TreeNode. Дерево строит сам пользователь.
Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
06.03.2012, 20:32     Десериализация. Конец потока обнаружен до завершения разбора   #12
Посмотрите внимательнее пост 1. P.P.S.
мде... смотрел, и нифига не понял, зачем столько извращения, садомазо++ в моде?
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
06.03.2012, 21:13  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #13
Цитата Сообщение от Konctantin Посмотреть сообщение
мде... смотрел, и нифига не понял, зачем столько извращения, садомазо++ в моде?
Хочу записать в базу данных. Файл в базу не запишешь
Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
07.03.2012, 15:52     Десериализация. Конец потока обнаружен до завершения разбора   #14
ну так с этого и надо было начинать...

Добавлено через 18 часов 34 минуты
вот так как вы писали, и все так же работает, если что-то не так, то пожалуйста подробно все излагайте и показывайте что у вас есть и чего и от куда вы хотите, еще как поизвращаться, я не придумал.
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var tn = new TreeNode();
var node1 = tn.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
node1.Nodes.Add("123");
 
using (var fs = File.Create("test.bin"))
{
    new BinaryFormatter().Serialize(fs, tn);
    fs.Flush();
}
 
using (var fs = new BinaryReader(File.Open("test.bin", FileMode.Open)))
{
    // вернемся к тем же баранам и сначала получим массив байт
    byte[] b = fs.ReadBytes((int)fs.BaseStream.Length);
 
    // а потом же и используем его
    var node = (TreeNode)new BinaryFormatter().Deserialize(new MemoryStream(b));
    treeView1.Nodes.Add(node);
}
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
08.03.2012, 23:48  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #15
Цитата Сообщение от Konctantin Посмотреть сообщение
еще как поизвращаться, я не придумал.
да уж, изврат ещё тот

ваш код работает.

Приведу тогда полностью функции с базой данных

Добавлено через 59 секунд
Код 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
        /// <summary>
        /// Получить объект из БД.
        /// </summary>
        /// <param name="nameAttribute">Имя атрибута</param>
        /// <returns>Поток для десереализации</returns>
        public MemoryStream GetNode(string nameAttribute)
        {
            MySqlCommand mysql_query = new MySqlCommand("", mysql_connection);
            object value = null;
 
            // Считать дерево с БД
            if (OpenConnection())
            {
                // Генерация запроса
                mysql_query.CommandText = "SELECT attribute FROM  attribute_node WHERE Name='" + 
                    nameAttribute + "'";
                // Считывание дерева с БД
                try
                {
                    MySqlDataReader mysql_result = mysql_query.ExecuteReader();
                    if (mysql_result.HasRows == true)
                    {
                        mysql_result.Read();
                        value = mysql_result.GetValue(0);                        
                    }
                    mysql_result.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(errorProgram + ex.Message);
                }
                finally
                {
                    mysql_connection.Close();
                }
            }
 
            // Преобразование извлечённого значения в поток
            byte[] array = (byte[])value;
            MemoryStream streamBytes = new MemoryStream(array);
 
            return streamBytes;
        } 
Добавлено через 2 минуты
Код 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
        /// <summary>
        /// Конструктор (показать содержимое древовидного атрибута)
        /// </summary>
        /// <param name="stream">Поток для десереализации</param>
        public FormAttributeNode(MemoryStream stream)
        {
            InitializeComponent();
 
            // Десериализовать дерево            
            stream.Position = 0;
            TreeNode treeNode = null;
            try
            {
                treeNode = (TreeNode)new BinaryFormatter().Deserialize(stream);
            }
            catch (SerializationException ex)
            {
                MessageBox.Show(errorMessage + "Невозможно десериализовать объект. Объект не помечен, как сериализуемый. "
                    + ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(errorMessage + "Невозможно десериализовать объект. " + ex.Message);
            }
            // Вывести загруженное дерево на экран
            if (treeNode != null)
            {
                trvTree.Nodes.Add(treeNode);
                trvTree.ExpandAll();
            }
Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
09.03.2012, 09:35     Десериализация. Конец потока обнаружен до завершения разбора   #16
а самого интересного то и не показали, как вы то записываете в БД?
ладно. я тут накалякал на скорую руку, проверил, все работает:
Код 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
78
79
80
81
82
83
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using MySql.Data.MySqlClient;
 
/*
CREATE TABLE `dat` (
`entry`  int(9) NOT NULL AUTO_INCREMENT ,
`data`  blob NOT NULL ,
PRIMARY KEY (`entry`)
)
ENGINE=MyISAM
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=1
CHECKSUM=0
ROW_FORMAT=DYNAMIC
DELAY_KEY_WRITE=0
;
 */
 
namespace SerializeTreeNodeFromSQL
{
    public partial class Form1 : Form
    {
        const string ConnectionString = "Server=localhost;Port=3306;Uid=root;Pwd=mangos;Database=test;character set=utf8;Connection Timeout=10";
        
        public Form1()
        {
            InitializeComponent();
 
            TreeNode root = new TreeNode("root");
            root.Nodes.Add("node1");
            root.Nodes.Add("node2");
            root.Nodes.Add("node3");
            root.Nodes.Add("node4");
 
            SaveToDB(root);
 
            var result = ReadFromDB();
            treeView1.Nodes.AddRange(result);
        }
 
        private void SaveToDB(TreeNode node)
        {
            using (var stream = new MemoryStream())
            {
                new BinaryFormatter().Serialize(stream, node);
 
                using (var connection = new MySqlConnection(ConnectionString))
                {
                    var command = new MySqlCommand("REPLACE INTO `dat` VALUES(@key, @data);", connection);
                    command.Parameters.AddWithValue("@key", 1);
                    command.Parameters.AddWithValue("@data", stream.ToArray());
                    connection.Open();
                    command.ExecuteNonQuery();
                }
            }
        }
 
        private TreeNode[] ReadFromDB()
        {
            var list = new List<TreeNode>();
 
            using (var connection = new MySqlConnection(ConnectionString))
            {
                var command = new MySqlCommand("SELECT * FROM `dat`;", connection);
                connection.Open();
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var key = reader[0]; // unused
                        var node = new BinaryFormatter().Deserialize(new MemoryStream((byte[])reader[1]));
                        list.Add((TreeNode)node);
                    }
                }
            }
 
            return list.ToArray();
        }
    }
}
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
09.03.2012, 17:28  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #17
Запись в файл
Код C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        void btnSave_Click(object sender, EventArgs e)
        {
            // Сериализовать дерево
            MemoryStream streamBytes = new MemoryStream();
            TreeNode treeNode = trvTree.Nodes[0];
            try
            {
                new BinaryFormatter().Serialize(streamBytes, treeNode);
            }
            catch (SerializationException ex)
            {
                MessageBox.Show(errorMessage + "Невозможно сериализовать объект. Объект не помечен, как сериализуемый. "
                    + ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(errorMessage + "Невозможно сериализовать объект. " + ex.Message);
            }
 
            // Записать в БД
            CMySQL MySQL=new CMySQL("sourcedatabase");
            MySQL.SaveObjectAttribute(streamBytes, "attribute_node", "attribute", nameAttribute);
       }
Добавлено через 1 минуту
Код 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
        /// <summary>
        /// Сохранение атрибута-объекта в базу данных
        /// </summary>
        /// <param name="stream">Поток</param>
        /// <param name="table">Имя таблицы</param>
        /// <param name="column">Имя столбца</param>
        /// <param name="nameAttribute">Имя атрибута</param>
        public void SaveObjectAttribute(MemoryStream stream, string table, string column, 
            string nameAttribute)
        {
            // ====== БАЗА ДАННЫХ =======
            // Переменные для SQL-запросов
            MySqlCommand mysql_query = new MySqlCommand("", mysql_connection);
 
            // Сохранение дерева в БД
            if (OpenConnection())
            {
                mysql_query.CommandText = "INSERT INTO " + table + " VALUES(NULL,'" +
                    nameAttribute + "','" + stream.ToArray() +"')";
 
                try
                {
                    int intResult = mysql_query.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(errorProgram + ex.Message);
                }
                finally
                {
                    mysql_connection.Close();
                }
            };
         }
Добавлено через 4 минуты
ENGINE=MyISAM
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=1
CHECKSUM=0
ROW_FORMAT=DYNAMIC
DELAY_KEY_WRITE=0

как эти параметры можно получить?

Добавлено через 5 минут
P.S. и ещё я заметил, что все BLOB поля в базе занимают 13 байт. Пробовал сохранять достаточно длинные деревья
Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
09.03.2012, 17:45     Десериализация. Конец потока обнаружен до завершения разбора   #18
эти параметры не обязательны

Добавлено через 4 минуты
mysql_query.CommandText = "INSERT INTO " + table + " VALUES(NULL,'" +
nameAttribute + "','" + stream.ToArray() +"')";
и получите:
Код C#
1
"INSERT INTO `table` VALUES(NULL, 'nameAttribute', 'System.Byte[]')
Добавлено через 12 минут
тип поля можно поменять, к примеру longblob
и можно записать столько:
Код C#
1
2
3
4
5
6
7
8
9
10
TreeNode root = new TreeNode("root");
 
for (int i = 0; i < 100; ++i)
{
    TreeNode first = root.Nodes.Add("Node" + i);
    for (int j = 0; j < 30; ++j)
    {
        first.Nodes.Add("node" + j);
    }
}
ваша проблема в том, что вы неправильно записываете сериализованый объект.
делайте это через параметры:
Код C#
1
2
3
var command = new MySqlCommand("REPLACE INTO `dat` VALUES(@key, @data);", connection);
command.Parameters.AddWithValue("@key", 1);
command.Parameters.AddWithValue("@data", stream.ToArray());
MDmitry_
Форумчанин
59 / 27 / 2
Регистрация: 01.10.2010
Сообщений: 298
09.03.2012, 18:01  [ТС]     Десериализация. Конец потока обнаружен до завершения разбора   #19
Как в параметрах AUTO_INCREMENT поле обозначить?

Код C#
1
2
3
mysql_query.CommandText = "INSERT INTO " + table + " VALUES(NULL,@data)";
//mysql_query.Parameters.AddWithValue("@key",null);
mysql_query.Parameters.AddWithValue("@data", stream.ToArray());
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.03.2012, 18:14    Десериализация. Конец потока обнаружен до завершения разбора

Еще ссылки по теме:

C# Ожидание завершения потока

C# Обработка запроса на остановку потока внутри этого потока

C# Определить конец потока TcpClient

C# Ждать завершения потока (без зависания формы)

Konctantin
Форумчанин
775 / 579 / 24
Регистрация: 12.04.2009
Сообщений: 1,452
09.03.2012, 18:14     Десериализация. Конец потока обнаружен до завершения разбора   #20
Как в параметрах AUTO_INCREMENT поле обозначить?
совершенно ничего не понял, автоинкремент, это автоматически увеличивающееся значение, используется для автоформирования ключевых полей.
Yandex
Объявления
09.03.2012, 18:14    Десериализация. Конец потока обнаружен до завершения разбора
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать новую тему
Опции темы

Текущее время: 19:23. Часовой пояс GMT +4.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.7 PL3
Copyright ©2000 - 2014, vBulletin Solutions, Inc.