在开发silverlight 项目时,需要用到文件上传功能。我上传的文件,第一次上传后上传的文件正常,第二次就不正常。具体原因如下。
因为是上传多个文件,并且这些要上传的文件可以自动增删。所以,我就另外写了一个类 fileList,来存放上传文件的资料,如 name ,Filestream.
然后上传文件时,上传的是 List<fileList> . 我以为是 encoding 的原因。可是查了关天感觉没有问题的。
后来才发现,同一个文件选择后,第一次上传是不乱码的,而第二次再上次就有问题了。
原来是读 FileStream 的原因。
1. 文件位置。
FileStream类维护内部文件指针,该指针指向文件中进行下一次读写操作的位置。在大多数情况下,当打开文件时,它就指向文件的开始位置,但是此指针可以修改。这允许应用程序在文件的任何位置读写,随机访问文件,或直接跳到文件的特定位置上。当处理大型文件时,这非常省时,因为马上可以定位到正确的位置。
实现此功能的方法是Seek()方法,它有两个参数:第一个参数规定文件指针以字节为单位的移动距离。第二个参数规定开始计算的起始位置,用SeekOrigin枚举的一个值表示。Seek Origin枚举包含3个值:Begin、Current和End。
例如,下面的代码行将文件指针移动到文件的第8个字节,其起始位置就是文件的第1个字节
FileInfo aFileInfo = new FileInfo("Data.txt");
FileStream aFile = aFile.OpenRead();
aFile.Seek(8,SeekOrigin.Begin);
下面的代码行将指针从当前位置开始向前移动2个字节。如果在上面的代码行之后执行下面的代码,文件指针就指向文件的第10个字节:
aFile.Seek(2,SeekOrigin.Current);
注意读写文件时,文件指针也会改变。在读取了10个字节之后,文件指针就指向被读取的第10个字节之后的字节。
也可以规定负查找位置,这可以与SeekOrigin.End枚举值一起使用,查找靠近文件末端的位置。下面的代码会查找文件中倒数第5个字节:
aFile.Seek(–5, SeekOrigin.End);
以这种方式访问的文件有时称为随机访问文件,因为应用程序可以访问文件中的任何位置。大文件分批上传就要用到这个功能。
2 读取数据
FileStream类只能处理原始字节(raw byte)。处理原始字节的功能使FileStream类可以用于任何数据文件,而不仅仅是文本文件。通过读取字节数据,FileStream对象可以用于读取图像和声音的文件。这种灵活性的代价是,不能使用FileStream类将数据直接读入字符串,而使用StreamReader类却可以这样处理。但是有几种转换类可以很容易地将字节数组转换为字符数组,或者进行相反的操作。
FileStream.Read()方法是从FileStream对象所指向的文件中访问数据的主要手段。这个方法从文件中读取数据,再把数据写入一个字节数组。它有三个参数:第一个参数是传输进来的字节数组,用以接受FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置。它通常是0,表示从数组开端向文件中写入数据(并不是文件的开头)。最后一个参数指定从文件中读出多少字节。
下面的示例演示了从随机访问文件中读取数据。
FileStream aFile = new FileStream("../../Program.cs",FileMode.Open);
aFile.Seek(135,SeekOrigin.Begin);
aFile.Read(byData,0,200); //取到的数组是从第136 个字节开始后的200 个字节。
3. 写入数据
向随机访问文件中写入数据的过程与从中读取数据非常类似。首先需要创建一个字节数组;最简单的办法是首先构建要写入文件的字符数组。然后使用Encoder对象将其转换为字节数组,其用法非常类似于Decoder。最后调用Write()方法,将字节数组传送到文件中。
byte[] byData;
char[] charData;
FileStream aFile = new FileStream("Temp.txt", FileMode.Create);
charData = "My pink half of the drainpipe.".ToCharArray();
byData = new byte[charData.Length];
Encoder e = Encoding.UTF8.GetEncoder();
e.GetBytes(charData, 0, charData.Length, byData, 0, true);
// Move file pointer to beginning of file.
aFile.Seek(0, SeekOrigin.Begin);
aFile.Write(byData, 0, byData.Length); //但是从一个文件里读出的字节数组可以直接写到另一个新建的文件中。示例如下:
byte[] byData1;
FileStream aFile1 = new FileStream("../../Program.cs",FileMode.Open);
aFile1.Seek(0,SeekOrigin.Begin);
aFile1.Read(byData,0,aFile.Lenght);
FileStream aFile = new FileStream("Temp.cs", FileMode.Create);
aFile.Write(byData1,0 ,byData1.Length);
结论 :我出现乱码的原因是,第一次读取这个Filestream 后,文件指针就定位到了文件末尾,结果再重新读filesStream 就会出现乱码。
long fileSize=userFiles.FileStream.Length;
buffer = new byte[fileSize];
userFiles.FileStream.Read(buffer, 0, (int)fileSize); //这时userFiles.FileStream.Position =fileSize;
所在,在 再次read 之前要指针定位到文件开头: userFiles.FileStream.Seek(0, SeekOrigin.Begin);
正确的应为:
long fileSize=userFiles.FileStream.Length;
buffer = new byte[fileSize];
userFiles.FileStream.Seek(0, SeekOrigin.Begin);
userFiles.FileStream.Read(buffer, 0, (int)fileSize);
资料参考 : http://book.51cto.com/art/200801/65284.htm