How to read byte array into FileStream - c#

I have an byte array and I want to read the byte array into a FileStream. Below is my sample of code:
string fileName = "test.txt";
byte[] file = File.ReadAllBytes(Server.MapPath("~/Files/" + fileName));
FileStream fs = new FileStream();
fs.ReadByte(file);
object obj = LoadFile<object>(fs);
public static T LoadFile<T>(FileStream fs)
{
using (GZipStream gzip = new GZipStream(fs, CompressionMode.Decompress))
{
BinaryFormatter bf = new BinaryFormatter();
return (T)bf.Deserialize(gzip);
}
}
In the method above, I have use FileStream to read byte array, but unlucky fs.ReadByte cannot read byte array. Any help please focus on how to Read byte array into a FileStream for using as a parameter in method "LoadFile". Please do not read directly the file into FileStream because the file here is loaded from somewhere else like from database or other source.

string fileName = "test.txt";
byte[] file = File.ReadAllBytes(Server.MapPath("~/Files/" + fileName));
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(file, 0, file.Length);
memStream.Seek(0, SeekOrigin.Begin);
Object obj = (Object)binForm.Deserialize(memStream);

I'm not sure where the misunderstanding is. FileStream represents a file on disk. You cannot "read bytes into it" without writing them to disk and you cannot read from it without reading from disk.
Maybe what you want is a MemoryStream which can contain arbitrary contents.
Both derive from Stream.

Yeah! Now I got a good solution after doing some more research. As the topic I have posted "How to read byte array into FileStream". We cannot read byte array into FileStream, it just use to read a file on driver to byte array. So I have change a little bit on my code, and now I have a file to read it using FileStream. How I made a file?
In this context I have an object. The object is anything as you want!
I use a collection as a samble object.
Collection<object> list = new Collection<object>();
//Now I will write this list to a file. fileName is what you want and be sure that folder Files is exist on server or at the root folder of your project
WriteFile(list, Server.MapPath("~/Files/" + fileName));
//The method to write object to file is here
public static void WriteFile<T>(T obj, string path)
{
FileStream serializeStream = new FileStream(path, FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(serializeStream, obj);
serializeStream.Flush();
serializeStream.Close();
}
After I have wrote my object to a file, I need a method to read it back to object. So I do write this method:
public static Collection<object> ReatFile(string fileName){
//I have to read the file which I have wrote to an byte array
byte[] file;
using (var stream = new FileStream(Server.MapPath("~/Files/" + fileName), FileMode.Open, FileAccess.Read))
{
using (var reader = new BinaryReader(stream))
{
file = reader.ReadBytes((int)stream.Length);
}
}
//And now is what I have to do with the byte array of file is to convert it back to object which I have wrote it into a file
//I am using MemoryStream to convert byte array back to the original object.
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(file, 0, file.Length);
memStream.Seek(0, SeekOrigin.Begin);
Object obj = (Object)binForm.Deserialize(memStream);
Collection<object> list = (Collection<object>)obj;
return list;
}
After doing some steps above, I am now can write any type object to file and then read it back to original object. Thank too much for any help I have got there.

Why do you run File.ReadAllBytes prior to the usage of your FileStream?
string fileName = "test.txt";
using(FileStream fs = new FileStream(Server.MapPath("~/Files/" + fileName), FileMode.Open, FileAccess.Read))
{
object obj = LoadFile<object>(fs);
fs.Close();
}

Related

Read and write of binary file in c#

I have read a binary file in using C# as per the following code. Then I tried to write this binary data in another binary file. But I found that when I opened these 2 files in Winmerge, there is a difference in both binary files. i.e read file and written file.
Could you please suggest why there is a difference if I just read files and rewrite?
string fileNameWithPath_ = "1.pwpmi";
string newfileNameWithPath_ = "2.pwpmi";
System.IO.FileStream fileStream = new System.IO.FileStream(fileNameWithPath_, System.IO.FileMode.Open,
System.IO.FileAccess.Read);
System.IO.BinaryReader binReader = new System.IO.BinaryReader(fileStream, Encoding.ASCII);
char[] chararr = new char[fileStream.Length];
chararr = binReader.ReadChars((int)fileStream.Length);
byte[] buffer = binReader.ReadBytes((int)fileStream.Length);
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes,0, (int)fileStream.Length);
byte[] fileBytes = System.IO.File.ReadAllBytes(fileNameWithPath_);
string stringbyte1 = Encoding.ASCII.GetString(fileBytes);
binReader.Close();
fileStream.Close();
System.IO.BinaryWriter binWriter =
new System.IO.BinaryWriter(System.IO.File.Open(newfileNameWithPath_, System.IO.FileMode.Create));
binWriter.Flush();
binWriter.Write(stringbyte1);
binWriter.Close();
It appears you have tried a few different methods and have actually come quite close to the working one. The issue is likely in the way your read your binary data as one data type and write it back into output as another. Try sticking to bytes:
string fileNameWithPath_ = "1.pwpmi";
string newfileNameWithPath_ = "2.pwpmi";
System.IO.FileStream fileStream = new System.IO.FileStream(fileNameWithPath_, System.IO.FileMode.Open,
System.IO.FileAccess.Read);
System.IO.BinaryReader binReader = new System.IO.BinaryReader(fileStream, Encoding.ASCII);
byte[] fileBytes = binReader.ReadBytes((int)fileStream.Length);
//byte[] fileBytes = System.IO.File.ReadAllBytes(fileNameWithPath_); // this also works
binReader.Close();
fileStream.Close();
System.IO.BinaryWriter binWriter =
new System.IO.BinaryWriter(System.IO.File.Open(newfileNameWithPath_, System.IO.FileMode.Create));
binWriter.Flush();
binWriter.Write(fileBytes); // just feed it the contents verbatim
binWriter.Close();
the above code does not make any changes to the incoming byte stream and produces identical files when I run it through WinMerge
As comments suggest, you might be better off just copying the file altogether:
string fileNameWithPath_ = "1.pwpmi";
string newfileNameWithPath_ = "2.pwpmi";
File.Copy(fileNameWithPath_, newfileNameWithPath_, overwrite: true);
The .NET framework provides a built-in method to copy a file:
File.Copy(fileNameWithPath_, newfileNameWithPath_)
(Here, File is System.IO.File.)
Or alternatively:
using (FileStream inStream = new FileStream(fileNameWithPath_, FileMode.Open, FileAccess.Read))
using (FileStream outStream = new FileStream(newfileNameWithPath_, FileMode.Create, FileAccess.Write))
{
inStream.CopyTo(outStream);
}

Using MemoryStream and DotNetZip to zip a json file

I have a JSON file created, and I am going to zip it using DotNetZip.
Using with StreamWriter to zip it is working, if I try to use MemoryStream it will not working.
StreamWriter :
sw = new StreamWriter(assetsFolder + #"manifest.json");
sw.Write(strManifest);
sw.Close();
zip.AddFile(Path.Combine(assetsFolder, "manifest.json"), "/");
zip.AddFile(Path.Combine(assetsFolder, "XXXXXXX"), "/");
zip.Save(outputStream);
MemoryStream :
var manifestStream = GenerateStreamFromString(strManifest);
public static Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
zip.AddEntry("manifest.json", manifestStream);
zip.AddFile(Path.Combine(assetsFolder, "XXXXXXX"), "/");
zip.Save(outputStream);
I must using the .JSON file type to zip it, Can any one told me where have a mistake?
To create a Gzipped Json you need to use GZipStream. Try method below.
https://www.dotnetperls.com/gzipstream
GZipStream compresses data. It saves data efficiently—such as in
compressed log files. We develop a utility method in the C# language
that uses the System.IO.Compression namespace. It creates GZIP files.
It writes them to the disk.
public static void CompressStringToFile(string fileName, string value)
{
// A.
// Write string to temporary file.
string temp = Path.GetTempFileName();
File.WriteAllText(temp, value);
// B.
// Read file into byte array buffer.
byte[] b;
using (FileStream f = new FileStream(temp, FileMode.Open))
{
b = new byte[f.Length];
f.Read(b, 0, (int)f.Length);
}
// C.
// Use GZipStream to write compressed bytes to target file.
using (FileStream f2 = new FileStream(fileName, FileMode.Create))
using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
{
gz.Write(b, 0, b.Length);
}
}

Writing a memory stream to a file

I have tried retrieving data in the json format as a string and writing it to a file and it worked great. Now I am trying to use MemoryStream to do the same thing but nothing gets written to a file - merely [{},{},{},{},{}] without any actual data.
My question is - how can I check if data indeed goes to memory stream correctly or if the problem occurs somewhere else. I do know that myList does contain data.
Here is my code:
MemoryStream ms = new MemoryStream();
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(List<myClass>));
dcjs.WriteObject(ms, myList);
using (FileStream fs = new FileStream(Path.Combine(Application.StartupPath,"MyFile.json"), FileMode.OpenOrCreate))
{
ms.Position = 0;
ms.Read(ms.ToArray(), 0, (int)ms.Length);
fs.Write(ms.ToArray(), 0, ms.ToArray().Length);
ms.Close();
fs.Flush();
fs.Close();
}
There is a very handy method, Stream.CopyTo(Stream).
using (MemoryStream ms = new MemoryStream())
{
StreamWriter writer = new StreamWriter(ms);
writer.WriteLine("asdasdasasdfasdasd");
writer.Flush();
//You have to rewind the MemoryStream before copying
ms.Seek(0, SeekOrigin.Begin);
using (FileStream fs = new FileStream("output.txt", FileMode.OpenOrCreate))
{
ms.CopyTo(fs);
fs.Flush();
}
}
Also, you don't have to close fs since it's in a using statement and will be disposed at the end.
using (var memoryStream = new MemoryStream())
{
...
var fileName = $"FileName.xlsx";
string tempFilePath = Path.Combine(Path.GetTempPath() + fileName );
using (var fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
{
memoryStream.WriteTo(fs);
}
}
//reset the position of the stream
ms.Position = 0;
//Then copy to filestream
ms.CopyTo(fileStream);
The issue is nothing to do with your file stream/ memory stream. The problem is that DataContractJsonSerializer is an OPT IN Serializer. You need to add [DataMemberAttribute] to all the properties that you need to serialize on myClass.
[DataContract]
public class myClass
{
[DataMember]
public string Foo { get; set; }
}
This line looks problematic:
ms.Read(ms.ToArray(), 0, (int)ms.Length);
You shouldn't need to read anything into the memory stream at this point, particularly when you're code is written to read ms into ms.
I'm pretty confident that simply removing this line will fix your problem.

Unable to cast object of type 'System.Web.HttpInputStream' to type 'System.IO.FileStream' MVC 3

I have met an issue regarding the casting type from HttpInputStream to FileStream.
How I did ?
I have a HttpPostedFileBase object and I want to have FileStream.
I wrote:
public void Test(HttpPostedFileBase postedFile) {
FileStream fileStream = (FileStream)(postedFile.InputStream); // throw exception
FileStream anotherFileStream = postedFile.InputStream as FileStream; // null
}
I tried also
public void Test(HttpPostedFileBase postedFile) {
Stream stream = postedFile.InputStream as Stream;
FileStream myFile = (FileStream)stream;
}
But no success.
Why at postedFile.InputStream comes HttpInputStream type ?
And how could I solve this issue ?
Thanks
public byte[] LoadUploadedFile(HttpPostedFileBase uploadedFile)
{
var buf = new byte[uploadedFile.InputStream.Length];
uploadedFile.InputStream.Read(buf, 0, (int)uploadedFile.InputStream.Length);
return buf;
}
The stream that you get from your HTTP call is read-only sequential (non-seekable) and the FileStream is read/write seekable. You will need first to read the entire stream from the HTTP call into a byte array, then create the FileStream from that array.
I used the following and it worked just fine for the same situation
MemoryStream streamIWant = new MemoryStream();
using (Stream mystream = (Stream)AmazonS3Service.GetObjectStream(AWSAlbumBucketName, ObjectId))
{
mystream.CopyTo(streamIWant);
}
return streamIWant;
The GetObjectStream returns the same type of string mentioned in the question.
You can use the .SaveAs method to save the file content. HttpInputSteam probably because it's uploaded through http [browser]
postedFile.SaveAs("Full Path to file name");
You can also use CopyTo
FileStream f = new FileStream(fullPath, FileMode.CreateNew);
postedFile.InputStream.CopyTo(f);
f.Close();
Below code worked for me..
Use a BinaryReader object to return a byte array from the stream like:
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
How to create byte array from HttpPostedFile
It will work for you.
IFormFile file;
if (file != null)
{
byte[]? image = Array.Empty<byte>();
await using var memoryStream = new MemoryStream();
await file!.CopyToAsync(memoryStream);
image = memoryStream.ToArray();
}
First convert to byte array then convert to Stream.
[HttpPost]
[Route("api/TestReader/UploadTestReaderStudentsGrade")]
public IHttpActionResult UploadTestReaderStudentsGrade()
{
HttpPostedFile httpPostedFile = HttpContext.Current.Request.Files[0];
var fileBytes = new byte[httpPostedFile.InputStream.Length];
httpPostedFile.InputStream.Read(fileBytes, 0, (int)httpPostedFile.InputStream.Length); // to byte array
Stream stream = new MemoryStream(fileBytes); // to Stream
Workbook workbook = new Workbook(stream);
return Ok();
}

What is the best practice for storing a file upload to a MemoryStream (C#)?

I need to temporary store a file upload to a MemoryStream.
What would be the best method to do this using asp.net (3.5)?
Here's what I have so far. It works (locally tested), but it does not look right to me.
protected void lnkUploadFile_Click(object sender, EventArgs e)
{
MemoryStream memStream = new MemoryStream();
BinaryWriter sWriter = new BinaryWriter(memStream);
foreach (byte b in flUpload.FileBytes)
{
sWriter.Write(b);
}
sWriter.Flush();
// writing to file to verify file stream converted correctly
FileStream fstream = new FileStream(#"C:/test/" + flUpload.FileName, FileMode.Create);
memStream.WriteTo(fstream);
fstream.Dispose();
memStream.Dispose();
}
If flUpload.FileBytes is a byte array, you can use the MemoryStream constructor that accepts the contained data as a parameter:
MemoryStream memStream = new MemoryStream(flUpload.FileBytes);
If not (if it just implements IEnumerable), you can convert it to a byte array using Linq:
MemoryStream memStream = new MemoryStream(flUpload.FileBytes.ToArray());
protected void lnkUploadFile_Click(object sender, EventArgs e)
{
using (MemoryStream memStream = new MemoryStream(flUpload.FileBytes))
{
using (FileStream fstream = new FileStream(#"C:/test/" +
flUpload.FileName, FileMode.Create))
{
memStream.WriteTo(fstream);
}
}
}
Might be easier to work with as a string... all depends on what you're going to do with it I guess.
System.IO.StreamReader reader = new System.IO.StreamReader("path");
string file = reader.ReadToEnd();
Or if you need the bytes there is actually a code snipet "filReadBin" you can use that produces this:
byte[] fileContents;
fileContents = System.IO.File.ReadAllBytes(#"C:\Test.txt");
Just three lines.
if (flUpload.FileName.Length > 0)
{
string directoryPath="C:\\SomeFolderName";
flUpload.SaveAs(directoryPath + "\\" + fileUpload.FileName);
}

Categories