I'm sorry for not knowing a better way to subject this issue. I can modify once I better understand what is happening. I am trying to use a StreamWriter in the following code block:
public static bool SendFileToPrinter(string szPrinterName, string fontFileNames)
{
// Open the file.
FileStream fs = new FileStream(fontFileNames, FileMode.Open, FileAccess.Write);
//Add string to the file
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine ("Test");
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte[] bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
int nLength;
nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes(nLength);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
}
When I add the stream writer I get a "Stream not readable" error and I'm not sure why. I'm new, so this is probably something elementary. I'm just trying to add a string to a file that I am sending to a printer (as raw PCL). Any help is appreciated.
You have some logical errors in your code:
You need to open your file as FileAccess.ReadWrite.
The FileMode.Open flag indicates that the operating system should open an existing file; however, you subsequently proceed to overwrite the first few bytes of its contents with your "Test" string. This is probably not desired behaviour. If you want to replace the file, use FileMode.Truncate. If you want to add your string to the end of the file, use FileMode.Append.
You need to flush the contents of your StreamWriter once you're done writing to it.
You need to reset your stream's position for your BinaryReader to read the written contents.
Don't forget to dispose your streams, readers, writers, and (preferably through using blocks).
Sample code:
// Open the file.
using (FileStream fs = new FileStream(fontFileNames, FileMode.Truncate, FileAccess.ReadWrite))
using (StreamWriter sw = new StreamWriter(fs))
{
//Add string to the file
sw.WriteLine("Test");
sw.Flush();
fs.Position = 0;
// Create a BinaryReader on the file.
using (BinaryReader br = new BinaryReader(fs))
{
/* rest of your code here */
}
}
Edit: Sample code with append:
// Open the file.
using (FileStream fs = new FileStream(fontFileNames, FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fs))
{
//Add string to the file
sw.WriteLine("Test");
}
// Create a BinaryReader on the file.
using (FileStream fs = new FileStream(fontFileNames, FileMode.Open, FileAccess.Read))
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((int)fs.Length);
/* rest of your code here */
}
The issue occurs because you open the FileStream with only write access:
FileStream fs = new FileStream(fontFileNames, FileMode.Open, FileAccess.Write);
and then try to read from it with BinaryReader:
bytes = br.ReadBytes(nLength);
Instead open the stream with read/write access:
... = new FileStream(fontFileNames, FileMode.Open, FileAccess.ReadWrite);
Related
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);
}
below code:
var fs = new FileStream(#"C:\Users\Michał\Desktop\tools\test.txt",
FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
var fs2 = new FileStream(#"C:\Users\Michał\Desktop\tools\test.txt",
FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
int a = 0;
while (a < 3)
{
byte[] info = new UTF8Encoding(true).GetBytes("DEF_");
byte[] info2 = new UTF8Encoding(true).GetBytes("abc_");
fs.Write(info, 0, info.Length);
Thread.Sleep(100);
fs2.Write(info2, 0, info2.Length);
Thread.Sleep(1000);
++a;
}
fs.Close();
fs2.Close();
Why result is that in a file there is just "abc_abc_abc" ?
FileShare.ReadWrite means for me other processes/threads can write to this file in the same time in FileStream ctor call.
You can achieve the desired behavior as follows:
using (var fs = new FileStream("test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
using (var fs2 = new FileStream("test.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
byte[] info = new UTF8Encoding(true).GetBytes("DEF_");
byte[] info2 = new UTF8Encoding(true).GetBytes("abc_");
for (int i = 0; i < 3; i++)
{
fs.Seek(0, SeekOrigin.End);
fs.Write(info, 0, info.Length);
fs.Flush();
fs2.Seek(0, SeekOrigin.End);
fs2.Write(info2, 0, info2.Length);
fs2.Flush();
}
}
Before writing, each pointer of stream must be positioned at the end. This is done using the Seek method.
After writing, you need to flush the buffer to disk. This ensures that the stream is in the correct state before starting the next write. To do this, use the Flush method.
When you create a stream in its constructor, you can specify the FileOptions.WriteThrough. According to its description, the intermediate buffer should not be used. However, it still doesn't work without the Flush method. Perhaps experts will explain the reason.
There might be something obvious I'm missing here, but I can't seem to set the encoding on my FileStream read. Here's the code:
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
using (fs)
{
byte[] buffer = new byte[chunk];
fs.Seek(chunk, SeekOrigin.Begin);
int bytesRead = fs.Read(buffer, 0, chunk);
while (bytesRead > 0)
{
ProcessChunk(buffer, bytesRead, database, id);
bytesRead = fs.Read(buffer, 0, chunk);
}
}
fs.Close();
Where ProcessChunk saves the read values to objects which are then serialized to XML, but the characters read appear wrong. The encoding needs to be 1250. I haven't seen an option to add the encoding to the FileStream. What am I missing here?
Rather than FileStream, use StreamReader. It has several constructors which allow you to specify the Encoding. For example:
StreamReader sr = new StreamReader(file, System.Text.Encoding.ASCII);
Since you require encoding 1250, this can be done with:
StreamReader sr = new StreamReader(file, System.Text.Encoding.GetEncoding(1250));
I would also suggest writing it as:
using (StreamReader sr = new StreamReader ...etc)
rather than declaring the variable outside the using; and you don't need to do the Close outside the using, since the Dispose will handle that.
You can also use both FileStream and FileReader :
using (FileStream fs = new FileStream(_fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(1252)))
{
while (!sr.EndOfStream)
ProcessLine(sr.ReadLine());
}
}
I'm trying code from http://www.paraesthesia.com/archive/2009/12/16/posting-multipartform-data-using-.net-webrequest.aspx to do a POST through httpwebrequest.
If I try this same code with a text file, it's fine. However if I do it with a zip file, then when re-download that file it's saying it's not a valid zip. I assume the zip portion is likely getting uploaded as text rather than binary. However, that page does say " It's OK to include binary content here. Don't base-64 encode it or anything, just stream it on in." But this doesn't seem to be working with the given code. I'm assuming I have to change the portion that reads the file to the stream:
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
}
fileStream.Close();
}
Maybe to use BinaryReader? I'm a bit confused on how to use that in this context though, or if it's even what I need to do. A nudge in the right direction would be awesome. Thanks!
BinaryReader should work indeed:
FileInfo fInfo = new FileInfo(file.FullName);
//
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
byte[] bdata = br.ReadBytes((int)numBytes);
br.Close();
fStream.Close();
// Write bdata to the HttpStream
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("url-here");
// Additional webRequest parameters settings.
HttpStream stream = (Stream)webRequest.GetRequestStream();
stream .Write(bdata, 0, bdata.Length);
stream.Close();
HttpWebResponse response = (HttpWebRewponse)webRequest.GetResponse();
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();
}