Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
Her er min kode der validere på min tekst om det er RTF tekst, altså hvor de to chars efter \' er mellem 0-9 og a-f
Teksten den skal validere er denne:
{\rtf1\ansi\ansicpg1252\deff0\deflang1030{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}} \viewkind4\uc1\pard\fs20 Fint lille feriehus, beliggende p\'e5 en meget central grund i Vorup\'f8r. Huset er velholdt og indbyder til afslappende ferie. Her er ikke parabol p\'e5 TV'et men omr\'e5det byder p\'e5 mange andre muligheder for at nyde hinandens selskab. \par Vand indeholdt i lejeprisen. Str\'f8m dkk 1,95 pr. kwh. Ingen gebyr for husdyr. Reng\'f8ring kan bestilles for dkk 495,00. Gratis udl\'e5n af b\'f8rnesenge, b\'f8rnestole og tr\'e6kvogne. Gratis adgang til tennisbaner (Vorup\'f8r), \f1 samt gratis adgang til badeland (Sydthy Sv\'f8mmebad, Hurup) hele \'e5ret! \par \f0 \par \par }
Byt det ud med "H.Tekst"
char[] Chars = new char[] {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; List<char> ValidChars = new List<char>(); ValidChars.AddRange(Chars);
MatchCollection MC = Regex.Matches(H.Tekst, "\'", RegexOptions.IgnoreCase);
foreach (Match M in MC) { string RTFField = H.Tekst.Substring(M.Index + 1, 2);
if (!ValidChars.Contains(RTFField[0]) || !ValidChars.Contains(RTFField[1])) { //Er ikke valid!!! } }
namespace e792027 { class Program { class TestClass { public string Tekst = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1030{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}} \viewkind4\uc1\pard\fs20 Fint lille feriehus, beliggende p\'e5 en meget central grund i Vorup\'f8r. Huset er velholdt og indbyder til afslappende ferie. Her er ikke parabol p\'e5 TV'et men omr\'e5det byder p\'e5 mange andre muligheder for at nyde hinandens selskab. \par Vand indeholdt i lejeprisen. Str\'f8m dkk 1,95 pr. kwh. Ingen gebyr for husdyr. Reng\'f8ring kan bestilles for dkk 495,00. Gratis udl\'e5n af b\'f8rnesenge, b\'f8rnestole og tr\'e6kvogne. Gratis adgang til tennisbaner (Vorup\'f8r), \f1 samt gratis adgang til badeland (Sydthy Sv\'f8mmebad, Hurup) hele \'e5ret! \par \f0 \par \par }"; }
static void Main(string[] args) { TestClass H = new TestClass();
Dit alternative bud vil da gå uden om ugylgige \'XX kombinationer som jeg lige ser det... Spørgsmålet er self om det betyder noget... (aner ikke meget om RTF text)
Derudover forstår jeg ikke helt nødvendigheden i et lookbehind...
Enyways... ------------------------
Har lige tiladt mig at forenkle din kode en smule...:
class TestClass { public string Tekst = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1030{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}} \viewkind4\uc1\pard\fs20 Fint lille feriehus, beliggende p\'e5 en meget central grund i Vorup\'f8r. Huset er velholdt og indbyder til afslappende ferie. Her er ikke parabol p\'e5 TV'et men omr\'e5det byder p\'e5 mange andre muligheder for at nyde hinandens selskab. \par Vand indeholdt i lejeprisen. Str\'f8m dkk 1,95 pr. kwh. Ingen gebyr for husdyr. Reng\'f8ring kan bestilles for dkk 495,00. Gratis udl\'e5n af b\'f8rnesenge, b\'f8rnestole og tr\'e6kvogne. Gratis adgang til tennisbaner (Vorup\'f8r), \f1 samt gratis adgang til badeland (Sydthy Sv\'f8mmebad, Hurup) hele \'e5ret! \par \f0 \par \par }\' "; }
static void Main( string[] args ) { TestClass h = new TestClass(); string ValidChars = "0123456789abcdef";
foreach ( Match m in macthes ) { int a = m.Index + 2, b = a + 1; if ( !(b < h.Tekst.Length) ) break; //Her er den formentlig invalid... ved du nok bedre...
Console.WriteLine( "DEBUG: [{0}{1}]", h.Tekst[ a ], h.Tekst[ b ] );
if ( !ValidChars.Contains( h.Tekst[ a ].ToString() ) || !ValidChars.Contains( h.Tekst[ b ].ToString() ) ) Console.WriteLine( "Er ikke valid!!!" ); } }
-------------------------------------- Og for ren fun har jeg lige lavet nogle forskellige måder at tjecke om dine 2 efterfølgende chars er valid: -------------------------------------- class TestClass { public string Tekst = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1030{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}} \viewkind4\uc1\pard\fs20 Fint lille feriehus, beliggende p\'e5 en meget central grund i Vorup\'f8r. Huset er velholdt og indbyder til afslappende ferie. Her er ikke parabol p\'e5 TV'et men omr\'e5det byder p\'e5 mange andre muligheder for at nyde hinandens selskab. \par Vand indeholdt i lejeprisen. Str\'f8m dkk 1,95 pr. kwh. Ingen gebyr for husdyr. Reng\'f8ring kan bestilles for dkk 495,00. Gratis udl\'e5n af b\'f8rnesenge, b\'f8rnestole og tr\'e6kvogne. Gratis adgang til tennisbaner (Vorup\'f8r), \f1 samt gratis adgang til badeland (Sydthy Sv\'f8mmebad, Hurup) hele \'e5ret! \par \f0 \par \par }\' "; }
static void Main( string[] args ) { TestClass h = new TestClass(); MatchCollection macthes = Regex.Matches( h.Tekst, @"\\'", RegexOptions.IgnoreCase ); // RETTET HER
foreach ( Match m in macthes ) { int a = m.Index + 2, b = a + 1; if ( !(b < h.Tekst.Length) ) break; //Her er den formentlig invalid... ved du nok bedre...
Console.Write( "DEBUG: [{0}{1}]", h.Tekst[ a ], h.Tekst[ b ] );
if( !ArimeticCheck( h.Tekst[ a ] ) || !ArimeticCheck( h.Tekst[ b ] ) ) Console.Write( " (A) is invalid!" ); else Console.Write( " (A) is valid..." );
if ( !StringCheck( h.Tekst[ a ] ) || !StringCheck( h.Tekst[ b ] ) ) Console.Write( " (S) is invalid!" ); else Console.Write( " (S) is valid..." );
if ( !HexCheck( string.Concat( h.Tekst[ a ], h.Tekst[ b ] ) ) ) Console.Write( " (H) is invalid!" ); else Console.Write( " (H) is valid..." );
Console.WriteLine(); } }
public static bool ArimeticCheck( char c ) { if ( c > 47 && c < 58 ) return true; if ( c > 64 && c < 71 ) return true; if ( c > 96 && c < 103 ) return true; return false; }
public static bool StringCheck( char c ) { return "0123456789abcdef".Contains( c.ToString() ); }
public static bool HexCheck( string s ) { int x; return int.TryParse( s, NumberStyles.HexNumber,NumberFormatInfo.InvariantInfo,out x ); } }
Den kan sagtens modifiseret til at tage *alle* de ugyldige med, men jeg troede netop at du ville undgå dem? Hvorfor matche alt og så bortsortere efter validChars bagefter når man kan gøre det allerede ved matchingen.
Hvis du vil have alle tegn med skal:
Regex re = new Regex(@"(?<=\\')([0-9a-f]{2})");
ændres til:
Regex re = new Regex(@"(?<=\\')(.{2})");
Jeg bruger lookbehind til at finde alle de 2-tegns koder som er foranstillet med \'. På den måde slipper jeg for at skulle lave efterfølgende regnearbejde på at finde indekset for et match, og så regne to pladser frem. Det er ikke nødvenligt med lookbehind men det er da en smule elegant?
Da vi i det sidste har fat i noget der vægter Performance VS. Pæn kode ect. har jeg lige tilladt mig at undersøge den side af sagen også:
static void Main( string[] args ) { StringBuilder builder = new StringBuilder( 1000 ); Random rand = new Random();
for ( int i = 0; i < 10000000; i++ ) builder.Append( rand.Next( 32, 126 ) );
string str = builder.ToString();
DateTime dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) ArimeticCheck( str[ i ] ); Console.WriteLine( "Time for ArimeticCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) CharArrayCheck( str[ i ] ); Console.WriteLine( "Time for CharArrayCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) StringCheck( str[ i ] ); Console.WriteLine( "Time for StringCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i+=2 ) HexCheck( string.Concat( str[ i ],str[ i+1 ]) ); Console.WriteLine( "Time for HexCheck: {0}", DateTime.Now.Subtract( dt ) ); }
public static char[] hexChars = "0123456789abcdef".ToCharArray();
public static bool ArimeticCheck( char c ) { if ( c > 47 && c < 58 ) return true; if ( c > 64 && c < 71 ) return true; if ( c > 96 && c < 103 ) return true; return false; }
public static bool StringCheck( char c ) { return "0123456789abcdef".Contains( c.ToString() ); }
public static bool CharArrayCheck( char c ) { return Array.BinarySearch<char>( hexChars, c ) > -1 ? true : false; }
public static bool HexCheck( string s ) { int x; return int.TryParse( s, NumberStyles.HexNumber,NumberFormatInfo.InvariantInfo,out x ); }
Giver dette resultat:
Time for ArimeticCheck: 00:00:00.2031250 Time for CharArrayCheck: 00:00:01.4218750 Time for StringCheck: 00:00:03.8281250 Time for HexCheck: 00:00:02.9843750 Press any key to continue . . .
Hvor du kan se at rent performace whise så er det langt bedre at benytte et aritmetisk check...
Det med lookbehind var lige mig der sov... det er naturligvis for at undgå at få nuppet \' med ind i matchet...
Grunden til det andet er at hvis fx: \'gg fx ikke må forekomme i en tekst... så når du ikke at identificere der er en fejl, da dit regex bare hopper videre... og man får derfor ikke identificeret den som en evt. fejl... men som sagt så ved jeg ikke meget om RTF så det kan da være det er ok at det forekommer?...
Det går jo tilsyneladene mere ud på at validere teksten og ikke udhente de eventuelle \'xx koder...
Jeg ved heller ikke noget videre om RTF formatet, så jeg skal ikke kunne sige om der kan være andet end hexadecimale ciffre.
Nu er jeg ikke klar over formålet med dit program, men hvis det er meningen at du ønsker at finde de steder hvor der måtte være noget mystisk, vil det selvfølgelig ikke være nogen god ide ikke at matche alt.
Og vi tager lige den der Performance haløj igen for jeg glemete tydeligvis noget yderst vigtigt... den streng der kom ud af den tidligere kode var bare en masse numre så ja... jeg glemte at Caste det reandom number den gennererede til en char... FLOT!
static void Main( string[] args ) { StringBuilder builder = new StringBuilder( 1000 ); Random rand = new Random();
Array.Sort<char>( hexChars );
for ( int i = 0; i < 25000000; i++ ) builder.Append( (char)rand.Next( 32, 126 ) );
string str = builder.ToString();
DateTime dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) ArimeticCheck( str[ i ] ); Console.WriteLine( "Time for ArimeticCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) CharArrayCheck( str[ i ] ); Console.WriteLine( "Time for CharArrayCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) StringCheck( str[ i ] ); Console.WriteLine( "Time for StringCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i+=2 ) HexCheck( string.Concat( str[ i ], (str[ i+1 ])) ); Console.WriteLine( "Time for HexCheck: {0}", DateTime.Now.Subtract( dt ) );
dt = DateTime.Now; for ( int i = 0; i < str.Length; i++ ) ListCheck( str[ i ] ); Console.WriteLine( "Time for ListCheck: {0}", DateTime.Now.Subtract( dt ) ); }
public static char[] hexChars = "0123456789abcdef".ToCharArray(); public static List<char> ValidChars = new List<char>( hexChars );
public static bool ArimeticCheck( char c ) { if ( c > 47 && c < 58 ) return true; if ( c > 64 && c < 71 ) return true; if ( c > 96 && c < 103 ) return true; return false; }
public static bool StringCheck( char c ) { return "0123456789abcdef".Contains( c.ToString() ); }
public static bool CharArrayCheck( char c ) { return Array.BinarySearch<char>( hexChars, c ) > -1 ? true : false; }
public static bool HexCheck( string s ) { int x; return int.TryParse( s, NumberStyles.HexNumber,NumberFormatInfo.InvariantInfo,out x ); }
public static bool ListCheck( char c ) { return ValidChars.Contains( c ); }
Og resultatet:
Time for ArimeticCheck: 00:00:00.5468750 Time for CharArrayCheck: 00:00:01.7031250 Time for StringCheck: 00:00:04.3125000 Time for HexCheck: 00:00:03.1406250 Time for ListCheck: 00:00:02.5625000 Press any key to continue . . .
Svaret på spørgsmålet er jo simpelt, man har glemt at \ skal escapes ... og det er både i C# og Regex... så derfor: "\\\\'" eller @"\\'"...
Det er svaret på spørgsmålet her...
Men selve problem stillingen er for mig at se ud fra: Kommentar: wb-freekill - 16/08-2007 16:12:26
At Validere en given streng som RTF tekst... i forhold til alle de \'XX koder den måtte indeholde... og evt. mere?... dunno...
Så kan den kode jeg lige har postet identificere den hurtigste måde at lave den test på ud fra det kode freekill har nu (der er helt sikkert nok endnu bedre løsninger)...
Det har jeg så gjort som et ekstra informativt indput til freekill... vi ved jo ikke om det han skal validere drejer sig om små 5000 tegns tekster eller flere stakke af dokumenter på måske en 100.000 tegn pr. stk...
Bortset at hvis tjekket, af om syntaksen af RTF-filen er korrekt, begynder at være lidt mere omfattende end kun at skulle tjekke om nogle givne positioner indeholder hexadecimale cifre, ja så kan det hurtigt blive lidt mere kompliceret end kun at kigge på performance af visse typer test isoleret.
Hvorfor har du forresten ikke inkluderet et regex-tjek iblandt dine målinger? :^)
Synes godt om
Slettet bruger
17. august 2007 - 09:15#32
Puha, sikke en masse jeg fik sat i gang! tak for hjælpen!
Og ja, programmet bruges til at finde alle forekomster af RTF fejl i en MASSe tekster.
Da jeg testede det her i dag, så resultatet sådan ud:
Total House Texts: 16472 (tekster af et par hundrede tegn ca. Total errors: 6 Collecting Data Time: 00:00:06:9375000 //Henter det hele ind i et array fra en SQL Check Text Time: 00:00:00:4687500 //Matcher alle og gemmer fejl i array
Med denne kode:
foreach (House H in HouseList) { MatchCollection MC = Regex.Matches(H.Tekst, @"\\'", RegexOptions.IgnoreCase);
foreach (Match M in MC) { string RTFField = H.Tekst.Substring(M.Index + 2, 2);
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.