Home > Net >  C# ReadFile _ Method returns string that sliced into jagged array
C# ReadFile _ Method returns string that sliced into jagged array

Time:02-23

I need to implement a method according to conditions:

char[][] Foo(StreamReader stream, int arraySize) {}

Method should return an underlying string that sliced into jagged array of characters according to arraySize.

First condition. If stream is string.Empty and arraySize is 10:

return Array.Empty<char[]>();

Second condition. If stream is "Lorem" and arraySize is 5:

return new char[][]
{
    new char[] { 'L', 'o', 'r', 'e', 'm' },
};

Third condition. If stream is "Lorem" and arraySize is 1:

return new char[][]
{
    new char[] { 'L' },
    new char[] { 'o' },
    new char[] { 'r' },
    new char[] { 'e' },
    new char[] { 'm' },
};

Forth condition. If stream is "Loremipsumdolorsitamet" and arraySize is 5:

return new char[][]
{
    new char[] { 'L', 'o', 'r', 'e', 'm' },
    new char[] { 'i', 'p', 's', 'u', 'm' },
    new char[] { 'd', 'o', 'l', 'o', 'r' },
    new char[] { 's', 'i', 't', 'a', 'm' },
    new char[] { 'e', 't' },
};

With my solution doesn't works Forth condition; To test my function I've created temp.txt file alongside Program.cs and put there above mentiond values (Lorem, Loremipsumdolorsitamet).

Implementation:

char[][] Foo(StreamReader stream, int arraySize) 
{
   long arrLength = 0;

    if (streamReader.BaseStream.Length % arraySize == 0)
    {
        arrLength = streamReader.BaseStream.Length / arraySize;
    }
    else
    {
        arrLength = streamReader.BaseStream.Length / arraySize   1;
    }

    char[][] array = new char[arrLength][];

    for (int i = 0; i < array.Length; i  )
    {
        array[i] = new char[arraySize];

        for (int j = 0; j < arraySize; j  )
        {
            array[i][j] = (char)streamReader.Read();
        }
    }

    return array;
}

call function and test results:

int num = 5;

var myArray = Foo(new StreamReader(@"D:\temp.txt"), num);

for (int i = 0; i < myArray.Length; i  )
{
  for (int k = 0; k < myArray[i].Length; k  )
  {
    Console.Write(myArray[i][k]   "\t");
  }
  Console.WriteLine();
}

Resalt is:

L       o       r       e       m
i       p       s       u       m
d       o       l       o       r
s       i       t       a       m
e       t       ▒       ▒       ▒

So, last array length is 5 (but should be - 2) and what the symbol is: '▒' ?

Please help!

CodePudding user response:

I've fixed my error:

char[][] Foo(StreamReader stream, int arraySize)
{
    long arrLength;

    if (stream.BaseStream.Length % arraySize == 0)
    {
        arrLength = stream.BaseStream.Length / arraySize;
    }
    else
    {
        arrLength = (stream.BaseStream.Length / arraySize)   1;
    }

    char[][] array = new char[arrLength][];

    for (int i = 0; i < array.Length; i  )
    {
        long chunkSize = arraySize;

        if (i == array.Length - 1 && stream.BaseStream.Length % arraySize != 0)
        {
            chunkSize = stream.BaseStream.Length % arraySize;
        }

        array[i] = new char[chunkSize];

        for (int j = 0; j < chunkSize; j  )
        {
            array[i][j] = (char)stream.Read();
        }
    }

    return array;
}

CodePudding user response:

If you are on .NET6, you can make use of the Chunk method to split the input into chunks:

char[][] Foo(TextReader stream, int arraySize) 
{
    return stream.ReadToEnd().Chunk(arraySize).ToArray();
}

If this is not possible, you may calculate the size of the current chunk as Math.Min(arraySize, array.Length - i * arraySize) and use this instead of arraySize in your for (int i...) loop. (array.Length - i * arraySize is the remaining length):

for (int i = 0; i < array.Length; i  )
{
    int chunkSize = Math.Min(arraySize, streamReader.BaseStream.Length - i * arraySize);
    array[i] = new char[chunkSize];

    for (int j = 0; j < chunkSize; j  )
    {
        array[i][j] = (char)streamReader.Read();
    }
}

CodePudding user response:

This might not be the best way, but for simplicity's sake you can just make a List<char[]> and then use StreamReader.ReadBlock() to fill a buffer. Then, based on the number of characters read in that block (conveniently returned as an int by the .ReadBlock() method), you instantiate an array of the correct size and add it to the list, using .ToArray() at the end to produce your char[][].

    char[][] Foo(StreamReader streamReader, int arraySize)
    {
        List<char[]> listOfArrays = new List<char[]>();
        char[] charBuffer = new char[arraySize];
        int charactersInThisBlock;

        while (!streamReader.EndOfStream)
        {
            //fills the charBuffer with as many characters as possible up to its' limit (arraySize)
            //the second parameter (0) simply keeps the function reading from the last unread character
            //the output will tell you the number of characters read into the buffer
            charactersInThisBlock = streamReader.ReadBlock(charBuffer, 0, arraySize);

            //create/fill your new array, and add it to the list
            char[] newArray = new char[charactersInThisBlock];
            for(int i = 0; i < charactersInThisBlock; i  )
            {
                newArray[i] = charBuffer[i];
            }

            listOfArrays.Add(newArray);
        }

        //return char[][]
        return listOfArrays.ToArray();
    }
  • Related