mboost-dp1
Search-replace C#
- Forside
- ⟨
- Forum
- ⟨
- Programmering
Mojn
Mit C# program (http://newz.dk/forum/programmering/c-sql-problemer-101351) nærmer sig sin afslutning, men der er lige én ting, der stadigvæk mangler.
Jeg har en masse værdier, der skal ændres, alt efter hvad værdien er.
Det kunne f.eks. være "DK" der skal ændres til 8, "DE", der skal ændres til 9 osv. Problemet er, at der er ~150 mulige værdier (i har måske allerede nu gættet, at det er landekoder?), der skal søges efter.
Dataene, der skal ændres, står i en komma-separeret tekstfil, så det er ret ligetil at søge efter dem, vil jeg tro? Der hvor mine evner kommer til kort, er når jeg skal søge i filen efter 150 værdier.
Men måske man kan lave det med et array alá array[0][0] = "AA" "0", og så loope den med en for-løkke, og smide værdien ind i en søge-dims, der scanner tekstfilen igennem for lignende værdier?
Eller har i en bedre metode?
Håber i kan fange hvad jeg mener :D
Mit C# program (http://newz.dk/forum/programmering/c-sql-problemer-101351) nærmer sig sin afslutning, men der er lige én ting, der stadigvæk mangler.
Jeg har en masse værdier, der skal ændres, alt efter hvad værdien er.
Det kunne f.eks. være "DK" der skal ændres til 8, "DE", der skal ændres til 9 osv. Problemet er, at der er ~150 mulige værdier (i har måske allerede nu gættet, at det er landekoder?), der skal søges efter.
Dataene, der skal ændres, står i en komma-separeret tekstfil, så det er ret ligetil at søge efter dem, vil jeg tro? Der hvor mine evner kommer til kort, er når jeg skal søge i filen efter 150 værdier.
Men måske man kan lave det med et array alá array[0][0] = "AA" "0", og så loope den med en for-løkke, og smide værdien ind i en søge-dims, der scanner tekstfilen igennem for lignende værdier?
Eller har i en bedre metode?
Håber i kan fange hvad jeg mener :D
Windcape (3) skrev:Du skal under alle omstændigheder definere relationen! Og hvis det ikke er noget der skal gentages flere gange, så er manual search/replace helt fint, og vil nok være hurtigere at skrive i hånden, end at begynde at kode.
Altså, der er 6 tekstfiler, hvor det samme skal udføres på.
Det nemmeste er vel bare at lave en replace-class, hvor man overfører filnavnet som parameter ikke?
Hvilken relation er det jeg skal definere?
*opdateret med StringBuilder (bedre performance).
var codes = new Dictionary<string, int>();
codes.Add("DK", 8);
codes.Add("DE", 9);
var builder = new StringBuilder(
File.ReadAllText("data.csv")
);
foreach (var code in codes)
{
builder.Replace(code.Key, code.Value.ToString());
}
File.WriteAllText("data.csv", builder.ToString());
Du kan lave et program i dit yndlingsscriptingsprog til at lave slave-arbejdet med at oversætte din tekstfil til indholdet i dit dictionary/map.
python
Ellers kan du nok få din editor til at gøre det for dig (hvis du har en fornuftig editor)
python
f = open("din-fil.txt")
a = f.read()
b = a.split(",")
counter = 0
res = """SomeClass varname = new SomeThing() {\n"""
for i in b:
res = res +"{" + i + ", " + counter +"},\n"
counter+=1
#fjern sidste komma og newline og tilføj slut-tuborg.
res = res[:-2] + "\n}"
print res
Ellers kan du nok få din editor til at gøre det for dig (hvis du har en fornuftig editor)
Lidt blandede betragtninger:
1) Hvis de numeriske værdier ikke i sig selv har betydning men bare skal pege på en lande tabel, så kan lister over landekode sagtens findes i passende format. Jeg har f.eks. en SQL fil med 240 lande liggende på lager.
2) Simple replace i hele filen eller hele linier er ikke nødvendigvis en brugbar løsning, da anden tekst kunne indeholde landekoderne. Linierne skal splittes op i felter og der skal kun erstattes i lande feltet. Og så kan man bruge direkte opslag i Dictionary<string,int> (som er den rigtige datastruktur).
3) Giver det mening at lave en CSV->CSV konvertering? Jeg antager at data skal loades ind i en database. Så kunne man jo lave konverteringen i forbindelse med indsæt i databasen. Hvis du bruger din egen loader skal du alligevel have læst alle linier og splittet op i felter.
1) Hvis de numeriske værdier ikke i sig selv har betydning men bare skal pege på en lande tabel, så kan lister over landekode sagtens findes i passende format. Jeg har f.eks. en SQL fil med 240 lande liggende på lager.
2) Simple replace i hele filen eller hele linier er ikke nødvendigvis en brugbar løsning, da anden tekst kunne indeholde landekoderne. Linierne skal splittes op i felter og der skal kun erstattes i lande feltet. Og så kan man bruge direkte opslag i Dictionary<string,int> (som er den rigtige datastruktur).
3) Giver det mening at lave en CSV->CSV konvertering? Jeg antager at data skal loades ind i en database. Så kunne man jo lave konverteringen i forbindelse med indsæt i databasen. Hvis du bruger din egen loader skal du alligevel have læst alle linier og splittet op i felter.
#13
1) Numrene skal have en bestemt værdi, da de skal passe med GLS's landekoder.. Så jeg har møjsomt siddet og taste 192 landekoder ind med tilhørende numre.. :<
2) Jeg har taget mine forholdsregler for det scenarie, du opstiller ved at søge specifikt på ",DK," - dataen jeg henter ud fra vores database indeholder kun de data ved landekoden.
3) Njarh, ikke som sådan. Dataene skal ligge i en bestemt rækkefølge med et bestemt antal felter, kommaer osv., så GLS's program (Interline) kan forstå formatet. Jeg skal såmænd bare sørge for at min output-fil er korrekt formateret, og så kan jeg importere det direkte fra GLS's program.
Jeg har forøvrigt fået programmet til at spille - så nu skal der bare laves lidt små-justeringer, lidt optimeringer hist og her, og så er det klar til brug. Måske man skulle uploade koden, så i kunne komme med en sønderlemmende kritik af hvor elendigt jeg slamkoder :)
1) Numrene skal have en bestemt værdi, da de skal passe med GLS's landekoder.. Så jeg har møjsomt siddet og taste 192 landekoder ind med tilhørende numre.. :<
2) Jeg har taget mine forholdsregler for det scenarie, du opstiller ved at søge specifikt på ",DK," - dataen jeg henter ud fra vores database indeholder kun de data ved landekoden.
3) Njarh, ikke som sådan. Dataene skal ligge i en bestemt rækkefølge med et bestemt antal felter, kommaer osv., så GLS's program (Interline) kan forstå formatet. Jeg skal såmænd bare sørge for at min output-fil er korrekt formateret, og så kan jeg importere det direkte fra GLS's program.
Jeg har forøvrigt fået programmet til at spille - så nu skal der bare laves lidt små-justeringer, lidt optimeringer hist og her, og så er det klar til brug. Måske man skulle uploade koden, så i kunne komme med en sønderlemmende kritik af hvor elendigt jeg slamkoder :)
#16
Hvis du mangler kode at kigge på så start her:
ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5...
:-)
Hvis du mangler kode at kigge på så start her:
ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5...
:-)
arne_v (15) skrev:#14
CSV er det næstbedste export/import firma, men det er en elendig database.
Var det ikke bedre at maintaine data i en database og så dumpe tiL CSV, når du skal importere i det der som jeg ikke ved hvad er.
Det gør vi også. Dataene ligger i vores Navision-database og bliver først hentet ud, når jeg skal have opdateret vores Interline (Interline er det program GLS har lavet til at oprette forsendelser med). CSV-filerne bliver kun brugt i ~5 minutter til at opbevare dataen inden de ryger videre. :)
Som lovet:
http://pastebin.com/CCJA0Sqh
Jeg har fjernet firma-navn mv.
Og ja, i så rigtigt.. al koden er smidt ind i button1_Click. :D
http://pastebin.com/CCJA0Sqh
Jeg har fjernet firma-navn mv.
Og ja, i så rigtigt.. al koden er smidt ind i button1_Click. :D
#) Brug statements (parameters) i stedet for string concatenation til alt dit SQL. Predefinere en række statements, og så vælg hvilket du vil bruge ud fra dine conditions (if-sætninger)
#) while (myReader.Read()) { ... } (linje 158-168): Her bør du bruge en StringBuilder. Samt at du burde overveje at bruge GetString() i stedet for ToString(), for at give mere klar kode.
#) Jeg ville nok have brugt syntaksen fra #8 i min definition af landekoderne, det ser pænere ud ;-)
#) Message.Show er ondskaben selv!
#) Overordnet:
Læs op om parameters
Lær at bruge string.format i stedet for string concatenation ("foo" + "bar")
Navngiv lidt bedre, f.eks.
TextWriter TW = new StreamWriter(@"c:\" + firma + "nolev.txt");
burde være
TextWriter writer = new StreamWriter(@"c:\" + firma + "nolev.txt");
#) while (myReader.Read()) { ... } (linje 158-168): Her bør du bruge en StringBuilder. Samt at du burde overveje at bruge GetString() i stedet for ToString(), for at give mere klar kode.
#) Jeg ville nok have brugt syntaksen fra #8 i min definition af landekoderne, det ser pænere ud ;-)
#) Message.Show er ondskaben selv!
#) Overordnet:
Læs op om parameters
Lær at bruge string.format i stedet for string concatenation ("foo" + "bar")
Navngiv lidt bedre, f.eks.
TextWriter TW = new StreamWriter(@"c:\" + firma + "nolev.txt");
burde være
TextWriter writer = new StreamWriter(@"c:\" + firma + "nolev.txt");
Windcape (24) skrev:#) Brug statements (parameters) i stedet for string concatenation til alt dit SQL. Predefinere en række statements, og så vælg hvilket du vil bruge ud fra dine conditions (if-sætninger)
Er det ikke det, jeg gør allerede? At der er lavet concatenation er udelukkende for min egen læsbarheds-skyld :) Men du mener måske, at det skal gøres højere oppe i koden og ikke i selve if-sætningerne?
Windcape (24) skrev:#) while (myReader.Read()) { ... } (linje 158-168): Her bør du bruge en StringBuilder. Samt at du burde overveje at bruge GetString() i stedet for ToString(), for at give mere klar kode.
Klar kode er ikke min største prioritet hehe. Det skal bare virke :) Men jo, der er masser af plads til forbedring.
Windcape (24) skrev:#) Message.Show er ondskaben selv!
Sandt. Men hvordan skal man ellers få beskeden frem, om at den er færdig?
Ang. navngivningen, så ved jeg godt, den er slem.. men det er ren dovenskab :)
XorpiZ (25) skrev:Klar kode er ikke min største prioritet hehe. Det skal bare virke :) Men jo, der er masser af plads til forbedring.
XorpiZ (25) skrev:Ang. navngivningen, så ved jeg godt, den er slem.. men det er ren dovenskab :)
Alt andet lige, så er overskuelig kode meget, meget nemmere at modificere og debugge, så overskuelig kode vil hjælpe dig betragteligt med at få det til at virke.
Kodeorden er et farligt sted at være doven. Det kommer tilbage til dig 10-fold senere. De dovne skriver god kode, så de ikke skal bruge så meget krudt på at debugge senere. ;-)
#26
Så sandt, så sandt. Jeg ville skam også gøre det lækkert og overskueligt, hvis det var et større projekt, men nu er det bare et lille program, der skal gøre min hverdag lettere - og som aldrig vil kunne bruges af folk udenfor firmaet :)
Ligeledes ville jeg nok også tilføje kommentarer hist og her, hvis det var nødvendigt hehe.
Så sandt, så sandt. Jeg ville skam også gøre det lækkert og overskueligt, hvis det var et større projekt, men nu er det bare et lille program, der skal gøre min hverdag lettere - og som aldrig vil kunne bruges af folk udenfor firmaet :)
Ligeledes ville jeg nok også tilføje kommentarer hist og her, hvis det var nødvendigt hehe.
#fortsat
2) Jer er enig i at der bør bruges parameter.
3) Jeg ville hverken bruge ToString eller GetString for at hive data ud af readeren men derimod type cast. Det er mere type sikkert.
4) Jeg ville hverken bruge string konkatanering eller StringBuilder til at opbygge linier med men derimod udskrive delene enkeltvist med Write og saa en tom WriteLine til sidst. Simplere kode.
2) Jer er enig i at der bør bruges parameter.
3) Jeg ville hverken bruge ToString eller GetString for at hive data ud af readeren men derimod type cast. Det er mere type sikkert.
4) Jeg ville hverken bruge string konkatanering eller StringBuilder til at opbygge linier med men derimod udskrive delene enkeltvist med Write og saa en tom WriteLine til sidst. Simplere kode.
XorpiZ (27) skrev:Så sandt, så sandt. Jeg ville skam også gøre det lækkert og overskueligt, hvis det var et større projekt, men nu er det bare et lille program, der skal gøre min hverdag lettere - og som aldrig vil kunne bruges af folk udenfor firmaet :)
Af hensyn til dine kolleger skal du så huske at se dig grundigt for inden du krydser vejen.
XorpiZ (27) skrev:Ligeledes ville jeg nok også tilføje kommentarer hist og her, hvis det var nødvendigt hehe.
Trivielle kommentarer er overflødige, men en kommentar i toppen som dokumenterer tabel struktur og fil format kunne nok være godt.
arne_v (28) skrev:#23
Der er vist flere ting som kan forbedres.
1) Den er hel gal med algoritmen.
læs fra database
skriv til fil
læs fra fil
lav 200 replaces
skriv til fil
er meget langtfra optimalt.
læs fra database
erstat landekode via simpelt opslag i Dictionary
skriv til fil
er meget bedre.
Det er faktisk rigtigt. Det har jeg ikke lige luret :) Dog tager det ikke mange millisekunder for hver gennemkørsel. Jeg vil dog huske det til næste gang, jeg skal lave noget lignende.
Filnavn-logik-tingen har jeg rettet lidt på, så der ikke er så mange overflødige ting.
arne_v (31) skrev:Af hensyn til dine kolleger skal du så huske at se dig grundigt for inden du krydser vejen.
Nu er det udelukkende mig selv, der skal kigge på koden.. Jeg arbejder i et tøjfirma, og der er ikke en eneste udover mig, der forstår C# eller andet programmeringssprog. Min chef kan lidt SQL, men det er vist også det.
arne_v (31) skrev:Trivielle kommentarer er overflødige, men en kommentar i toppen som dokumenterer tabel struktur og fil format kunne nok være godt.
Sandt. Det må jeg hellere få gjort.
I øvrigt kan det oplyses, at jeg har fundet en bug i mit program.
Interline (GLS-programmet) forventer input i stil med nummer,navn,adresse1,adresse2,postnummer,landekode plus et par stykker mere. Det virker som sådan fint nok - indtil der er et "," i en af de felter. Hvis adresse1 f.eks. er "Vej123, 1. sal", så bliver det hele skubbet en tand med det resultat, at importeringen fejler.
Problemet er ikke så stort, da det i 90% af tilfældende kun er i adresse1 at problemet opstår, så der har jeg løst det med et grimt grimt hack.. skal lige have set om jeg kan finde en mere elegant løsning, der ændrer alle kommaer til punktummer f.eks. :)
XorpiZ (32) skrev:
Interline (GLS-programmet) forventer input i stil med nummer,navn,adresse1,adresse2,postnummer,landekode plus et par stykker mere. Det virker som sådan fint nok - indtil der er et "," i en af de felter. Hvis adresse1 f.eks. er "Vej123, 1. sal", så bliver det hele skubbet en tand med det resultat, at importeringen fejler.
Problemet er ikke så stort, da det i 90% af tilfældende kun er i adresse1 at problemet opstår, så der har jeg løst det med et grimt grimt hack.. skal lige have set om jeg kan finde en mere elegant løsning, der ændrer alle kommaer til punktummer f.eks. :)
Understøtter Interline/GLS ikke en håndtering af dette f.eks. mulighed for at putte tekst i "" eller dublering eller escaping?
Altså at skrive god kode er ligesom at huske at børste tænder om morgenen. Det gør at koden (tænderne) holder længere, og ikke virker frastødende på andre mennesker.
# parameters
http://msdn.microsoft.com/en-us/library/yy6y35y8.a...
http://msdn.microsoft.com/en-us/library/system.dat...
# parameters
http://msdn.microsoft.com/en-us/library/yy6y35y8.a...
http://msdn.microsoft.com/en-us/library/system.dat...
#parameters
Foretrækker man indenbysk så evt. et af mine skriverier:
http://www.eksperten.dk/guide/831
Foretrækker man indenbysk så evt. et af mine skriverier:
http://www.eksperten.dk/guide/831
arne_v (37) skrev:#parameters
Foretrækker man indenbysk så evt. et af mine skriverier:
http://www.eksperten.dk/guide/831
Jeg tager lige en nærlæsning i morgen. Den ser ud til at være skrevet på et niveau, vi alle kan være med på :)
Nu har jeg et nyt problem - men af en lidt anden kaliber.
For at slippe for at have mit brugernavn og password stående direkte i koden, har jeg lavet to tekstbokse og en login-knap.
I loginButton_Click har jeg lavet noget kode, der tester om forbindelsen til databasen kan oprettes. Problemet er så, at startButton_Click (der henter data mv. fra databasen) ikke kan "se" databaseforbindelsen:
Jeg formoder, det er fordi, programmet ikke kan "se" login-koden, før der er blevet trykket på knappen?
Er der en nem måde at omgå det på?
For at slippe for at have mit brugernavn og password stående direkte i koden, har jeg lavet to tekstbokse og en login-knap.
I loginButton_Click har jeg lavet noget kode, der tester om forbindelsen til databasen kan oprettes. Problemet er så, at startButton_Click (der henter data mv. fra databasen) ikke kan "se" databaseforbindelsen:
Error 1 The name 'sqlConnection' does not exist in the current context
Jeg formoder, det er fordi, programmet ikke kan "se" login-koden, før der er blevet trykket på knappen?
Er der en nem måde at omgå det på?
nej, det er fordi du skal deklarer det som et class member, så den er tilgængelig fra mere end én metode.
ala:
ala:
SqlConnection sqlConnection;
void LoginButton_Click(object sender, EventArgs e)
{
sqlConnection = new SqlConnection(....);
}
void StartButton_Click()
{
if (sqlConnection != null && sqlConnection.IsConnected)
{
// do stuff
}
else
{
// forbindelsen er ikke oprettet, vis en fejl?
}
}
#database connections
God skik og brug er at vente med at åbne connection indtil den skal bruges og close/dispose straks efter at man er færdig med den.
Du kan godt teste om forbindelsen er OK ved login, men bare luk igen og opret en ny forbindnelse når du skal bruge databasen.
God skik og brug er at vente med at åbne connection indtil den skal bruges og close/dispose straks efter at man er færdig med den.
Du kan godt teste om forbindelsen er OK ved login, men bare luk igen og opret en ny forbindnelse når du skal bruge databasen.
arne_v (43) skrev:#database connections
God skik og brug er at vente med at åbne connection indtil den skal bruges og close/dispose straks efter at man er færdig med den.
Du kan godt teste om forbindelsen er OK ved login, men bare luk igen og opret en ny forbindnelse når du skal bruge databasen.
Sandt. Ellers holder man jo en forbindelse åben.
Nå, nyt spørgsmål.
Alt virker som det skal - bortset fra ÆØÅ. Dataene jeg får læst ud og dataene der bliver gemt ser rigtige ud (ÆØÅ ser fint ud osv.).
Men når dataene bliver indlæst i Interline, bliver ÆØÅ til øæå!?!. Åbner jeg min text-fil i notepad, lukker den og indlæser filen igen, så ser ÆØÅ korrekt ud.
Jeg forestiller mig, at det er encoding-problemer, men så vidt jeg kunne læse mig frem til, så bruger Streamwriteren UTF-8 som standard, og så burde det vel ikke være et problem?
Har i to genier et bud? :)
XorpiZ (44) skrev:Jeg forestiller mig, at det er encoding-problemer, men så vidt jeg kunne læse mig frem til, så bruger Streamwriteren UTF-8 som standard, og så burde det vel ikke være et problem?
StreamWriter har en constructor som tager Encoding som argument.
Prøv med Encoding.Default eller Encoding.GetEncoding(1252).
#49
Nu har jeg prøvet med Encoding.Default og Encoding.UTF8, hvilket giver to forskellige resultater, der begge er forkerte. Encoding.GetEncoding(1252) giver samme resultat som UTF8.
Ligeledes giver Unicode også et forkert output.
Det kan nævnes, at hvis jeg åbner tekstfilen i notepad, så ser alt korrekt ud :<
Nu har jeg prøvet med Encoding.Default og Encoding.UTF8, hvilket giver to forskellige resultater, der begge er forkerte. Encoding.GetEncoding(1252) giver samme resultat som UTF8.
Ligeledes giver Unicode også et forkert output.
Det kan nævnes, at hvis jeg åbner tekstfilen i notepad, så ser alt korrekt ud :<
Gå til top
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.