1

I am creating a small pet cryptography project and am reading text from a text file, modifying it while each line is in an array, and then submitting it back to its text file. The issue is adding the string back to the file, as the text file's current text is simply deleted as of how the program is now. More specifically I want to bring all of the strings in the array into a single string, and this is where I believe the fault is. Here is the code I have written.

static void Main(string[] args)
    {
        string[] getAllText = File.ReadAllLines("H:\\BetaText.txt");

        File.WriteAllText("H:\\BetaText.txt", string.Concat(Lock(getAllText)));
        System.Diagnostics.Process.Start("H:\\BetaText.txt");
    }

Lock is simply a method in my program that returns an encrypted array of strings. The text file is confirmed to be correctly parsed in and the modification return does indeed return the array as I wanted. The issue continues to be my string.Concat() statement. I do know how to fix this issue with a multi-line statement but I would like to avoid this and learn why the Concat() statement is not working the way I believed it would. I have also used the string.Join method with a "" delimiter. Looking through StackOverflow I have not seen this answered and according to MSDN documentation I do not believe I should be having this issue. Thank you.

Matt Quick
  • 70
  • 9
  • Wouldn't the code you posted only put a single item into the string[]? It seems like you would need to perform a `Split()` method on some delimiter within the the string result of `File.ReadAllLines` in order to get multiple items within the string[]. Concatenating a single string[] item would only return a single string. – Russ Mar 03 '16 at 16:29
  • 1
    Is there a particular reason you are encrypting each string in the array, when you could read the entire file into a byte[], encrypt, and then write back the encrypted bytes? – Matthew Layton Mar 03 '16 at 16:29
  • 1
    So what does `string.Concat` return and what did you expect it to return? – Pieter Witvoet Mar 03 '16 at 16:38
  • @Russ: Each line of my text file is added into an individual string in my array when I pull it with `ReadAllLines` – Matt Quick Mar 03 '16 at 16:39
  • @series0ne My intention is to learn how to use this method to use the encryption before moving onto better ways to do it. When I reach that step I will be on Code Review. Better to learn how to do it the easy way now and learn how to do it the best way once I have a good grasp of it. Also I am not yet comfortable modifying bytes as I have yet to work with individual bytes. – Matt Quick Mar 03 '16 at 16:42
  • @PieterWitvoet My intention is to have it give me a single string with all of the strings in the array concatenated onto my new single string. – Matt Quick Mar 03 '16 at 16:43
  • I think the problem you'll have with that is separating the encrypted strings back out for decryption. If you are going to do it this way, you should write the encrypted strings separately with line terminators ("\r\n"), then you can read the encrypted lines back in like you did the unencrypted ones. – Kevin Mar 03 '16 at 16:49
  • So the declared return type of `Lock` is `string[]`? – Jeppe Stig Nielsen Mar 03 '16 at 17:03
  • @Kevin Yes I have tried writing back the message with a hard-coded array and it returns it in the same way I grabbed it. So all good there. – Matt Quick Mar 03 '16 at 21:20
  • @JeppeStigNielsen Yes the return type is a string array. – Matt Quick Mar 03 '16 at 21:20
  • But when `a` is of declared type `string[]`, then `string.Concat(a)` works as it should. You should debug and find out what `string[]` you have. What is its `Length`, what do its entries look like? Try to show us more, then we can tell you what happens. Try to show us a complete scenario reproducing the problem. Then we can analyze it. _Edit:_ And answer Pieter Witvoet's comment above. – Jeppe Stig Nielsen Mar 03 '16 at 22:00
  • @MattQuick: you still have not explained your actual problem. `string.Concat` does return a single string, which is what you want... What output did you expect and what did you actually get? – Pieter Witvoet Mar 03 '16 at 22:24
  • @PieterWitvoet I expected a single string with some placeholder text. Instead it gives me an empty string. Please note this is not a `null` string. – Matt Quick Mar 04 '16 at 02:45
  • The most likely cause for that is `Lock` returning an empty array. Can you show us that method (or at least the relevant parts of it) so we can reproduce the problem? (a so-called [mcve]) – Pieter Witvoet Mar 04 '16 at 07:55
  • @PieterWitvoet As explained in the text of my question I know its not the method returning an empty string array as it currently replaces the pulled array with a hard-coded array that is guaranteed not null or empty. – Matt Quick Mar 04 '16 at 14:46
  • I know, but I can also verify that `string.Concat` does work as expected, so without seeing the relevant parts of your code I cannot reproduce your problem. – Pieter Witvoet Mar 04 '16 at 14:51
  • @PieterWitvoet At this point I feel I have a problem with my system. I have opened other projects to test their use and it is as you say. Regardless of how it _should_ be that is sadly not how it is going for me. As such I will be giving credit to the answer that would be correct under normal circumstances and will restart my project. Thanks for the help guys! – Matt Quick Mar 04 '16 at 15:14

3 Answers3

2

You can use String.Join to join string array into a single string.

String.Join ("", getAllText);

Also you can use Aggregate

getAllText.Aggregate((c, n) => string.Format("{0}{1}", c, n);

Using aggregate you can construct more sophisticated examples. For example this is how you can separate them with comma

getAllText.Aggregate((c, n) => string.Format("{0}, {1}", c, n));
Valentin
  • 5,380
  • 2
  • 24
  • 38
  • I have not seen this method before and am not aware how to use it. Can you give an example of what `f` and `n` are? I have checked MSDN but I do not fully understand. – Matt Quick Mar 03 '16 at 16:45
  • I changed `f` to `n`. I understand it as `c`-current set and `n` - next element. Try this link http://stackoverflow.com/questions/7105505/linq-aggregate-algorithm-explained – Valentin Mar 03 '16 at 16:51
  • I see absolutely no reason why one should use `Aggregate` like that when we have `string.Join` and `string.Concat`. – Jeppe Stig Nielsen Mar 03 '16 at 17:01
  • 1
    One problem with using `Aggregate` instead of `string.Concat` or `string.Join` is that a new temporary string instance is created for each iteration. That is wasteful. The methods `string.Concat` and `string.Join` can be optimized to use a `StringBuilder` or something even better. – Jeppe Stig Nielsen Mar 03 '16 at 21:52
1

Or simply joined with a ','. Choose another delimiter if you wish

 var writeText = string.Join(", ", Lock(getAllText).Select(v => v.ToString()));
 File.WriteAllText("H:\\BetaText.txt", writeText);
James Dev
  • 2,979
  • 1
  • 11
  • 16
1

So what you are doing is reading a file, line-by-line into a string[] and then encrypting each line, and then committing those lines back into a file.

Personally, I think your approach is wrong (gut feeling, but here's why)

File.ReadAllLines creates an array by splitting the file using line breaks (Environment.NewLine, "\r\n", "\n"...) - what happens if your encryption algorithm happens to encrypt some particular byte as a newline character? - all of a sudden your line breaks are different - therefore doing the reverse would essentially fail (I think, since decrypting the file "might" be working with different line breaks)

A better solution would be this:

byte[] unencryptedBytes = Encoding.UTF8.GetBytes(File.ReadAllText(filename));
byte[] encryptedBytes = Lock(unencryptedBytes);
File.WriteAllText(filename, Encoding.UTF8.GetString(encryptedBytes));

I know this is not technically what you are asking for (sorry) - I just have this gut feeling that what you're doing, might not work.

Matthew Layton
  • 39,871
  • 52
  • 185
  • 313