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

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.

Related

Navigating MimeKit.MimeParser

Is it possible to read the Nth attachment of the Mth message, from an mbox file, using MimeKit.MimeParser? In my case, I would store few messages (few fields for each msg including a list of attachments) to an in-memory data structure and after that, I want to be able to return to a specific message attachment and read its contents.
Things I have tried so far:
Remembering underlying stream position for each read message and
positioning the stream to that position before calling
_parser.ParseMessage() later to get the message and its attachment.
I also tried to use LINQ methods to get a message by
MessageID in combination with setting stream position to 0 and
calling SetStream again and without it.
The above does not work.
Here is some code just to illustrate my efforts:
public void SaveAttachment(Attachment att, Stream outStream)
{
_inputStream.Seek(0, SeekOrigin.Begin);
_parser.SetStream(_inputStream, false);
//MimeMessage mimeMsg = _parser.Skip((int)(att.Parent as Message).Position).First();
MimeMessage mimeMsg =_parser.SingleOrDefault(x => x.MessageId == (att.Parent as Message).EntryID);
MimeEntity mimeAtt = mimeMsg.Attachments.ToList()[att.AttachmentIndex];
if (mimeAtt is MessagePart)
{
(mimeAtt as MessagePart).Message.WriteTo(outStream);
}
else
{
(mimeAtt as MimePart).Content.DecodeTo(outStream);
}
}
Is it possible to read the Nth attachment of the Mth message, from an mbox file, using MimeKit.MimeParser?
If you want to do this, then you will need exact stream start/end offsets of the MimeEntity that you want.
Then what you'll want to do is to wrap the stream in a MimeKit.IO.BoundStream with those stream offsets to prevent the parser from straying outside of those bounds and set the BoundStream on the MimeParser.
When you set the stream, make sure to use MimeFormat.Entity (and not MimeFormat.Mbox) since you are only interested in parsing a single MimeEntity (which can be a multipart containing other MimeEntities).
To get these offsets, you'll need to subscribe to the MimeParser's MimeEntityBegin/End events when you first parse the mbox: http://www.mimekit.net/docs/html/Events_T_MimeKit_MimeParser.htm
I want to be able to return to a specific message attachment and read its contents.
Have you looked into the persistent argument to MimeParser.SetStream()?
This may still use more memory than you want to use (since it will have all of the headers loaded + track stream offsets for each MimeEntity's content), but you may find that it's more convenient and has low-enough memory usage to fit your practical needs.
When this property is set to true, instead of loading each MimePart's content into RAM, it instead creates a BoundStream that wraps the stream provided to the MimeParser so that when you request the content of these MimeParts, it lazily loads it from disk.
By default (or when persistent = false), the MimeParser will load that content into a MemoryBlockStream (effectively a MemoryStream that tries to reduce byte array resizing for performance) which can, as you probably know, use quite a bit of memory if the messages have large attachments (or a lot of them).
The thing to watch out for when using persistent = true is that you will need to keep the mbox file stream open if you want to be able to get the content of any of the MimeParts parsed by the parser. Once you close the stream, trying to get the content of any MimeParts will likely result in an ObjectDisposedException.

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.

C# Networkstream BeginRead How to obtain buffer length/size?

I have a problem to obtain the right buffer size of my application.
What i read from the site about specifying the buffer size is normally declared before reading.
byte[] buffer = new byte[2000];
And then using to get the result.
However, this method will stop once the received data contains '00', but my return code contains something like this... 5300000002000000EF0000000A00. and the length is not fixed, can be this short until 400 bytes
So the problems comes, if i define a prefixed length like above, eg 2000, the return value is
5300000002000000EF0000000A000000000000000000000000000000000000000000000000000..........
thus making me unable to split the bytes to the correct amount.
Can any1 show me how to obtain the actual received data size from networkstream or any method/cheat to get what i need?
Thanks in advance.
Network streams have no length.
Unfortunately, your question is light on detail, so it's hard to offer specific advice. But you have a couple of options:
If the high-level protocol being used here offers a way to know the length of the data that will be sent, use that. This could be as simple as the remote host sending the byte count before the rest of the data, or some command you could send to the remote host to query the length of the data. Without knowing what high-level protocol you're using, it's not possible to say whether this is even an option or not.
Write the incoming data into a MemoryStream object. This would always work, whether or not the high-level protocol offers a way to know in advance how much data to expect. Note that if it doesn't, then you will simply have to receive data until the end of the network stream.
The latter option looks something like this:
MemoryStream outputStream = new MemoryStream();
int readByteCount;
byte[] rgb = new byte[1024]; // can be any size
while ((readByteCount = inputStream.Read(rgb, 0, rgb.Length)) > 0)
{
outputStream.Write(rgb, 0, readByteCount);
}
return outputStream.ToArray();
This assumes you have a network stream named "inputStream".
I show the above mainly because it illustrates the more general practice of reading from a network stream in pieces and then storing the result elsewhere. Also, it is easily adapted to directly reading from a socket instance (you didn't mention what you're actually using for network I/O).
However, if you are actually using a Stream object for your network I/O, then as of .NET 4.0, there has been a more convenient way to write the above:
MemoryStream outputStream = new MemoryStream();
inputStream.CopyTo(outputStream);
return outputStream.ToArray();

Manipulating Mp3's as Array Using NAudio

I'm trying to reimplement an existing Matlab 8-band equalizer GUI I created for a project last week in C#. In Matlab, songs load as a dynamic array into memory, where they can be freely manipulated and playing is as easy as sound(array).
I found the NAudio library which conveniently already has Mp3 extractors, players, and both convolution and FFT defined. I was able to open the Mp3 and read all its data into an array (though I'm not positive I'm going about it correctly.) However, even after looking through a couple of examples, I'm struggling to figure out how to take the array and write it back into a stream in such a way as to play it properly (I don't need to write to file).
Following the examples I found, I read my mp3's like this:
private byte[] CreateInputStream(string fileName)
{
byte[] stream;
if (fileName.EndsWith(".mp3"))
{
WaveStream mp3Reader = new Mp3FileReader(fileName);
songFormat = mp3Reader.WaveFormat; // songFormat is a class field
long sizeOfStream = mp3Reader.Length;
stream = new byte[sizeOfStream];
mp3Reader.Read(stream, 0, (int) sizeOfStream);
}
else
{
throw new InvalidOperationException("Unsupported Exception");
}
return stream;
}
Now I have an array of bytes presumably containing raw audio data, which I intend to eventually covert to floats so as to run through the DSP module. Right now, however, I'm simply trying to see if I can play the array of bytes.
Stream outstream = new MemoryStream(stream);
WaveFileWriter wfr = new WaveFileWriter(outstream, songFormat);
// outputStream is an array of bytes and a class variable
wfr.Write(outputStream, 0, (int)outputStream.Length);
WaveFileReader wr = new WaveFileReader(outstream);
volumeStream = new WaveChannel32(wr);
waveOutDevice.Init(volumeStream);
waveOutDevice.Play();
Right now I'm getting errors thrown in WaveFileReader(outstream) which say that it can't read past the end of the stream. I suspect that's not the only thing I'm not doing correctly. Any insights?
Your code isn't working because you never close the WaveFileWriter so its headers aren't written correctly, and you also would need to rewind the MemoryStream.
However, there is no need for writing a WAV file if you want to play back an array of byes. Just use a RawSourceWaveStream and pass in your MemoryStream.
You may also find the AudioFileReader class more suitable to your needs as it will provide the samples as floating point directly, and allow you to modify the volume.

What is ADODB.Stream?

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.

Categories

Resources