03. maj 2006 - 11:00Der er
29 kommentarer og 1 løsning
Slet specifik linie i en txtfil
Hej Alle
Jeg har et lille problem jeg ikke kan finde ud af og håber da i kan hjælpe mig herinde.
Jeg har denne textfil www.jajo.midtfyn.net/AFLAES.txt som indholder en masse info jeg bruger. Mit problem er at jeg skal have mulighed for at regigere de sidste 2 tal i hver linie til noget nyt, eks. skal linie 3 regigeres fra 87 til 88.
Lige pt laver jeg bare en linie der ligner den man redigere i på en prik dog med nye tal til sidst. Ville så bagefter slette den gamle linie men det kan jeg ikke helt finde ud af, så ender op med 2 linier der næsten ligner hinanden.
Håber om en af jer kan hjælpe med det, eller om der er en helt anden smartere måde at regigere en linie på.
Hvis i har brug for mere info skriver i bare. Programmerer til en PDA hvis det skulle have noget sige.
Har tænkt på at gå ind og søge efter "87" og så replace det med eks. "88", men hvis der nu står "87" flere steder bliver det vel rettet alle stederne eller?
Men på den anden side burde det være muligt da de første tegn i hver linie er unik (er de dog ikke i filen der er linket til, da det er en test fil) Hvordan ville man gøre det nemmest, altså søge efter det unikke i hver linie (de første tegn i starten) når dette er fundet replace det sidste tal med det nye skriv filen med ændringer og beholde alt det gamle?
1. Det er ikke meget anderledes, det var bare lige for info'ens skyld.
2. Jeg kender alle data fra filen, men det er kun det i starten (48260, LUKIA osv) der må benyttes da der er unikt. Man vælger det unikke fra en comboBox som herefter lister alle data fra linien hvor den unikke værdi er. Man skal herefter indtaste en ny værdi som sal erstattes med den gamle, værdien er placeret som der sidste i filen. http://www.jajo.midtfyn.net/pda.jpg billede fra programmet håber det giver lidt mere menning og håber jeg besvarede dit spørgesmål theSurfer eller må du bare råbe lidt af mig :P
Her er et forslag: - Læs hele filen ind i en variabel - opret en string array ("string[]") og opdel indeholdet af variablen ved "\n" ("nylinie") - loop fra 0 or til antallet af linier i string arrayen -- hvis fra start af linien, og til ";", er lig det ønskede --- erstat gammel værdi med ny værdi -- slut hvis -- hop ud af loop - dan ny (almindelig) streng igen via en loop, og gem hele strengen
Det betyder at hele filens indhold, bliver erstattet af den nye indhold, med den rettede værdi.
Yes det lyder fornuftigt, prøver det lige af og vender tilbage :) Jeg er ikke haj til det her endnu så der kan gå alt fra 30 min til 10 timer til jeg er færdig :P
Du kan evt bruge noget i stil med denne kode, så skulle du gerne få fat på "48260, LUKIA, 48260, LUKIA, 62069" osv..
unik = strarr[i]; unik = unik.substring(0, unik.indexOf(";")); // indholder jo f.eks. "LUKIA" if (unik == ønskedeværdi) { strarr[i] = strarr[i].Replace(gammelværdi, nyværdi) break; // hop ud af loopen }
Den her køre når formen loades, den finder de unikke værdier i hver linie og udksriver dem i en comboboks.
private void RetInfo_Load(object sender, System.EventArgs e) { int i = 0; FileInfo t = new FileInfo("\\my documents\\Personal\\AFLAES.txt"); if(t.Exists) { StreamReader readAll = new StreamReader("\\my documents\\Personal\\AFLAES.txt ", System.Text.Encoding.Default);
while ((linjerFraFil[i] = readAll.ReadLine()) != null) { //comboBoxforbrugernr indholder det unikke. comboBoxforbrugernr.Items.Add(linjerFraFil[i].Split(splitter)[0]); i++; } readAll.Close(); } else En messageboks med en fejl, da AFLAES.txt ikke findes. ----------------------------------------------------------------------------------- Sådan her ser koden ud hvor jeg henter data og indsætter det i mine testbokse/labels udfra hvad der er valgt i comboboksen.
delt = linjerFraFil[i].Split(splitter); //splitter er ';" labelMaalernr.Text = delt[1]; labelForbrugtype.Text = delt[2]; labelRegisternr.Text = delt[3]; labelRegistertype.Text = delt[4]; NyValue.Text = delt[7]; // den textbox hvor den nye værdi skal indtastes. findPoster.Close(); }
sorry, det ser nok total åndsvagt og er slam kode men det virker :P
theSurfer: Da det kun er en testfil der er linket til står der LUKIA flere steder med vilje, i den rigtige vil LUKIA kun stå 1 gang og alt vil være unikt i starten.
Din kode virker fint, jeg får byttet værdien ud med den nye værdi og den ligger så i "linie". Problemet er dog ikke helst løst endnu. Jeg har modificeret din kode lidt så den tager og ændre ud fra hvilken linie der er valgt i comboboksen (se billedet). Det virker fint.
Problemet er nu at få skrevet den nye linie ind i tekstfilen istedet for den gamle der er ændret i.
Jeg har leget lidt med StreamWriter men den ender altid med at der bare bliver add'et en ny linie og den gamle forbliver i filen. Jeg håber du eller andre lige kan regne den ud :)
hvis den nye linie har samme længde som den gamle linie, så kan man fuske det med noget direct access (Seek & Write)
hvis den nye linie har en anden længde en den gamle længde så skal du formentlig genskrive hele filen (du kan også nøjes med at genskrive fra der hvor ændringen sker - igen med lidt fusk)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO;
namespace q706949 { public partial class RetInfo : Form { // hvis du bruger "@", behøver du ikke at escape backslash (dvs, dobbelt backslash) string fil = Application.StartupPath + @"\AFLAES.txt"; // filen "AFLAES.txt" ligger sammen med EXE-filen string indhold = ""; // kommer til at indeholde indholdet af filen int i, j = 0; // interatorer string unikid = ""; // kommer til at indeholde det unikke id string[] data = null; // kommer til at indeholde dataene fra linier fra filen bool fundet = false; // checkpoint så man kan se, om det unikke id blev fundet
string[] linier = indhold.Split("\n".ToCharArray()); // split indholdet op i linier for (i = 0; i < linier.Length; i++) // løb alle linierne igennem { data = linier[i].Split(";".ToCharArray()); // split den nuværende linie unikid = data[0]; // dette unikke id er på plads 0 (første) på linien if (unikid == cbxId.Text) // sammen lign det unikke id med det valgte (combobox) { data[data.Length - 1] = tbxVaerdi.Text; // sætte sidste plads i data-array til text-værdien linier[i] = ""; // nulsil linien, så vi kan samle den igen, med den nye værdi for (j = 0; j < data.Length; j++) // løb igennem alle data-værdierne { linier[i] += data[j] + ";"; // tilføj den nuværende værdi til den nuværende linie } linier[i] = linier[i].Substring(0, linier[i].Length - 1); // fjerne det sidste ";" fundet = true; // sæt checkpoint, så man kan se, at der er set en rettelse = save file break; // hop ud af loopen } }
if (fundet == true) // check om der er blevet fundet/rettet noget { indhold = ""; // nulstil indholdet for (i = 0; i < linier.Length; i++) // løb igennem alle linierne { indhold += linier[i] + "\r\n"; // tilføj linien til indholdet og lav linieskift } indhold = indhold.Substring(0, indhold.Length - 2); // fjern det sidste linieskift
try { StreamWriter SW; // opret instans af StreamWrite så vi kan skrive til filen SW = File.CreateText(fil); // opret forbindelse til filen SW.Write(indhold); // skriv indholdet (alle linier + den nye værdi) SW.Close(); // afslut instansen OpdaterCombobox(); // opdater combobox'en, så man kan se at der er "sket" noget } catch (Exception ex) { // hvis der opstår fejl (f.eks. ved skrivning), fanges den her: if (ex.Message != "") MessageBox.Show("FEJL!\n" + ex.Message); } } } catch (Exception ex) { // hvis der opstår general fejl, fanges den her: if (ex.Message != "") MessageBox.Show("Error: " + ex.Message); } }
string[] linier = indhold.Split("\n".ToCharArray()); // *** cbxId.Items.Clear(); // tøm/nulstil combobox'en for (i = 0; i < linier.Length; i++) // løb igennem alle linierne { // filføj den unikke id til combobox'en: cbxId.Items.Add(linier[i].Split(";".ToCharArray())[0]); } cbxId.Focus(); // set fokus på combobox'en } catch (Exception ex) { // hvis der opstår general fejl, fanges den her: if (ex.Message != "") MessageBox.Show("Error: " + ex.Message); }
}
private string LaesFilenOgReturnerIndholdet() { string filens_indhold = ""; // nulstil variablen der kommer til at indeholde indholdet try { StreamReader SR; // opret instans af StreamWrite så vi kan skrive til filen SR = File.OpenText(fil); // opret forbindelse til filen filens_indhold = SR.ReadToEnd(); // put indholdet af filen i variablen "filens_indhold" SR.Close(); // afslut instansen } catch (Exception ex) { // hvis der opstår fejl (f.eks ved åben/læs fil), fanges den her: if (ex.Message != "") filens_indhold = "FEJL!\n\n" + ex.Message; } return filens_indhold.Replace("\r\n", "\n"); // erstat carrige return (?) og send indholdet retur }
private string HentDenSpecifikkeLinieMedDenMedsendteUnikkeId(string unikid) { string[] linier = indhold.Split("\n".ToCharArray()); // split string linie = ""; // nulstil variablen linie for (i = 0; i < linier.Length; i++) // løb alle linierne igennem { data = linier[i].Split(";".ToCharArray()); // opdel linien og put dataene i string-arrayen data string tmpid = data[0]; // den unikke id smides over i variablen "tmpid" if (tmpid == unikid) // sammenlign "tmpid" med den medsendte unikke id { // de er ens linie = linier[i]; // læg den nuværende linie over i variablen "linie" fundet = true; // sæt checkpoint, så man kan se, at linien blev fundet break; // hop ud af loopen } } if (fundet == true) // check om linien blev fundet { return linie; // linien blev fundet.. returner den } else { // linien blev IKKE fundet.. return en fejlmeddelelse: return "FEJL!\nDet unikke ID blev ikke fundet!"; } }
private void cbxId_SelectedIndexChanged(object sender, EventArgs e) { indhold = LaesFilenOgReturnerIndholdet(); // indlæs indholdet af filen string tmp = HentDenSpecifikkeLinieMedDenMedsendteUnikkeId(cbxId.Text); // hent linien if (tmp.Substring(0, 4) == "FEJL") // check for fejl = linien blev ikke fundet { MessageBox.Show(tmp); // linien blev ikke fundet.. vis en fejlmeddelelse } else { // linien blev fundet.. forsæt med at arbejde med den: data = tmp.Split(";".ToCharArray()); // opdel linien så vi kan få fat på dataene tmp = data[data.Length - 1]; // smid den sidste plads fra "data" over i "tmp" tbxVaerdi.Text = tmp; // vis værdien, så man kan se/redigere den } } } }
- Fordelen ved at læse fra filen, hver gang et unikt id vælges, er at man altid har de nyeste data.
- Ulempen er at man bruger ressourcer hver gang. Man kunne have indlæst alle data i variabler (eller objekter), når programmet starter op, og så ikke igen..
Ikke det store faktisk TROR jeg :) Er dog selv nybegynder men har da fundet ud at eks. cryptography kan ikke bruges på PDA'er. Desuden havde jeg problemer med Application.StartupPath fra din kode, det kunne den ikke finde ud af :S Ved ikke om det bare er mig der gør et eller andet galt :P Ændrede det dog bare til string fil = "<sti>"; det virkede også kanon :)
axcx> Jeg ved at "Application.StartupPath" ikke virker fra klasser, da det skal bruges fra "Application"/formen.. Ellers skal man tilføje "using System.Window.Forms" (eller noget i den stil) i toppen..
Men du kører koden fra formen (RetInfo_Load).. ik?
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.