Search code examples
c#filestreambinarywriter

Best way to read a short array from disk in C#?


I have to write 4GB short[] arrays to and from disk, so I have found a function to write the arrays, and I am struggling to write the code to read the array from the disk. I normally code in other languages so please forgive me if my attempt is a bit pathetic so far:

using UnityEngine;
using System.Collections;
using System.IO;

public class RWShort : MonoBehaviour {

    public static void WriteShortArray(short[] values, string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
        {
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                foreach (short value in values)
                {
                    bw.Write(value);
                }
            }
        }
    } //Above is fine, here is where I am confused: 


    public static short[] ReadShortArray(string path) 
    {
        byte[]  thisByteArray= File.ReadAllBytes(fileName);
        short[] thisShortArray= new short[thisByteArray.length/2];      
                for (int i = 0; i < 10; i+=2)
                {
                    thisShortArray[i]= ? convert from byte array;
                }


        return thisShortArray;
    }   
}

Solution

  • Shorts are two bytes, so you have to read in two bytes each time. I'd also recommend using a yield return like this so that you aren't trying to pull everything into memory in one go. Though if you need all of the shorts together that won't help you.. depends on what you're doing with it I guess.

    void Main()
    {
        short[] values = new short[] {
            1, 999, 200, short.MinValue, short.MaxValue
        };
    
        WriteShortArray(values, @"C:\temp\shorts.txt");
    
        foreach (var shortInfile in ReadShortArray(@"C:\temp\shorts.txt"))
        {
            Console.WriteLine(shortInfile);
        }
    }
    
    public static void WriteShortArray(short[] values, string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
        {
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                foreach (short value in values)
                {
                    bw.Write(value);
                }
            }
        }
    }
    
    public static IEnumerable<short> ReadShortArray(string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        using (BinaryReader br = new BinaryReader(fs))
        {
            byte[] buffer = new byte[2];
            while (br.Read(buffer, 0, 2) > 0)
                yield return (short)(buffer[0]|(buffer[1]<<8)); 
        }
    }
    
    

    You could also define it this way, taking advantage of the BinaryReader:

    public static IEnumerable<short> ReadShortArray(string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        using (BinaryReader br = new BinaryReader(fs))
        {
            while (br.BaseStream.Position < br.BaseStream.Length)
                yield return br.ReadInt16();
        }
    }