Wyszukiwanie tekstu w pliku

0

Dzień dobry.
Mam następny problem :/
Mianowicie mam plik (.txt) w którym jest duuużo wierszy, ale każdy wiersz posiada swój schemat
Przykład:

**[INFO]**
"1.0.5",,,"Program","Stacja', ...

**[NAGLOWEK]**
"FS",1,0,1254,,,"0001/01/2012",,,,,"PRZYKŁADOWA STACJA", ...

**[ZAWARTOSC]**
"23",23.0000,138.2100,50.49, ...

**[NAGLOWEK]**
"WZ",1,0,1250,,,"952/13/2011",,4.5,"AAA", ...

**[ZAWARTOSC]**

**[NAGLOWEK]**
"FZ",1,0,1250,"Stacja Bazowa", ...

**[ZAWARTOSC]**
"23",23.0000,202.5200,11.8500, ...

i w programie chcę wyciągnąć tylko wiersze, które zaczynają się słowem "FS" i wiersze [ZAWARTOSC] im odpowiadające, czyli z przykładu

"FS",1,0,1254,,,"0001/01/2012",,,,,"PRZYKŁADOWA STACJA",
"23",23.0000,138.2100,50.49,
 

Nie wiem jak się za to zabrać :(
Próbowałem stworzyć tablicę string-ów i przypisać im każdą linijkę, ale nie wiem jak wyciągnąć z tej tablicy wiersze zaczynające się na "FS" i ich zawartości.
Bardzo proszę o pomoc i dziękuje za dotychczasowe rozwiązania :)
Czekam z niecierpliwością na pomysły.

0

skoro plik jest duży, to wczytywanie całego do pamięci mija się z celem.
wczytuj w pętli linijka po linijce, sprawdzaj, czy pierwsze dwa znaki to "FS" (.Substring(0, 4) == ""FS""), jeśli tak, to dodawaj linijkę do List<string>

0

I po co zakładasz drugi temat o tym samym?
Odczyt słów z pliku i zapis do textbox

0

Zmodziłem kod

 
 string[] tekst = File.ReadAllLines(path1 ,Encoding.GetEncoding("ISO-8859-2")); //wczytaj wszystkie linie
            
            string[] slowo = new string[0];
            foreach (string linia in tekst)
            {
                
                    if (linia.StartsWith("\"FS\""))
                    {

                        slowo = linia.Split(new string[] { ",", ",\"",  "[", "\r\n" }, StringSplitOptions.None).ToArray();
                        
                    }
                    else
                    {
                       
                    }
            }

Który jeżeli znajdzie linijkę "FS" to zapisuje każde słowo do tablicy.
Moje pytanie brzmi, jak zapisać też 3 linijkę od słowa "FS"
Przykład pliku który odczytuje.

[NAGLOWEK]
"FS", ...

[ZAWARTOSC]
"23",23.0000, ...

Chcę też zapisać Zawartość ("23",23.0000 itp)

0

Mniej więcej tak:

            int licznik = 0;
            foreach (string linia in tekst)
            {
 
                    if (linia.StartsWith("\"FS\""))
                    {
 
                        slowo = linia.Split(new string[] { ",", ",\"",  "[", "\r\n" }, StringSplitOptions.None).ToArray();
                        licznik = 0;
 
                    }
                    else
                    {
                        licznik++;
                        if(licznik == 3) //zapisz wiersz
                }
        }
0

Ok dałem sobie jakoś radę :P
Ale teraz zawiesiłem się nad takim problemem i nie wiem jak go przebrnąć mianowicie:
W pliku który odczytuje szuka mi linii które zaczynają się słowem "FS" i te linie mają po 62 wartości.
sęk tkwi w tym, że niektóre słowa z tych linii posiadają enter, lub więcej znaków cudzysłowów.
Przykład:

"FS",0,1,,,,"Jan Kowalski","99-999 Nibylandia ul. 4programmers 64","Domek z zapałek","20120803", ... <---- Wszystko elegancko czyta

"FS",0,1,,,,"Jan Kowalski","99-999
Nibylandia
ul. 4programmers 64","Domek z zapałek","20120803", ... <---- I tu już czyta jako następne linie, a nie jako słowo

"FS",0,1,,,,"Jan Kowalski","""99-999, Nibylandia, ul.4programmers 64""","Domek z zapałek","20120803", <---- Tu to już zupełnie nie wiem o co chodzi

Jak mogę słowo "99-999 Nibylandia ul. 4programmers 64" przeczytać jako jedna dana z jednej linii obsadzona w znakach( ,"TREŚĆ SŁOWA", )?
Próbowałem w

 slowo = linia.Split(new string[] {"\"," , ",\"" , "[", },StringSplitOptions.None).ToArray(); 

Ale pomija mi dane, które nie posiadają wartości czyli ("FS",0,1,,,,), chodzi o te przecinki.
Kompletnie nie wiem jak mam się za to zabrać :(

P.S.

I jak przypisaną do string-a tekst w formacie daty ( RRRRMMDD ) wyświetlić w formacie ( DDMMRRRR ) ?

0

Jak zrobić, żeby np. program po otwarciu pliku jak napotka błąd (ArgumentOutOfRangeException was unhandled), to wyświetli messagebox-a, otworzy ten plik i wskaże które to miejsce żeby ręcznie to poprawić :)

0

licznik linijek + try/catch + wyświetlenie messageboksa

0

zamierzasz z każdym drobnym problemem biegać na forum? tak to się nie nauczyć programować.

0
Rafal_ql napisał(a):

Jak mogę słowo "99-999 Nibylandia ul. 4programmers 64" przeczytać jako jedna dana z jednej linii obsadzona w znakach( ,"TREŚĆ SŁOWA", )?

Bardzo prosto:

 
static void Main(string[] args)
{
    string[] daneZPliku = File.ReadAllLines(@"D:\TempDev\Rafal_ql.txt");

    List<string> poprawioneDane = new List<string>();
    string nowaLinia = string.Empty;

    for (int i = 0; i < daneZPliku.Length; i++)
    {
        if (daneZPliku[i].StartsWith("\"FS\""))
        {
            nowaLinia = daneZPliku[i];
        }
        else
        {
            nowaLinia += daneZPliku[i];
        }

        if (i == daneZPliku.Length - 1 || string.IsNullOrEmpty(daneZPliku[i]))
        {
            poprawioneDane.Add(nowaLinia);
            nowaLinia = string.Empty;
        }
    }

    foreach (string s in poprawioneDane)
    {
        Console.WriteLine(s);
    }

    Console.ReadLine();
}

W poprawioneDane zawiera linie bez enterów.

0

<qoute>Działa wyśmienicie tylko jak mozna zmodyfikować kod tak, by zamiast łamania linii odczytywał dane od " do " a jeżeli są puste to od , do , Przykład: "FS",1,0,"tekst1",tekst2,"tekst 3, dalej tekst3",""tekst4","dalej tekst4"",123,, </quote>

obawiam się, że przy ogólnych założeniach jest to niemożliwe. w ""tekst4","dalej tekst4"" nie wiadomo, czy czwarty cudzysłów zamyka całość, czy jest kontynuacją. poniższy kod zadziała w miarę prawidłowo w takiej sytuacji, ale nie doda cudzysłowów do wynikowej listy, tj.

tab = {string[10]} =
    [0]: "FS"
    [1]: "1"
    [2]: "0"
    [3]: "tekst1"
    [4]: "tekst2"
    [5]: "tekst 3, dalej tekst3"
    [6]: "tekst4,dalej tekst4"
    [7]: "123"
    [8]: ""
    [9]: ""
string csv = "\"FS\",1,0,\"tekst1\",tekst2,\"tekst 3, dalej tekst3\",\"tekst4,dalej tekst4\",123,,";
bool quote = false;
var sb = new StringBuilder();
var list = new List<string>(8);

for (int i = 0; i < csv.Length; i++)
{
	var ch = csv[i];
	if (ch == '"')
		quote = !quote; 
	else
	{
		if (ch != ',' || quote)
			sb.Append(ch);
		else
		{
			list.Add(sb.ToString());
			sb = new StringBuilder();
		}
	}
}
list.Add(sb.ToString());
var tab = list.ToArray();

ZACZNIJ WRESZCIE MYŚLEĆ SAMODZIELNIE. programowanie właśnie na tym polega. jeśli nie potrafisz bez pomocy rozwiązać jakiegoś problemu, to znaczy że jest dla Ciebie za trudny, a to oznacza, że najpierw musisz przerobić podstawy, bo inaczej będziesz z każdym duperelem biegać na forum, aż w końcu dorobisz się bana.

0

Przepraszam mój błąd :(
schemat danych to:

[NAGLOWEK]
"FS",1,1250,,,,"dana1",32,""dana2,dalej dana 2"","dana 3
dalej dana 3, cały czas dana 3",dana4

I chciałbym umieścić jakoś znaki oddzielające w Split, który czytał by dane od (,) do (,) i od (,") do (",)
z tym, że niektóre dane nie posiadają ("") a niektóre nie mają wartości (,,)

Nie mam pomysłu jak to zamieścić w split (i czy jest to w ogóle możliwe).
Mam takie coś:

 
slowo = linia.Split(new string[] { ",", ",\"", "[", "\r\n" }, StringSplitOptions.None).ToArray();
0

Ty chyba za dużo chcesz zrobić w jednej linijce, a opis nadal jest niejasny.
Napisz, co chcesz otrzymać na wyjściu, w sensie jakie słowa maja się znaleźć w tablicy slowo.
I po co wywołujesz ToArray() na czymś, co już jest tablicą?

0

@Rafal_ql: z łaski swojej przeanalizuj moje rozwiązanie i odpowiednio je przerób. użyj debuggera, żeby wykonać program linijka po linijce (podpowiem - F10), użyj wtedy podglądu wartości zmiennych (okna Locals/Immediate Window/najedź myszką na zmienną).

0
somekind napisał(a):

Bardzo prosto:

 
static void Main(string[] args)
{
    string[] daneZPliku = File.ReadAllLines(@"D:\TempDev\Rafal_ql.txt");

    List<string> poprawioneDane = new List<string>();
    string nowaLinia = string.Empty;

    for (int i = 0; i < daneZPliku.Length; i++)
    {
        if (daneZPliku[i].StartsWith("\"FS\""))
        {
            nowaLinia = daneZPliku[i];
        }
        else
        {
            nowaLinia += daneZPliku[i];
        }

        if (i == daneZPliku.Length - 1 || string.IsNullOrEmpty(daneZPliku[i]))
        {
            poprawioneDane.Add(nowaLinia);
        }
    }

    foreach (string s in poprawioneDane)
    {
        Console.WriteLine(s);
    }

    Console.ReadLine();
}

W poprawioneDane zawiera linie bez enterów.

Niestety kod nie robi tego zbyt dokładnie :(
Każdą linię wypisuje mi po 4 razy i nie wiem jak zrobić, że jak program napotka linię "FS", to ma też zapamiętać linijkę [ZAWARTOSC] należącej do "FS"
Przykład danych wejściowych:

[NAGLOWEK]
"FS",0,1,"dana1",dana2,"dana3
dalej dana3
caly czas dana3,dana4,"dana5"

[ZAWARTOSC]
"23",dana1,dana2, ...

[NAGLOWEK]
"FZ", <----------- TEGO MA NIE CZYTAĆ

[ZAWARTOSC]
"23",dana1,dana2 <-------------- TEGO TEZ MA NIE CZYTAĆ

[NAGLOWEK]
"FS",0,1,"dana1",dana2,"dana3",dana4,"dana5"

[ZAWARTOSC]
"23",dana1,dana2, ...

Program ma odczytywac tylko linie [NAGLOWEK] które zaczynają się od "FS"

Schemat linii "FS" jak widać nie jest stały (w niektórych liniach występuje załamanie linii),
ale zawsze po nagłówku "FS" występuje [ZAWARTOSC](gdzie zawsze jest jedna linia zaczynająca się od "23")

chcę posklejać linię "FS" (Jeżeli będzie ona załamana) i zapisać również dane z [ZAWARTOSC]

Mój kod:

 
 private void button3_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            string[] tekst = File.ReadAllLines(path1, Encoding.GetEncoding("ISO-8859-2")); //wczytaj wszystkie linie

            string[] slowo = new string[0]; //tworzy tablice do zapisywania danych z [NAGLOWEK]
            string[] zawartosc = new string[0];// tworzy tablice do zapisywania danych z [ZAWARTOSC]
            int licznik = 4;
            int index = 1;

                foreach (string linia in tekst)
                {
                    if (linia.StartsWith("\"FS\"")) //czy linijka to FS?
                    {
                        licznik = 0;
                        slowo = linia.Split(new string[] { "," },
                            StringSplitOptions.None).ToArray(); //oddziela slowa przecinkiem i załamaniem(a załamania nie chcę tu )

                        string liniaFS = (               // zapisuje potrzebne dane z lini [NAGLOWEK]                                           
                              slowo[0]      // "FS"
                            + slowo[2]      // 1
                            + slowo[5]);    // dana3
                      
                        listBox1.Items.Add(liniaFS);  // wyswietla dane w listbox-ie
                        //licznik = 0;
                        index++;

                    }
                    else
                    {
                        licznik++;
                        if (licznik == 3) // tutaj jeżeli znajdzie linie "FS" to program zapisze 3 linijke pod "FS" czyli linie zawartosci ("23",dana1,dana2 itd.) ale jezeli linia "FS
                                             // jest zalamana, to wyswietla blad :(
                        {
                            zawartosc = linia.Split(new string[] { ",", ",\"", "[", "\r\n" },
                                StringSplitOptions.None).ToArray(); //oddziela slowa 
                            string liniaZAWARTOSC = (           // zapisuje potrzebne dane z lini [ZAWARTOSC]
                                zawartosc[0]            //"23"
                                + zawartosc[1]          //dana1
                                + zawartosc[2]          //dana2
                                );
                            listBox1.Items.Add(liniaZAWARTOSC); // wyswietla dane w listbox-ie
                            listBox1.Items.Add("\n");           // każdą linijkę "FS" i jej [ZAWARTOSC] oddziela pustym wierszem
                          
                        }
                    }
                }
               
            }
        }

Cały weekend siedzę nad tym i nie mogę sobie poradzić :/
Mam nadzieję, że mój problem jest dokładnie opisany i zrozumiały.
Byłbym bardzo wdzięczny za jakąkolwiek pomoc.
Dziękuje za wszystko.

0
Rafal_ql napisał(a):

Niestety kod nie robi tego zbyt dokładnie :(
Każdą linię wypisuje mi po 4 razy

Faktycznie zrobiłem mały błąd, w ostatnim if w pętli zabrakło wyzerowania zmiennej nowaLinia, czyli nowaLinia = string.Empty. Oczywiście wyzerować należy po jej dodaniu do kolekcji poprawioneDane.

Mam nadzieję, że mój problem jest dokładnie opisany i zrozumiały.

Chyba nie jest. Nadal nie zamieściłeś przykładu tego, jak mają wyglądać dane wyjściowe. Ciągle nie wiadomo, czy w danych wyjściowych mają być też wiersze o treści "[ZAWARTOSC]" i "[NAGLOWEK]".
Gdybyś sobie napisał przykład danych wejściowych i wyjściowych, to może łatwiej byłoby Ci wpaść na rozwiązanie.

Mam wrażenie, że sam swojego problemu nie rozumiesz i zbyt wiele chcesz zrobić na raz. Rozwiązanie wygodnie jest podzielić na trzy etapy:

  1. Odczyt danych z pliku. (Od tego jest gotowa funkcja File.ReadAllLines).
  2. Usunięcie nadmiarowych enterów z linii. (To robi mój kod.)
  3. Wybranie odpowiednich wierszy. (Czyli tego, który zaczyna się od "FS" i następnego.)

Zrobienie tego wszystkiego w jednej pętli jest wykonalne, ale tylko sobie utrudniasz. Punkty 2 i 3 powinny być oddzielnymi funkcjami.

0

Może i masz rację, sam gubię się już w tym co robię :/
Postaram się użyć twojej pętli do przeredagowania tekstu i dopiero wtedy odczytać dane.
Mam tylko jedno pytanie, czy nie można tych załamań linii umieścić jakoś w funkcji linia.Split ?
Albo zrobić taką pętlę, która skleja tekst do jednej linii aż nie napotka pustej linii

0
Rafal_ql napisał(a):

Mam tylko jedno pytanie, czy nie można tych załamań linii umieścić jakoś w funkcji linia.Split ?

Split służy raczej do dzielenia niż łączenia.

Albo zrobić taką pętlę, która skleja tekst do jednej linii aż nie napotka pustej linii

Przecież mój kod właśnie to robi. :|

0
somekind napisał(a):

Albo zrobić taką pętlę, która skleja tekst do jednej linii aż nie napotka pustej linii

Przecież mój kod właśnie to robi. :|

Troszkę poprzerabiałem kod tak, aby łączył linie aż nie napotka pustej linii ( w pętli lenght < 3)

string[] daneZPliku = File.ReadAllLines(path1, Encoding.GetEncoding("ISO-8859-2"));
            List<string> poprawioneDane = new List<string>();
            string nowaLinia = string.Empty;

            for (int i = 0; i < daneZPliku.Length; i++)
                {
                    if (daneZPliku[i].Length > 3)
                    {
                        nowaLinia += daneZPliku[i];
                    }
                    else
                    {
                        poprawioneDane.Add(nowaLinia);
                        nowaLinia = daneZPliku[i];
                    }
                }
 

Wszystko działa elegancko :)
Mam tylko jeden problem (jak zawsze zresztą) :|
W liniach jako słowa znajdują się liczby, puste słowa i litery (napis) te trzy grupy oddzielone są od siebie (,) przecinkiem.
Mój problem polega na tym, że Split dzieli linie na słowa jak napotka znak (,) przecinek.
W liczbach i pustych słowach np (123456789,,4.99,,12) wszystko jest ok, ale jak w napisie (litery) znajdzie się znak (,) przecinek to napis się dzieli splitem.
Przykład

"FS","każdy napis umieszczony jest w cudzysłowach",123.456,,,"TEN NAPIS, ZOSTANIE PODZIELONY, TEGO CHCE UNIKNAC",

Jak zmodyfikować split-a, żeby dzielił po przecinku liczby i puste pola, ale jak napotka znak (,") to niech czyta aż do znaku (",)?

Dziękuję za dotychczasową pomoc.

1
Rafal_ql napisał(a):

Jak zmodyfikować split-a, żeby dzielił po przecinku liczby i puste pola, ale jak napotka znak (,") to niech czyta aż do znaku (",)?

jesteś niepełnosprytny umysłowo? kilka postów temu podawałem Ci podobny kod, wystarczy chwilę pomyśleć, żeby go zrozumieć, a potem następną, żeby go odpowiednio przerobić. nawet specjalnie dla Ciebie urodziłem kilka dni temu artykuł o debugowaniu kodu.

0

Program działa jak należy.
Moje ostatnie pytanie:
Co warto poustawiać, gdzie zapisać autora programu itp. żeby sfinalizować aplikację?
Zrobiłem instalkę w build -> publish. Jak zrobić bardziej zaawansowaną instalację?
Gdzie wpisać autora i opis programu?

0
Rafal_ql napisał(a):

Program działa jak należy.
Moje ostatnie pytanie:
Co warto poustawiać, gdzie zapisać autora programu itp. żeby sfinalizować aplikację?
Zrobiłem instalkę w build -> publish. Jak zrobić bardziej zaawansowaną instalację?
Gdzie wpisać autora i opis programu?

A co wpisałeś w google, że nic nie znalazłeś?

1 użytkowników online, w tym zalogowanych: 0, gości: 1