Both StreamReader and BinaryReader can be used to get data from binary file ( for example )
BinaryReader :
using (FileStream fs = File.Open(#"c:\1.bin",FileMode.Open))
{
byte[] data = new BinaryReader(fs).ReadBytes((int)fs.Length);
Encoding.getstring....
}
StreamReader :
using (FileStream fs = File.Open(#"c:\1.bin",FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs,Encoding.UTF8))
{
var myString=sr.ReadToEnd();
}
}
What is the difference and when should I use which ?
Both StreamReader and BinaryReader can be used to get data from binary file
Well, StreamReader can be used to get text data from a binary representation of text.
BinaryReader can be used to get arbitrary binary data. If some of that binary data happens to be a representation of text, that's fine - but it doesn't have to be.
Bottom line:
If the entirety of your data is a straightforward binary encoding of text data, use StreamReader.
If you've fundamentally got binary data which may happen to have some portions in text, use BinaryReader
So for example, you wouldn't try to read a JPEG file with StreamReader.
Related
I am reading a file using StreamReader fileReader = File.OpenText(filePath). I would like to modify one line in the file in memory and push the modified stream to another method.
What I would like to avoid is reading the whole file into a string and modifying the string (doesn't scale). I would also like to avoid modifying the actual file.
Is there a straightforward way of doing this?
There is no built-in way to do that in .Net framework.
Stream and StreamReader/StreamWriter classes are designed to be chained if necessary (like GZipStream wraps stream to compress it). So you can create wrapper StreamReader and update data as you need for every operation after calling wrapped reader.
You can open two stream -one for read, one for write- at the same time. I tested simple code that works, but not sure that's what you want:
// "2.bar\r\n" will be replaced by "!!!!!\r\n"
File.WriteAllText("test.txt",
#"1.foo
2.bar
3.fake");
// open inputStream for StreamReader, and open outputStream for StreamWriter
using (var inputStream = File.Open("test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(inputStream))
using (var outputStream = File.Open("test.txt", FileMode.Open, FileAccess.Write, FileShare.Read))
using (var writer = new StreamWriter(outputStream))
{
var position = 0L; // track the reading position
var newLineLength = Environment.NewLine.Length;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
// your particular conditions here.
if (line.StartsWith("2."))
{
// seek line start position
outputStream.Seek(position, SeekOrigin.Begin);
// replace by something,
// but the length should be equal to original in this case.
writer.WriteLine(new String('!', line.Length));
}
position += line.Length + newLineLength;
}
}
/* as a result, test.txt will be:
1.foo
!!!!!
3.fake
*/
As you can see, both streams can be accessed by StreamReader and StreamWriter at the same time. And you can also manipulate both read/write position as well.
I'm not entirely new to programming but I still see myself as a novice. I'm currently creating an Invoicing system with a max of 5 line items, this being said, I'm creating a String<> item, serializing it to store and then de-serializing it to display.
So far I've managed the serializing, and de-serializing, and from the de-serialized value I've managed to display the relevant information in the correct fields.
My question comes to: HOW do I add the list of items in the String<> object to either a Binary or XML field in my SQL table?
I know it should be similar to adding an Image object to binary but there's a catch there. usually:
byte[] convertToByte(string sourcePath)
{
//get the byte file size of image
FileInfo fInfo = new FileInfo(sourcePath);
long byteSize = fInfo.Length;
//read the file using file stream
FileStream fStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);
//read again as byte using binary reader
BinaryReader binRead = new BinaryReader(fStream);
//convert image to byte (already)
byte[] data = binRead.ReadBytes((int)byteSize);
return data;
}
this kind of thing is done for an image however the whole "long" thing does not apply to the List<> object.
Any assistance would be helpful
If you simply want to store your data as "readable" text, you can use the varchar(MAX) or nvarchar(MAX) (depending on whether you need extended character support). That translates directly into a string in ADO.NET or EntityFramework.
If all you need are bytes from a string, the Encoding class will do that:
System.Text.Encoding.Default.GetBytes(yourstring);
See: http://msdn.microsoft.com/en-us/library/ds4kkd55%28v=vs.110%29.aspx
A way of saving a binary file in a string is to convert the image to a Base64 string. This can be done with the Convert.ToBase64String (Byte[]) method:
Convert.ToBase64String msdn
string convertImageToBase64(string sourcePath)
{
//get the byte file size of image
FileInfo fInfo = new FileInfo(sourcePath);
long byteSize = fInfo.Length;
//read the file using file stream
FileStream fStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);
//read again as byte using binary reader
BinaryReader binRead = new BinaryReader(fStream);
//convert image to byte (already)
byte[] data = binRead.ReadBytes((int)byteSize);
return Convert.ToBase64String (data);
}
Now you will be able to save the Base64 string in a string field in your database.
I have a file with size 10124, I am adding a byte array, which has length 4 in the beginning of the file.
After that the file size should become 10128, but as I write it to file, the size decreased to 22 bytes. I don't know where is the problem
public void AppendAllBytes(string path, byte[] bytes)
{
var encryptedFile = new FileStream(path, FileMode.Open, FileAccess.Read);
////argument-checking here.
Stream header = new MemoryStream(bytes);
var result = new MemoryStream();
header.CopyTo(result);
encryptedFile.CopyTo(result);
using (var writer = new StreamWriter(#"C:\\Users\\life.monkey\\Desktop\\B\\New folder (2)\\aaaaaaaaaaaaaaaaaaaaaaaaaaa.docx.aef"))
{
writer.Write(result);
}
}
How can I write bytes to the file?
The issue seems to be caused by:
using a StreamWriter to write binary formatted data. The name does not inthuitively suggest this, but the StreamWriter class is suited for writing textual data.
passing an entire stream instead of the actual binary data. To obtain the bytes stored in a MemoryStream, use its convenient ToArray() method.
I suggest you the following code:
public void AppendAllBytes(string path, byte[] bytes)
{
var fileName = #"C:\\Users\\life.monkey\\Desktop\\B\\New folder (2)\\aaaaaaaaaaaaaaaaaaaaaaaaaaa.docx.aef";
using (var encryptedFile = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var writer = new BinaryWriter(File.Open(fileName, FileMode.Append)))
using (var result = new MemoryStream())
{
encryptedFile.CopyTo(result);
result.Flush(); // ensure header is entirely written.
// write header directly, no need to put it in a memory stream
writer.Write(bytes);
writer.Flush(); // ensure the header is written to the result stream.
writer.Write(result.ToArray());
writer.Flush(); // ensure the encryptdFile is written to the result stream.
}
}
The code above uses the BinaryWriter class which is better suited for binary data. It has a Write(byte[] bytes) method overload that is used above to write an entire array to the file. The code uses regular calls to the Flush() method that some may consider not needed, but these guarantee in general, that all the data written prior the call of the Flush() method is persisted within the stream.
Just started with writing unit tests and I am now, blocked with this situation:
I have a method which has a FileStream object and I am trying to pass a "string" to it.
So, I would like to convert my string to FileStream and I am doing this:
File.WriteAllText(string.Concat(Environment.ExpandEnvironmentVariables("%temp%"),
#"/test.txt"), testFileContent); //writes my string to a temp file!
new FileStream(string.Concat(Environment.ExpandEnvironmentVariables("%temp%"),
#"/test.txt"), FileMode.Open) //open that temp file and uses it as a fileStream!
close the file then!
But, I guess there must be some very simple alternative to convert a string to a fileStream.
Suggestions are welcome! [Note there are other answers to this question in stackoverflow but none seems to be a straight forward solution to that]
Thanks in advance!
First of all change your method to allow Stream instead of FileStream. FileStream is an implementation which, as I remember, does not add any methods or properties, just implement abstract class Stream. And then using below code you can convert string to Stream:
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
As FileStream class provides a stream for a file and hence it's constructor requires the path of the file,mode, permission parameter etc. to read the file into stream and hence it is used to read the text from file into stream. If we need to convert string to stream first we need to convert string to bytes array as stream is a sequence of bytes. Below is the code.
//Stream is a base class it holds the reference of MemoryStream
Stream stream = new MemoryStream();
String strText = "This is a String that needs to beconvert in stream";
byte[] byteArray = Encoding.UTF8.GetBytes(strText);
stream.Write(byteArray, 0, byteArray.Length);
//set the position at the beginning.
stream.Position = 0;
using (StreamReader sr = new StreamReader(stream))
{
string strData;
while ((strData= sr.ReadLine()) != null)
{
Console.WriteLine(strData);
}
}
I want to read an exe file in my C# code then decode as base64.
I am doing it like this
FileStream fr = new FileStream(#"c:\1.exe", FileMode.Open, FileAccess.Read, FileShare.Read);
StreamReader sr = new StreamReader(fr);
fr.Read(data, 0, count);
But the problem is that when I write this file the written file gets corrupted.
When analyzing in hex workshop code value 20 in hex is being replaced by 0.
A StreamReader should be used only with text files. With binary files you need to use directly a FileStream or:
byte[] buffer = File.ReadAllBytes(#"c:\1.exe");
string base64Encoded = Convert.ToBase64String(buffer);
// TODO: do something with the bas64 encoded string
buffer = Convert.FromBase64String(base64Encoded);
File.WriteAllBytes(#"c:\2.exe", buffer);
StreamReader official docs:
"Implements a TextReader that reads characters from a byte stream in a particular encoding."
It's for text, not binary files. Try just Stream or BinaryReader.. (Why did you try a StreamReader?)