zwei statische öffentliche Methoden (1x für die Übergabe eines Textfiles, 1x zur direkten Übergabe eines mehrzeiligen Strings mit Zeilenumbrüchen)
Der übergebene String wird anhand von Zeilenumbrüche aufgeteilt und auf das erste Vorkommen eines Whitespace-Zeichens in einer nicht leeren Zeile geprüft. Anschließend wird über regex aus jeder Zeile die gleiche Anzahl an führenden, gleichartigen Whitespace-Zeichen entfernt, wobei die Zeile mit den wenigsten vorangestellten Whitespace-Zeichen als Referenz gilt.
Auf Exceptionhandling, Performanceoptimierung und ähnliches wurde im Snippet bewusst verzichtet. Dies kann gerne über die Kommentare geschehen.
Anhand der Kommentare der Version 1 sind folgende Verbesserungen eingeflossen:
1. Es werden nun zuerst Kontrollzeichen für den Zeilenumbruch gesucht
2. Es wird anhand des ersten Zeichens der ersten nicht leeren Zeile entschieden, welches Whitespacezeichen verwendet wurde und dessen Häufigkeit bis zum ersten anderen Zeichen geprüft.
3. Es wird geprüft, ob dieses gefundene Zeichen ein Whitespacezeichen ist
4. Es wird nun (wie im Kommentar des Originalsnippets als Alternative beschrieben), der komplette mehrzeilige String über regex bearbeitet und nicht mehr zeilenweise in einer Schleife
5. Die Zeile mit den wenigsten vorangestellten Whitespace-Zeichen gilt als Referenz
Verbesserungspotential:
Wenn abwechselnd Leerzeichen und Tabs verwendet werden, wird nur das erste Whitespacezeichen gewertet. Somit können Whitespaces for dem eigentlichen Textbeginn stehen bleiben.
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace WhitespaceRemover
{
class Program
{
static void Main(string[] args)
{
WhitespaceRemover.ProcessFile(args[0]);
}
}
public static class WhitespaceRemover
{
/// <summary>
/// reads a textfile and writes the processed content back to a new textfile
/// </summary>
/// <param name="file"></param>
public static void ProcessFile(string file)
{
//probably not the most beautiful way for getting the filename but it works :)
var newfile = Regex.Replace(file, @"^(.*?)(\..+)?$","$1_removed$2");
//call the processing method and write the processed content to the new file.
using (var swr = new StreamWriter(newfile))
{
swr.Write(ProcessString(File.ReadAllText(file)));
}
}
/// <summary>
/// removes an equal number of whitespaces on each line of a multiline string, taking the first line as reference
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static string ProcessString(string text)
{
//find the new line control characters
var newlinecontrolcharacters = Regex.Replace(text, @"^.*?(\r?\n)", "$1|", RegexOptions.Multiline).Split('|')[0];
//splits the multiline string into an array using the new line control characters
var textLines = text.Split(new string[] { newlinecontrolcharacters }, StringSplitOptions.None);
char[] characters = null;
char whitespacecharacter = default(char);
var count = 0;
var minappearances = 0;
bool minappearancesassigned = false;
bool characterfound = false;
//split the first line into a character array
for (int i = 0; i < textLines.Length; i++)
{
if(!string.IsNullOrWhiteSpace(textLines[i]))
{
characters = textLines[i].ToCharArray();
if (!characterfound)
{
//first character is defined as whitespace character that will be removed
whitespacecharacter = characters[0];
//if first character is not a whitespace character, keep on searching
if (!Regex.IsMatch(whitespacecharacter.ToString(), @"\s"))
{
continue;
}
else
{
characterfound = true;
}
}
//finally loop through it as long as there are whitespace characters and count them
while (characters[count] == whitespacecharacter) count++;
//assign the value of count to minappearances, if a line was found with less whitespace characters
if(minappearances > count || (minappearances == 0 && !minappearancesassigned))
{
minappearances = count;
minappearancesassigned = true;
}
count = 0;
}
}
if(minappearances == 0 || characterfound == false)
return text;
//do the replacements for the whole file
return Regex.Replace(text, string.Format("^{0}{1}(.*?)$", whitespacecharacter.ToString(), string.Concat(new string[]{"{",minappearances.ToString(),"}"})), "$1", RegexOptions.Multiline);
}
}
}
8 Kommentare zum Snippet