0

I have a txt file looking like this:

1 5 7 5
4 8 19 6
23 56 78 9

I want to read all these values and write them to new file, but with different order.

Output file should look like this:

1 4 23
5 8 56
7 19 78
5 6 9

Right now I am trying to read everything into array, but I am not sure how to handle this data later...

string line;
        using (StreamReader sr = new StreamReader(@"C:\Users\as\Desktop\file\1.txt", Encoding.Default))
        {
            line = sr.ReadToEnd();
            string[] lines = line.Split('\n');
            string newLine = lines[0].ToString();
        }

My input file can have even up to 400000 columns.

EDIT 2:

I tried sth like this, but still not working, any suggestions?

using (StreamReader sr = new StreamReader(@"C:\Users\as\Desktop\files\1.txt", Encoding.Default))
            {
                List<string> list = new List<string>();
                while ((line = sr.ReadLine()) != null)
                {
                    list.Add(line);
                }
                int valuesNumber = list[0].Split(' ').Count();

                List<string> final = new List<string>();

                for (int j = 0; j < valuesNumber ; j++)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        string[] stringArray = list[i].Split(' ');
                        final .Add(stringArray[j]);

                    }
                }
                using (StreamWriter writer = new StreamWriter(@"C:\Users\as\Desktop\files\2.txt", true))
                {
                    foreach (string item in result)
                    {
                        writer.WriteLine(item.ToString());
                    }
                }
            }

But I still get every number under previous one, like this:

1
4
23
5 
8
56
7
19
78
5
6
9
Michal_LFC
  • 649
  • 3
  • 11
  • 25
  • What's the text file's file size? And, does it have to be fast? – Stefan Nov 04 '13 at 14:26
  • Right now is like this example that I posted. It will always have 3 rows, but can have many headers. – Michal_LFC Nov 04 '13 at 14:27
  • If as Stefen asks and the file is not big. Make a Array of List and push them in the list for each line in the array. – kenny Nov 04 '13 at 14:28
  • But my files sometimes have even up to 400k columns... – Michal_LFC Nov 04 '13 at 14:30
  • 1
    Rough estimation with 400k columns puts your memory requirements in ... I guess ... the tens-of-megabytes order of magnitude. It should not be a problem to keep the entire problem set in memory. – Magnus Hoff Nov 04 '13 at 14:38

6 Answers6

1

This does what you want (it's the full console application so you can play with it yourself). This assumes, as per your example in your post, that you always have the same number of 'columns' per row. I left out the reading / writing to file to keep code concise.

using System.Collections.Generic;
using System.Linq;

namespace ChangeOrder
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>();
            list.Add("3 5 7 2");
            list.Add("13 15 17 12");
            list.Add("23 25 27 22");

            int numberOfValuesPerLine = list[0].Split(' ').Count();

            List<string> result = new List<string>();

            for (int j = 0; j < numberOfValuesPerLine; j++)
            {
                for (int i = 0; i < list.Count; i++)
                {                    
                    string[] stringArray = list[i].Split(' ');
                    result.Add(stringArray[j]);    
                }                    
            }
        }
    }
}
Dave
  • 8,163
  • 11
  • 67
  • 103
0

quote simple really, you read the lines into an array. you then need to split each line into an array. the separation from your example seems to be an empty space so if the line was:

1 5 7 5

you need to split it into an array:

var currentLineColumn = currentLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

so your array now would look like:

1
5
7
5

you do the same for each line....

Magnus Hoff
  • 21,529
  • 9
  • 63
  • 82
Ahmed ilyas
  • 5,722
  • 8
  • 44
  • 72
0

Without addressing performance, I can think of one approach that will work. I'm presenting it very roughly here but you should be able to code to this.

1) Determine the number of columns. Create an array with that many rows

2) Insert a line break at the beginning of the file

3) Set counter to 1

4) After each line break, append each successive item to successive rows

5) Repeat until number of iterations = number of columns (inserting line breaks after each row is processed)

Edit: Thought about it another minute. Edited above.

nycdan
  • 2,819
  • 2
  • 21
  • 33
0

Assuming all rows will have the same length (in your example, 4 elements per row):

        using (StreamReader sr = new StreamReader(@"C:\Users\as\Desktop\file\1.txt", Encoding.Default))
        {
            string content = sr.ReadToEnd();
            string[] lines = content.Split('\n');

            string[][] matrix = new string[lines.Length][];
            for (int i = 0; i < lines.Length; i++)
            {
                matrix[i] = lines[i].Split(' ');
            }

            //print column by column
            var rowLength = matrix[0].Length; // assuming every row has the same length

            //for each column
            for (int i = 0; i < rowLength; i++)
            {
                //print each cell
                for (int j = 0; j < matrix.Length; j++)
                {
                    Console.WriteLine(matrix[j][i]);
                }
            }
        }
dcastro
  • 66,540
  • 21
  • 145
  • 155
0

I don't much believe in giving away code, so I'm going to show you some pseudo-code:

//define rows as a two dimensional array.
rows := [][]

reader := read_file("1.txt")

pointer:= 0

for each line in the file
    row := line.Split(" ") // So put each number into it's own array slow.
    rows[pointer] := row.
    pointer := pointer +1 // Increase pointer.

Now you've got a list of all of the rows, you want to create columns out of them.

newRows := [][]

for x = 0 to rows.length
    for y = 0 to rows[x].length
        // Cycle through all values in multidimensional array.
        newRows[y][x] := rows[x][y] 

Then you can print out each value to file.

christopher
  • 26,815
  • 5
  • 55
  • 89
0

If memory isn't an issue, you can use line.Split(' ') to turn each line into an array and then a Transpose method to rotate your array of arrays.

That might look like:

using (StreamReader sr = new StreamReader(@"C:\Users\as\Desktop\file\1.txt"))
{
    string allLinesAsString = sr.ReadToEnd();
    string[] lines = allLinesAsString.Split('\n');
    string[][] allLines = lines.Select(line => line.Trim().Split(' ')).ToArray();
    var rotatedLines = allLines.Transpose().ToList();
    string rotatedLinesAsString = string.Join(Environment.NewLine,
                                rotatedLines.Select(x => string.Join(" ", x)));
    // write rotatedLinesAsString to a file
}

If the file is too large to do this all in-memory, you could write code to work with FileStreams at a lower level. It would mean two reads through the file and a lot of seeking, but would lower the memory requirement to practically nothing. In pseudocode, that would be something like:

file_stream = open(input_file)
line_indexes = file_stream.indexes_of('\n')
output_stream = (output file)
loop
    output_stream.write(next item from each line_index)
    move each line_index past the just-read item
end when you reach the end of the line
Community
  • 1
  • 1
Tim S.
  • 55,448
  • 7
  • 96
  • 122