//namespace edu.toronto.psi.vincent.util { using System; using System.IO; /** * Class for reading binary data from files to multidimensional arrays * and writing binary data to files from multidimensional arrays * * * Copyright (C) 2004 Vincent Cheung (vincent@psi.toronto.edu, http://www.psi.toronto.edu/~vincent/) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * @author Vincent Cheung * @version 1.1 08/05/04 */ public class ArrayReaderWriter { /** * Writes an array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[] array, string filename) { // the size of the array int[] size = {array.Length}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int i = 0; i < array.Length; i++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[i]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for file.Close(); } // end write method /** * Writes a rectangular jagged array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[][] array, String filename) { // the size of the array int[] size = {array.GetLength(0), array.GetLength(1)}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int i = 0; i < array.Length; i++) { for(int j = 0; j < array[0].Length; j++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[i][j]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for file.Close(); } // end write method /** * Writes a rectangular jagged array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[][][] array, String filename) { // the size of the array int[] size = {array.Length, array[0].Length, array[0][0].Length}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int i = 0; i < array.Length; i++) { for(int j = 0; j < array[0].Length; j++) { for(int k = 0; k < array[0][0].Length; k++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[i][j][k]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for } // end for file.Close(); } // end write method /** * Writes a rectangular jagged array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[][][][] array, String filename) { // the size of the array int[] size = {array.Length, array[0].Length, array[0][0].Length, array[0][0][0].Length}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int t = 0; t < array.Length; t++) { for(int i = 0; i < array[0].Length; i++) { for(int j = 0; j < array[0][0].Length; j++) { for(int k = 0; k < array[0][0][0].Length; k++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[t][i][j][k]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for } // end for } // end for file.Close(); } // end write method /** * Writes a multidimensional array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[,] array, String filename) { // the size of the array int[] size = {array.GetLength(0), array.GetLength(1)}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int i = 0; i < array.GetLength(0); i++) { for(int j = 0; j < array.GetLength(1); j++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[i, j]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for file.Close(); } // end write method /** * Writes a multidimensional array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[, ,] array, String filename) { // the size of the array int[] size = {array.GetLength(0), array.GetLength(1), array.GetLength(2)}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int i = 0; i < array.GetLength(0); i++) { for(int j = 0; j < array.GetLength(1); j++) { for(int k = 0; k < array.GetLength(2); k++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[i, j, k]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for } // end for file.Close(); } // end write method /** * Writes a multidimensional array to a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * If the file already exists, then it will be overwritten. * * @param filename the name of the file to write to * @param array the array to write to the file * @throws IOException */ public static void write(double[, , ,] array, String filename) { // the size of the array int[] size = {array.GetLength(0), array.GetLength(1), array.GetLength(2), array.GetLength(3)}; int temp; long value; // create a stream to the file, overwriting any existing file Stream file = File.OpenWrite(filename); // write the number of array dimensions to the file temp = size.Length; for(int i = 0; i < 4; i++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } // write the array dimensions to the file for(int i = 0; i < size.Length; i++) { temp = size[i]; for(int j = 0; j < 4; j++) { file.WriteByte((byte)(temp & 0xff)); temp >>= 8; } } // write the array to the file for(int t = 0; t < array.GetLength(0); t++) { for(int i = 0; i < array.GetLength(1); i++) { for(int j = 0; j < array.GetLength(2); j++) { for(int k = 0; k < array.GetLength(3); k++) { // get the 64-bit long representation of the double value = BitConverter.DoubleToInt64Bits(array[t, i, j, k]); // write the 64-bit long to the stream for(int n = 0; n < 8; n++) { file.WriteByte((byte)(value & 0xff)); value >>= 8; } // end for } // end for } // end for } // end for } // end for file.Close(); } // end write method /** * Reads an array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[] read1DArray(String filename) { Stream file = File.OpenRead(filename); double[] array = null; int[] size = new int[1]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0]]; for(int i = 0; i < size[0]; i++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[i] = BitConverter.Int64BitsToDouble(value); } // end for file.Close(); return(array); } // end read1DArray method /** * Reads a rectangular jagged array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[][] read2DArray(String filename) { Stream file = File.OpenRead(filename); double[][] array = null; int[] size = new int[2]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0]][]; for(int i = 0; i < array.Length; i++) { array[i] = new double[size[1]]; for(int j = 0; j < array[0].Length; j++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[i][j] = BitConverter.Int64BitsToDouble(value); } // end for } // end for file.Close(); return(array); } // end read2DArray method /** * Reads a rectangular jagged array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[][][] read3DArray(String filename) { Stream file = File.OpenRead(filename); double[][][] array = null; int[] size = new int[3]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0]][][]; for(int i = 0; i < array.Length; i++) { array[i] = new double[size[1]][]; for(int j = 0; j < array[0].Length; j++) { array[i][j] = new double[size[2]]; for(int k = 0; k < array[0][0].Length; k++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[i][j][k] = BitConverter.Int64BitsToDouble(value); } // end for } // end for } // end for file.Close(); return(array); } // end read3DArray method /** * Reads a rectangular jagged array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[][][][] read4DArray(String filename) { Stream file = File.OpenRead(filename); double[][][][] array = null; int[] size = new int[4]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0]][][][]; for(int t = 0; t < array.Length; t++) { array[t] = new double[size[1]][][]; for(int i = 0; i < array[0].Length; i++) { array[t][i] = new double[size[2]][]; for(int j = 0; j < array[0][0].Length; j++) { array[t][i][j] = new double[size[3]]; for(int k = 0; k < array[0][0][0].Length; k++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[t][i][j][k] = BitConverter.Int64BitsToDouble(value); } // end for } // end for } // end for } // end for file.Close(); return(array); } // end read4DArray method /** * Reads a multidimensional array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[,] read2DMDArray(String filename) { Stream file = File.OpenRead(filename); double[,] array = null; int[] size = new int[2]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0], size[1]]; for(int i = 0; i < array.GetLength(0); i++) { for(int j = 0; j < array.GetLength(1); j++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[i, j] = BitConverter.Int64BitsToDouble(value); } // end for } // end for file.Close(); return(array); } // end read2DArray method /** * Reads a multidimensional array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[, ,] read3DMDArray(String filename) { Stream file = File.OpenRead(filename); double[, ,] array = null; int[] size = new int[3]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0], size[1], size[2]]; for(int i = 0; i < array.GetLength(0); i++) { for(int j = 0; j < array.GetLength(1); j++) { for(int k = 0; k < array.GetLength(2); k++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[i, j, k] = BitConverter.Int64BitsToDouble(value); } // end for } // end for } // end for file.Close(); return(array); } // end read3DArray method /** * Reads a multidimensional array from a file. * * The first four bytes (an integer) in the file indicate the number of dimensions of the array. * The size of the array along each of the dimensions are then written as four bytes each (integers), * note that the size along each of the dimensions must remain constant * The rest of the file contains the array values (double values) * * The 64-bit IEEE 754 floating-point "double format" bit layout is used * to write the byte representation of double values to the file. * * All values are written to the file in little endian form. * * @param filename the name of the file containing the array * @return the array in the file * @throws IOException */ public static double[, , ,] read4DMDArray(String filename) { Stream file = File.OpenRead(filename); double[, , ,] array = null; int[] size = new int[4]; int temp; long value; // get the number of dimensions of the array in the file temp = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); if(temp != size.Length) throw new IOException("File doesn't contain a " + size.Length + " dimensional array"); // get the size of the array along each of the dimensions for(int i = 0; i < size.Length; i++) size[i] = (file.ReadByte() & 0xff) | ((file.ReadByte() & 0xff) << 8) | ((file.ReadByte() & 0xff) << 16) | ((file.ReadByte() & 0xff) << 24); // read the array array = new double[size[0], size[1], size[2], size[3]]; for(int t = 0; t < array.GetLength(0); t++) { for(int i = 0; i < array.GetLength(1); i++) { for(int j = 0; j < array.GetLength(2); j++) { for(int k = 0; k < array.GetLength(3); k++) { value = 0; for(int n = 0; n < 8; n++) value |= (long)(file.ReadByte() & 0xff) << (8 * n); array[t, i, j, k] = BitConverter.Int64BitsToDouble(value); } // end for } // end for } // end for } // end for file.Close(); return(array); } // end read4DArray method } // end ArrayReaderWriter class //} // end namespace