What is ADODB.Stream? - c#

What exactly is it, or was it, as is a interop, used for?
Here, this is the method where I use it:
public void SaveAttachmentMime(String fileName, CDO.Message message)
{
ADODB.Stream stream = message.BodyPart.GetStream();
String messageString = stream.ReadText(stream.Size);
StreamWriter outputStream = new StreamWriter(fileName);
outputStream.Write(messageString);
outputStream.Flush();
outputStream.Close();
}

The ADODB.Stream object was used to read files and other streams. What it does is part of what the StreamReader, StreamWriter, FileStream and Stream does in the .NET framework.
For what the code in that method uses it for, in .NET you would use a StreamReader to read from a Stream.
Note that the code in the method only works properly if the stream contains non-Unicode data, as it uses the size in bytes to determine how many characters to read. With a Unicode encoding some characters may be encoded as several bytes, so the stream would run into the end of the stream before it could read the number of characters specified.

It is a COM object, which is used to represent a stream of data or text. The data can be binary. If I recall correctly, it implements the IStream interface, which stores data in a structured storage object. You can find the interop representation of the interface in System.Runtime.InteropServices.ComTypes.IStream.

Related

What is the simplest way to decompress a ZIP buffer in C#?

When I use zlib in C/C++, I have a simple method uncompress which only requires two buffers and no more else. Its definition is like this:
int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen);
/*
Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry,
destLen is the total size of the destination buffer, which must be
large enough to hold the entire uncompressed data. (The size of
the uncompressed data must have been saved previously by the
compressor and transmitted to the decompressor by some mechanism
outside the scope of this compression library.) Upon exit, destLen
is the actual size of the uncompressed data.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
In the case where there is not enough room, uncompress() will fill
the output buffer with the uncompressed data up to that point.
*/
I want to know if C# has a similar way. I checked SharpZipLib FAQ as follows but did not quite understand:
How do I compress/decompress files in memory?
Use a memory stream when creating the Zip stream!
MemoryStream outputMemStream = new MemoryStream();
using (ZipOutputStream zipOutput = new ZipOutputStream(outputMemStream)) {
// Use zipOutput stream as normal
...
You can get the resulting data with memory stream methods ToArray or GetBuffer.
ToArray is the cleaner and easiest to use correctly with the penalty
of duplicating allocated memory. GetBuffer returns a raw buffer raw
and so you need to account for the true length yourself.
See the framework class library help for more information.
I can't figure out if this block of code is for compression or decompression, if outputMemStream meas a compressed stream or an uncompressed stream. I really hope there is a easy-to-understand-way like in zlib. Thanks you very much if you can help me.
Check out the ZipArchive class, which I think has the features you need to accomplish in-memory decompression of zip files.
Assuming you have an array of bytes (byte []) which represent the ZIP file in memory, you have to instantiate a ZipArchive object which will be used to read that array of bytes and interpret them as the ZIP file you whish to load. If you check the ZipArchive class' available constructors in documentation, you will see that they require a stream object from which the data will be read. So, first step would be to convert your byte [] array to a stream that can be read by the constructors, and you can do this by using a MemoryStream object.
Here's an example of how to list all entries inside of a ZIP archive represented in memory as a bytes array:
byte [] zipArchiveBytes = ...; // Read the ZIP file in memory as an array of bytes
using (var inputStream = new MemoryStream(zipArchiveBytes))
using (var zipArchive = new ZipArchive(inputStream, ZipArchiveMode.Read))
{
Console.WriteLine("Listing archive entries...");
foreach (var archiveEntry in zipArchive.Entries)
Console.WriteLine($" {archiveEntry.FullName}");
}
Each file in the ZIP archive will be represented as a ZipArchiveEntry instance. This class offers properties which allow you to retrieve information such as the original length of a file from the ZIP archive, its compressed length, its name, etc.
In order to read a specific file which is contained inside the ZIP file, you can use ZipArchiveEntry.Open(). The following exemplifies how to open a specific file from an archive, if you have its FullName inside the ZIP archive:
ZipArchiveEntry archEntry = zipArchive.GetEntry("my-folder-inside-zip/dog-picture.jpg");
byte[] readResult;
using (Stream entryReadStream = archEntry.Open())
{
using (var tempMemStream = new MemoryStream())
{
entryReadStream.CopyTo(tempMemStream);
readResult = tempMemStream.ToArray();
}
}
This example reads the given file contents, and returns them as an array of bytes (stored in the byte[] readResult variable) which you can then use according to your needs.

How can I get the number of bytes availables with Xamarin Android

I want to use this method in order to get an estimated number of bytes that can be read in a JsonFile from the Asset.
For that I wrote this code:
string filename;
Stream mf = Context.Assets.Open(filename);
The problem is that I cannot have mf as an InputStream because Context.Assets.Open(filename); gives a System.IO.Stream.
And I need to define mf as an InputStream in order to be able to have the size such as:
int size= mf.Available();
I tried also:
InputStream mf = AssetManager.Open(filename);
But I have the error of "
An object reference is required for the property , method, or the non-static field "AssetManager.Open""
How can I get over this conflict?
If you want the actual Asset file size, there are two things you need to do:
1st: Set the file NOT to be compressed
Example, change extension to something unique, i.e. .utxt
Set those file extensions not to be compressed in your app package:
2nd: Use an asset file descriptor:
var fileFD = Assets.OpenFd("json.utxt");
Log.Debug("JSON", fileFD.Length.ToString());
From the docs, you can try something like this:
string content;
AssetManager assets = this.Assets;
using (StreamReader sr = new StreamReader (assets.Open ("read_asset.txt")))
{
content = sr.ReadToEnd ();
}
where this is the context.
The .NET Stream class doesn't have a method similar to the the java available() method. In the matter of fact, the java documentation states thatL
Note that while some implementations of InputStream will return the
total number of bytes in the stream, many will not. It is never
correct to use the return value of this method to allocate a buffer
intended to hold all data in this stream.
and
The available method for class InputStream always returns 0.
This method should be overridden by subclasses.
in summary, the available method is intended to be implemented by the sub classes and it's not always guaranteed to return the available length so it's not advised to use it in allocating buffers as the docs state.
So you can check the Stream.Length property and read the whole stream or allocate a buffer with a size less than the stream's length.

String to zip file

I use a webservice that returns a zip file, as a string, and not bytes as I expected. I tried to write it to the disk, but when I open it, it tells me that it is corrupt. What am I doing wrong?
string cCsv = oResponse.fileCSV;//this is the result from webservice
MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(cCsv));
using (FileStream file = new FileStream("test.zip", FileMode.Create, FileAccess.Write))
{
ms.WriteTo(file);
}
ms.Close();
I'm not sure what kind of encoding the string is in, but assuming UTF-8, the following should work. UTF-16 would be another guess.
string cCsv = oResponse.fileCSV;
using (BinaryWriter bw = new BinaryWriter(File.Create("test.zip")))
{
bw.Write(System.Text.Encoding.UTF8.GetBytes(cCsv));
}
It'd be informative to look at the characters and the raw string itself being returned.
Edit
Per Frank's answer, the correct encoding is base64, which of course makes sense because it's binary data stored as a string.
Also, per Frank's answer, if the only action is to directly write a single byte array, then File.WriteAllBytes is more compact.
Ok, i solve the problem:
File.WriteAllBytes("testbase64.zip", Convert.FromBase64String(cCsv));

converting MemoryStream array to fileStream C#

I have a function that is returning MemoryStream array, i want to convert this memory stream array to a FileStream object.
Is it possible if yes can you please provide a way to do that...
Thanks
A.S
You cannot "convert" the stream, because a MemoryStream and a FileStream are very different things. However, you can write the entire contents of the MemoryStream to a file. There is a CopyTo method that you can use for that:
// memStream is the MemoryStream
using (var output = File.Create(filename)) {
memStream.CopyTo(output);
}
A file stream object represents an open file (from disk) as a stream. A memory stream represents an area of memory (byte array) as a stream. So you can't really convert a memory stream into a file stream directly - at least not trivially.
There are two approaches you could take:
OFFLINE: fully consume the contents of the memory stream and write it all out to a file on disk; then open that file as a file stream
ONLINE: extent the FileStream class creating an adapter that will wrap a MemoryStream object and expose it as a FileStream (essentially acting as a converter)
The reason one is marked [OFFLINE] is because you need to have to full contents of the memory stream before you output it to the file (and once you do, modifications to the file stream will not affect the memory stream; nor changes to the memory stream, such as new data, be available to the file stream)
The second one is marked as [ONLINE] because once you create the adapter and you initialize the FileStream object from the MemoryStream you could process any new data in the MemoryStream using the FileStream adapter object. You would essentially be able to read/write and seek into the memory stream using the file stream as a layer on top of the memory stream. Presumably, that's what you'd want to do..
Of course, it depends on what you need to do, but I'm leaning towards the second [ONLINE] version as the better in the general sense.

How to read Hebrew text using System.IO.FileStream?

Am I missing something or does System.IO.FileStream not read Unicode text files containing Hebrew?
public TextReader CSVReader(Stream s, Encoding enc)
{
this.stream = s;
if (!s.CanRead)
{
throw new CSVReaderException("Could not read the given CSV stream!");
}
reader = (enc != null) ? new StreamReader(s, enc) : new StreamReader(s);
}
Thanks
Jonathan
The FileStream is nothing but a byte stream, which is language/charset agnostic. You need an encoding to convert bytes into characters (including Hebrew) and back.
There are several classes to help you with that, the most important being System.Text.Encoding and System.IO.StreamReader and System.IO.StreamWriter.
The stream might be closed.
From msdn on CanRead:
If a class derived from Stream does
not support reading, calls to the
Read, ReadByte, and BeginRead methods
throw a NotSupportedException.
If the stream is closed, this property
returns false.
I'd wager that you're simply not using the right encoding. Chances are you're passing in Encoding.Default or Encoding.ASCII when you should actually be passing Encoding.UTF8 (most common) or Encoding.Unicode to that method.
If you're sure that you're using the right encoding, post the full code and an example of the file.

Categories

Resources