-1

So far Ive got a function that reads in all the bytes using ReadBytes(). I want to use all to data and add it to my 'arrfile' which is a byte[].

private byte[] GetWAVEData(string strWAVEPath)
    {
        FileStream fs = new FileStream(@strWAVEPath, FileMode.Open, FileAccess.Read);

        byte[] arrfile = new byte[fs.Length - 44];
        fs.Position = 4;
    //  fs.Read(arrfile, 0, arrfile.Length);

        for (int i = 0; i < arrfile.Length; i++)      
        {
            int b = fs.ReadByte();
        }
        fs.Close();
        return arrfile;
    } 

I have used 'b' to read in all the bytes from the fileStream, now how do I put each value for 'b' into the 'arrfile' that is a byte[], using the loop?

user3602045
  • 39
  • 1
  • 5
  • Possible duplicate of [Creating a byte array from a stream](http://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream) – CSharpie Dec 07 '15 at 21:57

3 Answers3

1

You would do it by

arrfile[i] = (byte) b; // note: -1 is a special return value

but just don't do that. Use FileStream.Read() which directly reads into the byte array.

And since it seems you're trying to read a WAV file header, you should even consider another approach:

  1. define a struct that matches the wave header
  2. Read the struct by
T ReadStruct<T>(Stream stream)
{
    var buffer = new byte[Marshal.SizeOf(typeof(T))];
    stream.Read(buffer, 0, Marshal.SizeOf(typeof(T)));
    var gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    T result = (T)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(T));
    gcHandle.Free();
    return result;
}
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • I need to work on it byte by byte, using FileStream.Read() literally takes all the data and shifts it. I will later have to manipulate each byte like, so.. – user3602045 Dec 07 '15 at 21:50
  • a) you can still modify the data even if you use Read(). b) It's more expressive to modify the struct. – Thomas Weller Dec 07 '15 at 22:04
  • `FileStream.Read()` will convert the stream into an array of one byte on each item. I can process each byte easily this way. But arrfile[i] = b; won't work because ReadByte() return int and nobody want to store an array of byte as int because they must be converted before use. – Ray Chakrit Mar 11 '23 at 19:33
  • 1
    @RayChakrit It returns an `int` because -1 is used to indicate the end of the stream. You would need to check for -1 and cast it back to a byte. – Thomas Weller Mar 11 '23 at 19:37
1

The quick, inefficient answer to your question is that you could add the following within your for loop beneath the int b = fs.ReadByte(); line:

// b will be -1 if the end of the file is reached
if (b >= 0)
{
    arrfile[i] = (byte)b;
}

However, I'd suggest using the Read method to read all of the bytes into your array. Once you have them loaded into memory, you can manipulate the data in the array however you need to. Below is your code revised to use that approach:

        using(FileStream fs = new FileStream(@strWAVEPath, FileMode.Open, FileAccess.Read))
        {
            byte[] arrfile = new byte[fs.Length - 44];
            fs.Position = 4;
            int remainder = arrfile.Length;
            int startIndex = 0;
            int read;
            do
            {
                read = fs.Read(arrfile, startIndex, remainder);
                startIndex += read;
                remainder -= read;
            } while (remainder > 0 && read > 0);

            return arrfile;
        }

The reason for the while loop is that the Read method is not guaranteed to read all of the bytes that you request it to read on the first try. It will read at least one byte and not more than the number of bytes that you specify in the third parameter, unless it is at the end of the stream, in which case it will read zero bytes.

Also note that I put a using statement around your FileStream. You were calling the Close method on the FileStream, which was good, except that it wouldn't be called if an exception were thrown before reaching that point. The using statement effectively does the same thing, but will make sure the stream is closed even if an exception is thrown.

Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27
0

Thanks for all the answers, I got it working using:

private byte[] GetWAVEData(string strWAVEPath)
{
    FileStream fs = new FileStream(@strWAVEPath, FileMode.Open, FileAccess.Read);

    byte[] arrfile = new byte[fs.Length - 44];
    fs.Position = 44;


    for (int i = 0; i < arrfile.Length; i++)      
    {
        int b = fs.ReadByte();
        byte convert = Convert.ToByte(b);
        arrfile[i] = convert;
    }


    fs.Close();
    return arrfile;
}
user3602045
  • 39
  • 1
  • 5