Logo

רד-בורד: ארכיון

ראשי > תיכנות > Cast אוטומאטי ל byte[] - או שנקרא לזה Serializatio

30/08/2006 13:09:52 HLL
חפרתי המון המון לא ממש הצלחתי למצוא מענה אופטימלי לבעייה הבאה:

בסי / פיפי אם אתה רוצה לדוגמא
ליצור מערך של בתים מתוך נתוני מבנה מסויימים זה ממש לא בעייה
קוד:typedef struct {
int a;
int b;
}myStruct;
...
myStruct moshe;
byte *pBuf = (byte *)&moshe;

לדוגמא כמו שממשים איזהשהוא מבנה מסויים של חבילה בסוקטים, בונים מבנה עם השדות ואז משתמשים בCast הזה כדי לשלוח את הנתונים באמצעות הסוקט החל מהכתובת &moshe ובגודל sizeof(moshe) {או myStruct}
קיצר חפרתי קצת ב MSDN ובגוגל ולא ממש הצלחתי למצוא משהוא שעובד ככ טוב כמו זה ב C#. ניסיתי פתרון unsafe{} - ליצור מערך חדש של בתים, להצביע אליו ואז מתוך הבלוק להעתיק את הנתונים מן הstruct למצביע הbyte[] - אבל כשניסיתי להגדיר שהמבנה יהיה fixed כי אני רוצה להשתמש בו נתקלתי בבעיות מעצבנות של הקומפיילר

ניסיתי גם לבדוק פתרון של Serialization אבל המנגנון הזה סתם מסורבל מידי בשביל דבר תמוהה שכזה

מי שיוכל לעזור לי לפתור את הסוגייה הזו, זה יהיה ממש נחמד.

תודה
HLL

P.S אני משתמש ב Studio 2005 (אם זה בכלל ישנה)[ההודעה נערכה על-ידי HLL ב-30/08/2006 13:11:15]
30/08/2006 20:48:09 HLL
אוקע אוקע אוקע
עשיתי את זה בדרך ממש ממש מעפנה
השאלה עדיין תקפה כי זה פתרון מעפן
למרות שהוא אכן גלובאלי לחלוטין, הוא לא ממש טוב.
מה שעשיתי זה הקצתי זיכרות unmanaged עם אובייקט Marshal העתקתי את הנתונים לבאפר שהקצתי בעזרת StructToPtr, ומשם בבלוק unsafe העתקתי את הנתונים שאליהם הצביע המצביע, לבלוק byte[] managed.

קיצר בעע אבל זה עובד

ויש גם את הבעייה של ה Aligment שהגודל (והמיקומים היחסיים של האלמנטים בו) של המבנה הוא לא בדיוק סכום גדלי הטיפוסים בבתים אז השתמשתי ב StructViewAttribute אם אני לא טועה או משו כזה לקבוע את האלין ל1[ההודעה נערכה על-ידי HLL ב-30/08/2006 22:12:47]
30/08/2006 21:24:11 ziv
תגיד לי... אני לא בטוח אם זה מה שרצית אבל אולי אפשר לעשות את זה קצת יותר פשוט בעזרת union... לא חושב ככה?
30/08/2006 21:36:45 HLL
union זו חפיפה בין 2 אלמנטים שונים היושבים בעצם באותו מקום בזיכרון

הממ
עכשיו שאני חושב על זה כן, אולי זה אפשרי, לא בעצם לא - אם אני עושה יוניון בין המבנה לבין byte[] יוצא שהרפרנס ל [] יושב באותו כתובת כמו המבנה... הרפרנס לא עוזר לי הרבה ...
אבל שוב גם אם זה היה אפשרי זה לא מספק לי מענה כללי...
30/08/2006 21:39:16 ziv
התכוונתי למשהו בסגנון הזה:
קוד:#include <stdio.h>
#include <conio.h>

struct test{
union{
struct {
int a;
int b;
}inside;
int c[2];
};
};

void main()
{
clrscr();
test me;
me.inside.a = 15;
me.inside.b = 100;
me.c[0] = 1;
me.c[1] = 45;
printf("%d,%d",me.inside.a,me.inside.b);
getch();
}[ההודעה נערכה על-ידי ziv ב-30/08/2006 21:39:42]
30/08/2006 21:41:39 HLL
אז זהו שבסי זה יעבוד
ב# לא, כי אתה לא יכול להגדיר מערך (או בעצם שאני לא יודע איך), אלא רק רפרנסים (=מצביע) למערכים
30/08/2006 21:44:22 ziv
לסוגים הבסיסיים אתה כן יכול לעשות מצביעים(אני לא מתכנת של C# אבל זה מה שאני זוכר) ודרך unsafe צודק או לא?[ההודעה נערכה על-ידי ziv ב-30/08/2006 21:46:15]
30/08/2006 21:57:48 HLL
כן נכון אבל זה לא קשור למה שאמרתי
אמרתי שאתה לא יכול להגדיר
קוד:
//ERROR:
int a[5];
//OK:
int[] a=new int[5];
מה שהופך את a בעצם למצביע (בדיוק כמו בשימוש ב malloc)
כל עוד מצביע לבלוק הנתונים, ולא בלוק הנתונים עצמו, ממוקם כחלק מהאיבר השני ב union, הדבר בלתי אפשרי מכיוון שהחפיפה תתבצע בין המבנה לבין המצביע, ולא עם תוכן מערך הbyte.
30/08/2006 22:00:01 ziv
מה זה?!?!?!?!?!?!?!?!?!?!!
אי אפשר לעשות מערך סטטי?!
30/08/2006 22:07:47 HLL
יכול להיות שאפשר ופשוט אני לא יודע איך,
שוב גם אם היה אפשר, זה פתרון חמוד אבל לא ב 100% מה אני מחפש...[ההודעה נערכה על-ידי HLL ב-30/08/2006 22:08:17]
30/08/2006 22:09:00 ziv
הייתי מנסה את זה וגם מנסה פתרונות אחרים רק לצערי המחשב שלי מפגר וכרגע שום דבר כמעט לא עובד עליו...
01/09/2006 14:37:38 tal
כמו שדיברנו כבר ב- IRC, הנה דוגמא ל- Serialize שרושם ל- File Stream (למרות שיכולת גם לרשום ל- Network Stream)..

קוד:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace SerializationExample
{
class Program
{
static void Main(string[] args)
{
byte[] arr = new byte[50];
byte[] newArr = new byte[50];
for (int i = 0; i < arr.Length; i++)
{
arr = Convert.ToByte(i);
}
Console.WriteLine("Ok, Lets start writing to the file...");
BinaryFormatter oFormatter = new BinaryFormatter();
FileStream oStream = new FileStream("C:\\serializeExample.txt", FileMode.Create, FileAccess.Write, FileShare.None);
oFormatter.Serialize(oStream, arr);
oStream.Close();
Console.WriteLine("Lets start reading from the file...");
oStream = File.Open("C:\\serializeExample.txt", FileMode.Open);
newArr = (byte[])oFormatter.Deserialize(oStream);
for (int i = 0; i < newArr.Length; i++)
{
Console.WriteLine(i);
}

Console.WriteLine("Cya!");
Console.ReadLine();
}
}
}



ככה שבעצם תוכל לשמור את המערך לקובץ... למרות שעכשיו שאני חושב על זה כנראה שזאת לא הייתה הכוונה שלך..
מה שביינתים נראה כאילו הכיוון של ה- unmanaged יותר מתאים למטרה שלך..
אם תוכל לתת כיוון יותר מדוייק מה אתה מנסה לעשות יהיה יותר קל להסביר לך..

נ.ב
אם משהו לא ברור בקוד תשאל ואני אסביר...[ההודעה נערכה על-ידי tal ב-01/09/2006 14:40:00]
01/09/2006 15:01:56 ziv
לפעמים managed מסבך כל כך הרבה...
tal מה המטרה של serialize? האם אפשר לעשות את זה גם למבנים(structs)?
01/09/2006 16:16:36 tal
serialize נותן לך את האפשרות לשמור אובייקט כמו שהוא בצורה בינארית\XML(הן הנפוצות ביותר אך ישנם עוד פורמטים להעברה) ל- STREAM מסויים.. אם זה לקובץ או ל- tcp/ip stream.. או לכל סוג STREAM אחר..
דוגמא לשימוש בserialize זה כשאתה לדוגמא רוצה לשלוח ArrayList לאפליקציה אחרת שאתה מתקשר איתה ובמקום להעביר לו את הערכים אחד אחד מתוך ה- ARRAYLIST בצורה "מסובכת" יחסית אתה פשוט תוכל להעביר את כל האובייקט כמו שהוא כך שההעברה של האובייקט תהיה קלה לשתי הצדדים את האובייקט... כנ"ל לגבי כל אובייקט.. העיקר שהוא יוגדר כ- Serializable והאובייקטים שהוא משתמש בהם גם Serializables...

עוד דוגמא טובה ל- Serialize זה שאם לדוגמא יש לך קלאס שבו שאתה שם את כל ההגדרות שלך ואתה רוצה לשמור אותו לקובץ, במקום לשמור אותו כטקסט ואחרכך לעשות עבודה מסובכת של פירוק המידע תוכל פשוט לשמור את כל הקלאס לקובץ או ל- STREAM אחר וככה לטעון אותו מחדש בעת הפעלת האפליקציה בצורה מאוד מאוד פשוטה כמו שהראתי בדוגמא למעלה...


לגבי מערכים, ניתן לעשות Serialize גם ל- structs... הנה struct שהגדרתי ועשיתי לו Serialize ו- Deserialize וזה עבד מצויין.
קוד:
[Serializable]
struct Test
{
public int a;
public int b;
public string c;
}
[ההודעה נערכה על-ידי tal ב-01/09/2006 16:22:07]
01/09/2006 16:47:47 ziv
ואפשר במקום ל stream להעביר למערך bytes?
כלומר להמיר את כל ה struct לצורה פשוטה של בתים.[ההודעה נערכה על-ידי ziv ב-01/09/2006 16:49:39]
01/09/2006 19:12:41 sweet child
הבעייה עם כל זה הסיריאליזישן זה שהמנגנון מוסיף עוד המון נתונים נוספים מעבר למידע, הוא מעביר את שם המחלקה אם אני לא טועה ועוד מלא דברים.
אתה לא יכול לדעת במדוייק איך הוא שומר את זה , המטרה אח"כ היא להקלט ע"י אפליקציית ,net ולא ע"י נאמר לדוגמא רכיב אלקטרוני שיודע לקבל TCPIP זו הבעייה ...


(HLL)[ההודעה נערכה על-ידי sweet child ב-01/09/2006 19:13:04]
02/09/2006 18:24:02 tal
ב- BinaryFormatter הוא שומר רק את המידע ששמת בלי שום מידע מסביב.. נטו מה ששמת.

עכשיו תראה לי מה הקוד שכתבת ב- #C בשביל לעשות את זה ב- unmanaged code ואני אנסה להבין מה הבעייה שנתקלת בה..
עמודים: 1