An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
Hi @Jonathan ,
Thank you for reaching out.
The issue starts at the very first line:
var lines = File.ReadAllLines(@File0);
File.ReadAllLines splits the file on line breaks and returns each line without its terminating carriage return / line feed characters https://learn.microsoft.com/en-us/dotnet/api/system.io.file.readalllines. So by the time you reach:
if (!lastLine.EndsWith("\r\n"))
Since File.ReadAllLines removes the line terminators, lastLine does not include the original trailing CRLF. For a file containing at least one line, the condition therefore evaluates to true even when the original file ends with CRLF correctly. If the file contains no lines, lines.Last() throws an InvalidOperationException before this check is reached.
To inspect line terminators, you need the file's raw content instead — File.ReadAllText or File.ReadAllBytes both preserve them.
Option 1 — Check only the end of the file, if you simply want to confirm the file ends with a CR LF:
string content = File.ReadAllText(@File0);
if (!content.EndsWith("\r\n", StringComparison.Ordinal))
{
using (var sw = new StreamWriter(@File1, allowappend, Encoding.Unicode))
{
sw.WriteLine("CR LF is missing at the end of the file.");
}
}
Option 2 — Check every line, including standalone LF, standalone CR, and a final line without a terminating CRLF:
string content = File.ReadAllText(@File0);
using (var sw = new StreamWriter(@File1, allowappend, Encoding.Unicode))
{
int lineNumber = 1;
int lineStart = 0;
if (content.Length == 0)
sw.WriteLine("The file is empty; a CRLF-terminated line is required.");
for (int index = 0; index < content.Length; index++)
{
if (content[index] == '\r')
{
if (index + 1 < content.Length && content[index + 1] == '\n')
index++;
else
sw.WriteLine($"Line {lineNumber}: CR without LF.");
}
else if (content[index] == '\n')
sw.WriteLine($"Line {lineNumber}: LF without CR.");
else
continue;
lineNumber++;
lineStart = index + 1;
}
if (lineStart < content.Length)
sw.WriteLine($"Line {lineNumber}: missing CRLF at end of file.");
}
Additional Notes
- A final line without a trailing line break may be acceptable for your application. Both examples enforce a trailing CRLF and treat an empty file as invalid, so please confirm that this matches your requirement.
-
File.ReadAllTextuses UTF-8 by default and automatically detects supported Unicode encodings, including UTF-16, when a byte-order mark (BOM) is present. For a non-UTF-8 file without a BOM, specify its encoding explicitly. For example, useFile.ReadAllText(@File0, Encoding.Unicode)for UTF-16 little-endian input without a BOM. -
Encoding.Unicodein theStreamWriterconstructor controls the log file's encoding only. It does not affect how the input file is read.
Please try the option that matches your requirement and let me know whether you still encounter unexpected results.
If you found my response helpful or informative, I would greatly appreciate it if you could share your thoughts by reacting to this answer or leaving a comment.
Thank you.