2

I have some files and I am saving it in isolated storage, how do I convert isolated stream to Base64 using chunks, If I convert stream directly to base64 then, base64 becomes too long, and visual studio stopped working. So how to do using chunks? See my code below:

BinaryReader rdr = new BinaryReader(isofile);
long lng = rdr.BaseStream.Length;
int rr = Convert.ToInt32(lng);
byte[] b = rdr.ReadBytes(rr);
string str = Convert.ToBase64String(b);
Nitesh Kothari
  • 890
  • 12
  • 27

3 Answers3

3

Try using a predefined chunk size and read the file by chunks of data. Then you can use data from each chunk and use it. If you need to post the entire file as Base64, reading it by chunks will not change the fact it is too long, if that's the problem.

int chunkSize = 1024;
string source = @"file.accdb";

BinaryReader rdr = new BinaryReader(new FileStream(source, FileMode.Open));
int streamLength = (int)rdr.BaseStream.Length;


while (rdr.BaseStream.Position < rdr.BaseStream.Length) 
{
    byte[] b = new byte[chunkSize];

    long remaining = rdr.BaseStream.Length - rdr.BaseStream.Position;
    if(remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }

    string chunkString = Convert.ToBase64String(b);
    // .. do something with the chunk of data, write to a stream, etc
}

EDIT: I've tested this in your scenario, read the Wildlife video that you get with default windows installation with chunks and wrote them to a file with bytes, and also using Base64 encoded string like you are doing, both tests were OK, and I could play back the video without a problem in both cases, so the method of reading shouldn't be the problem here. I've supplied the method I used for the test. If the problem still persists, try uploading a small file and verify the sent contents match what your web service is getting and saving. I think that the problem might be what I described in the comment below, the hint that C# and Java treat Base64 a bit differently.

StringBuilder acc = new StringBuilder();
int chunkSize = 2187;
string source = @"Wildlife.wmv";

BinaryReader rdr = new BinaryReader(new FileStream(source, FileMode.Open));

while (rdr.BaseStream.Position < rdr.BaseStream.Length)
{
    byte[] b = new byte[chunkSize];

    long remaining = rdr.BaseStream.Length - rdr.BaseStream.Position;
    if (remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }

    acc.Append(Convert.ToBase64String(b));
}

FileStream fs = new FileStream(@"c:\dev\test.wmv", FileMode.OpenOrCreate);
fs.Write(Convert.FromBase64String(acc.ToString()),0,0);

Process.Start(@"c:\dev\test.wmv");
Andrej Kikelj
  • 800
  • 7
  • 11
  • shouldn't it be : `while (rdr.BaseStream.Position < StreamLength)` ? Otherwise, sounds sound enough :) – Noctis Aug 13 '14 at 06:29
  • Andrej, thanks man, I am testing your asnwer. Thank you so much!! – Nitesh Kothari Aug 13 '14 at 06:46
  • Andrej, When I try to play video using this code with VLC player, I am getting this message: "VLC can't recognize the input's format:"..Any correction? – Nitesh Kothari Aug 13 '14 at 07:42
  • Since you mentioned that you are trying to upload from C# to Java, I've stumbled upon something that might help you with the error: If you check this accepted answer: http://stackoverflow.com/a/13929054/1361993 the user was going the other way around, but apparently C# and Java have a difference in using Base64, answer says "It should be as simple as replacing the - and _ that Java uses with the + and / that C# uses", so maybe you could try replacing the other way around and see if it works for you. – Andrej Kikelj Aug 13 '14 at 07:58
  • http://stackoverflow.com/q/5805022/1698987 talks about something similar, but I'm surprised they have different implementations ...it's kind of defeating the purpose i guess... In any case, make sure you're not running into the problem I've highlighted in my answer as well . – Noctis Aug 13 '14 at 08:11
  • @AndrejKikelj ok brother, thank you, I am doing it!!god bless – Nitesh Kothari Aug 13 '14 at 09:07
  • I've added another change(fixed the edit code), the problem with reading by chunks and encoding in base64 is that you will need to read in chunks that are a multiple of 3. If you copy-paste the last edit, it should work, provided you have a video file to work with. When I was reading in multiples of 2(1024), the "composed" base64 string when being decoded gave an error, now that the chunks are a multiple of 3, the file can be read and written back OK. This should work for you. :) - Note the chunk size is now 2187 – Andrej Kikelj Aug 13 '14 at 09:20
  • @AndrejKikelj Yes, thats your final edit works like a charm!! Supperr. Keep it up man!! thanks – Nitesh Kothari Aug 13 '14 at 12:29
1

I'm still not a 100% about the why, but I would suggest looking at this answer for something similar.

I'm working with web services, and I can't remember needing to use base64 in a long time. Last time I did it was for a php one that talked to different applications ... You sure you need to do this?


Example (using Andrej code). THIS CASE WORKS , BUT : Read the warning after the code for more.

// Input
var my_string = "Hello world!";
// Get as binary
System.Text.ASCIIEncoding  encoding = new System.Text.ASCIIEncoding();
var input_as_binary = encoding.GetBytes(my_string);
    /*
        72 
        101 
        108 
        108 
        111 
        32 
        119 
        111 
        114 
        108 
        100 
        33 
    */
// If the following is not an exact divisor, It won't work.
int chunkSize = 6;
// Create a stream and reader
Stream stream = new MemoryStream(as_binary);
BinaryReader rdr = new BinaryReader(stream);
int streamLength = (int)rdr.BaseStream.Length;
// A stub to hold the bits of Base64. This will happen on your receiving end
var sb = new StringBuilder();

// from Andrej answer, I'm just using the "streamLength" Var he defined 
while (rdr.BaseStream.Position < streamLength) 
{
    byte[] b = new byte[chunkSize];

    long remaining = streamLength - rdr.BaseStream.Position;
    if(remaining >= chunkSize)
    {
        rdr.Read(b, 0, chunkSize);
    }
    else
    {
        rdr.Read(b, 0, (int)remaining);
    }
    string chunkString = Convert.ToBase64String(b).Dump("as base 64");

    // Lets assume we send it and it's received on the other side
    sb.Append(chunkString);
}

// This should happen on your receiving side as well
var other_side = sb.ToString(); // value => SGVsbG8gd29ybGQh
// Back into byte array
var byte_from_64 = Convert.FromBase64String(other_side);
// Back into string. Will hold "Hello World!"
var string_from_byte = encoding.GetString(byte_from_64);

The above works. But if you change the chunk size to something that doesn't give you precise Base64 bits (5 for example, instead of 6), you'll get a string like SGVsbG8=IHdvcmw=ZCEAAAA= and then an exception:

FormatException

The input is not a valid Base-64 string as it contains a non-base 64 character 
, more than two padding characters, or an illegal character among the pa... 

Hence why I suggested playing around with your input :)

Community
  • 1
  • 1
Noctis
  • 11,507
  • 3
  • 43
  • 82
  • Noctis, web service is created in Java and its type is "Base64", I am adding some media files, so I have to convert it to Base64. Thanks. Any suggestion? – Nitesh Kothari Aug 13 '14 at 06:17
  • Yep, look at the Andrej answer. I would test it with something short to make sure it doesn't behave funny though :) – Noctis Aug 13 '14 at 06:30