
Сообщение от
SSTREGG
Лучше создай "неуправляемую" структуру и работай с ней - имхо, удобней.
Честно говоря не совсем понял, что за неуправляемая структура. Пока сделал сохранения списка объектов. Но честно говоря пока слабо представляю, на какие проблемы наткнусь при поиске изображения нужного объекта в файле (в один файл пишется весь список).
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
| public static void Save(List<SomeObject> listSC, String fileName)
{
const int imgLengthOffeset = 8;
const int saveSizeOffset = 8;
using (FileStream fs = File.Create(fileName))
{
using (BinaryWriter binWriter = new BinaryWriter(fs))
{
binWriter.Write(listSC.Count); //Int32
foreach (SomeObject sc in listSC)
{
//Начальная позиция в новой итерации цикла
long newIterationPos = binWriter.BaseStream.Position;
//Перепрыгиваем, чтобы потом сюда записать длинну всего сэйва в байтах
binWriter.BaseStream.Seek(saveSizeOffset, SeekOrigin.Current);
//перепрыгиваем 8 байт, чтобы в дальнейшем сюда записать кол-во байт до изображения
binWriter.BaseStream.Seek(imgLengthOffeset, SeekOrigin.Current);
binWriter.Write(sc.Address); //String
binWriter.Write(sc.Comment); //String
binWriter.Write(sc.EMail); //String
binWriter.Write(sc.HomePhone); //String
binWriter.Write(sc.MobilePhone); //String
binWriter.Write(sc.Name); //String
//...
//ещё данные записываются...
//...
long lastPosition = binWriter.BaseStream.Position;
//перемещаемся в начало этой итерации
binWriter.BaseStream.Seek(-lastPosition + newIterationPos + saveSizeOffset, SeekOrigin.Current);
binWriter.Write(lastPosition); //записываем позицию начала изображения
long curPos = binWriter.BaseStream.Position;
binWriter.BaseStream.Seek(lastPosition - curPos, SeekOrigin.Current);
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(sc.MiniImageFoto));
encoder.Interlace = PngInterlaceOption.On;
encoder.Save(ms);
byte[] imgArray = ms.ToArray();
binWriter.Write(imgArray.Length); //int (длина изображения в байтах)
binWriter.Write(imgArray);
}
long lastPosition2 = binWriter.BaseStream.Position; //получаем текущую позицию
binWriter.BaseStream.Seek(-lastPosition2 + newIterationPos, SeekOrigin.Current);
binWriter.Write(lastPosition2); //Записываем кол-во байт на которых кончается этот сэйв
long curPos2 = binWriter.BaseStream.Position;
binWriter.BaseStream.Seek(lastPosition2 - curPos2, SeekOrigin.Current);
}
}
}
} |
|
Вот какая структура файла примерно получилась:
======================================
Кол-во сохранённых объектов (Int32, 4 байта);
Длинна текущего сэйва, чтобы его полностью можно было перепрыгнуть и начать читать следующий (Int64, 8 байт);
Позиция в текущей итерации с которой начинается изображение (Int64, 8 байт);
...
Строковые переменные...
...
Длинна изображения в байтах (Int32, 4 байта);
Изображение
======================================
Добавлено через 5 часов 24 минуты
Появился вопрос всё по этой теме. Мне
хотелось бы узнать стоит ли так делать:
Есть ListView в нём список объектов. При каждом редактировании, удалении, добавлении в ListView объектов происходит перезапись файла в который сохранён этот список. То есть не отдельный объект дописывается в файл, а файл полностью переписывается. При перезаписи может произойти ошибка (я правда вроде уже всё предусмотрел, но на всякий случай решил сделать резервирование).
Перед записью копируется файл в который мы ранее сохраняли данные. То есть создаётся рядом с ним его копия с другим именем. Происходит запись и если при записи происходит ошибка, а следовательно потеря того файла, то недозаписанный файл удаляется, а из резерва восстанавливается тот зарезервированный файл. Вот код:
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
84
85
86
87
88
89
90
91
92
93
94
| public static void Save(List<SomeObject> listSC, String fileName)
{
const int imgLengthOffeset = 8;
const int saveSizeOffset = 8;
String reserveName = "reserveSC.dat";
String fullReserveFileName = null;
if (File.Exists(fileName))
{
fullReserveFileName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fileName), reserveName);
if (File.Exists(fullReserveFileName))
File.Delete(fullReserveFileName);
File.Move(fileName, fullReserveFileName);
}
using (FileStream fs = File.Create(fileName))
{
using (BinaryWriter binWriter = new BinaryWriter(fs))
{
try
{
binWriter.Write(listSC.Count); //Int32
foreach (SomeObject sc in listSC)
{
//Начальная позиция в новой итерации цикла
long newIterationPos = binWriter.BaseStream.Position;
//Перепрыгиваем, чтобы потом сюда записать длинну всего сэйва в байтах
binWriter.BaseStream.Seek(saveSizeOffset, SeekOrigin.Current);
//перепрыгиваем 8 байт, чтобы в дальнейшем сюда записать кол-во байт до изображения
binWriter.BaseStream.Seek(imgLengthOffeset, SeekOrigin.Current);
binWriter.BaseStream.Seek(imgLengthOffeset, SeekOrigin.Current);
binWriter.Write(sc.Address); //String
binWriter.Write(sc.Comment); //String
binWriter.Write(sc.EMail); //String
binWriter.Write(sc.HomePhone); //String
binWriter.Write(sc.MobilePhone); //String
binWriter.Write(sc.Name); //String
//...
//ещё данные записываются...
//...
long lastPosition = binWriter.BaseStream.Position;
//перемещаемся в начало этой итерации
binWriter.BaseStream.Seek(-lastPosition + newIterationPos + saveSizeOffset, SeekOrigin.Current);
binWriter.Write(lastPosition); //записываем позицию начала изображения
long curPos = binWriter.BaseStream.Position;
binWriter.BaseStream.Seek(lastPosition - curPos, SeekOrigin.Current);
if (sc.MiniImageFoto != null)
{
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bd.MiniImageFoto));
encoder.Interlace = PngInterlaceOption.On;
encoder.Save(ms);
byte[] imgArray = ms.ToArray();
binWriter.Write(imgArray.Length); //int (длина изображения в байтах)
binWriter.Write(imgArray);
}
}
else
binWriter.Write(0); //int (длина изображения в байтах)
long lastPosition2 = binWriter.BaseStream.Position; //получаем текущую позицию
binWriter.BaseStream.Seek(-lastPosition2 + newIterationPos, SeekOrigin.Current);
binWriter.Write(lastPosition2); //Записываем кол-во байт на которых кончается этот сэйв
long curPos2 = binWriter.BaseStream.Position;
binWriter.BaseStream.Seek(lastPosition2 - curPos2, SeekOrigin.Current);
}
}
catch (Exception exc)
{
if (File.Exists(fullReserveFileName)) //если зарезервированный файл есть, то...
{
fs.Close();
if (File.Exists(fileName))
File.Delete(fileName);
File.Move(fullReserveFileName, fileName); //восстанавливаем из резервного файла
MessageBox.Show(String.Format("{0}\n{1}", exc.Message, "Ошибка записи в файл. Резервные данные восcтановлены."));
}
else
MessageBox.Show(exc.Message);
}
}
}
if (File.Exists(fullReserveFileName))
File.Delete(fullReserveFileName);
} |
|