我的Windows Phone应用程序保存由一些文本/数字信息(如图像捕获日期等)和一些JPEG图像组成的对象 . 例如,简单,单个文件可以由以下数据顺序组成:
from byte 0 to 3 -----> INT NUMBER
from byte 4 to 11 ----> TWO INTs DESCRIBING THE SIZE OF THE NEXT IMAGE
from byte 12 to X ----> FIRST JPEG IMAGE
from byte X+1 to X+7 -> TWO INTs DESCRIBING THE SIZE OF THE NEXT IMAGE
from byte X+8 to Y ---> SECOND JPEG IMAGE
我用这种方式实现了保存方法:
public bool SaveDataToMemory(string filename)
{
try
{
IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (!appStorage.DirectoryExists(App.USER_FOLDER))
{
appStorage.CreateDirectory(App.USER_FOLDER);
}
if (appStorage.FileExists(filename))
{
appStorage.DeleteFile(filename);
}
IsolatedStorageFileStream fs = null;
using (fs = appStorage.CreateFile(filename))
{
int thumbW = (int)this.thumbnail.PixelWidth;
int thumbH = (int)this.thumbnail.PixelHeight;
int thumbLength = thumbW * thumbH;
int imageW = (int)this.imageSize.Width;
int imageH = (int)this.imageSize.Height;
int imageLength = imageW * imageH;
byte[] byteToWrite;
int bufferCount;
byteToWrite = BitConverter.GetBytes(DATA_VERSION); // THE FIRST INT NUMBER
fs.Write(byteToWrite, 0, byteToWrite.Length);
byteToWrite = BitConverter.GetBytes(thumbW); // THE FIRST COUPLE OF INTs
fs.Write(byteToWrite, 0, byteToWrite.Length);
byteToWrite = BitConverter.GetBytes(thumbH);
fs.Write(byteToWrite, 0, byteToWrite.Length);
this.thumbnail.SaveJpeg(fs, thumbW, thumbH, 0, 75); // THE FIRST IMAGE (WriteableBitmap)
byteToWrite = BitConverter.GetBytes(imageW); // THE SECOND COUPLE OF INTs
fs.Write(byteToWrite, 0, byteToWrite.Length);
byteToWrite = BitConverter.GetBytes(imageH);
fs.Write(byteToWrite, 0, byteToWrite.Length);
this.image.SaveJpeg(fs, imageW, imageH, 0, 92); // THE SECOND IMAGE
}
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
return false;
}
}
该方法应该工作,至少没有抛出异常 . 现在的问题是当我尝试加载它们时 . 我按照之前描述的数据顺序访问流,我可以使用 WriteableBitmap.LoadJpeg
检索并查看第一个图像("thumbnail"),但是当我继续以便检索下一个整数时,它们看起来是0,而第二个图像无法加载例外 .
public bool LoadDataFromMemory(string filename)
{
try
{
IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fs = null;
if (!appStorage.FileExists(filename)) return false;
using (fs = appStorage.OpenFile(filename, FileMode.Open))
{
if (fs == null) return false;
byte[] dataVersionBuf = new byte[sizeof(Int32)]; // FIRST INTEGER
fs.Read(dataVersionBuf, 0, dataVersionBuf.Length);
int dataVersion = BitConverter.ToInt32(dataVersionBuf, 0);
System.Diagnostics.Debug.WriteLine("Data version:" + dataVersion);
byte[] thumbSizeBuf = new byte[8];
fs.Read(thumbSizeBuf, 0, thumbSizeBuf.Length); // SIZE OF THE NEXT IMAGE
int thumbW = BitConverter.ToInt32(thumbSizeBuf, 0);
int thumbH = BitConverter.ToInt32(thumbSizeBuf, 4);
this.thumbnail = new WriteableBitmap(thumbW, thumbH);
this.thumbnail.LoadJpeg(fs); // FIRST IMAGE
// (this prints the correct information)
System.Diagnostics.Debug.WriteLine("Loaded thumbnail " + this.thumbnail.PixelWidth + "x" + this.thumbnail.PixelHeight);
byte[] leftSizeBuf = new byte[sizeof(Int32) * 2];
fs.Read(leftSizeBuf, 0, leftSizeBuf.Length); // <<--- PROBLEMS READING HERE!
int imageW = BitConverter.ToInt32(leftSizeBuf, 0);
int imageH = BitConverter.ToInt32(leftSizeBuf, 4);
// imageW and imageH are equal to 0!!!!
System.Diagnostics.Debug.WriteLine("Loading left " + imageW + "x" + imageH);
WriteableBitmap wb = new WriteableBitmap(imageW, imageH);
wb.LoadJpeg(fs); // <--- EXCEPTION HERE!
return true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
return false;
}
}
抛出的异常是 System.ArgumentException: incorrect parameter
. 我是否实施了错误的方法将两个图像存储在同一个流/文件中?
2 回答
这可能是由于
WriteableBitmap.LoadJpeg
方法中的意外行为造成的 . 它可能会覆盖您的流,这可能会导致您的其余流处于不可预测的位置 . 我建议更新你的格式以添加jpeg的FileSize(以字节为单位),并从FileStream
中拉出MemoryStream
以传递给WriteableBitmap.LoadJpeg
.有些事情:(可能有编译问题,我不是在开发机器上检查)
使用与上面相同的技术来加载第二个图像 .
完成!从Xenolightning的回答开始,首先我将JPEG数据保存到单独的
MemoryStream
中,这样我就能用MemoryStream.Length
得到它的最终长度 . 我将IsolatedStorageFileStream
的长度写为一个简单的整数,然后用MemoryStream.WriteTo().
从前一个MemoryStream中写出全部内容 .当加载回来时,我首先读取文件大小数据块,然后将
fs.Read()
的适当数据量传输到MemoryStream,然后将其转换为位图对象 .