Text fájl szétdarabolás kisebb text fájlokra

Fórumok

Sziasztok!

Tudtok arra könnyű megoldást, hogy egy Text file-t bizonyos sorszámok között több text fájlra bontsuk?

A lenti kóddal azt próbálom megállapítani, hogy mik legyenek azok a bizonyos sorszámok.

Érdemes az egész fájlt beolvasni egy String Array-be vagy fölösleges?


public static void main(String[] args) {
Path file = Paths.get("C:/Users/pXXXX/Desktop/O_XXXX1027_0XXX35");
int LineNumber = 1;
List intList = new ArrayList();

try (InputStream in = Files.newInputStream(file);
BufferedReader reader =
new BufferedReader(new InputStreamReader(in))) {
String line;

while ((line = reader.readLine()) != null ) {

if (line.startsWith("EDI_DC40")) {

System.out.println(line);
intList.add(LineNumber);
}
LineNumber++;
}

} catch (IOException x) {
System.err.println(x);
}

for (Integer i : intList) {
System.out.println("LineNumber: " + i);
}

}

Hozzászólások

Mekkora a fájl? Mi az hogy bizonyos sorszámok között? Itt úgy tűnik a sor eleje jelzi, hogy mit akarsz belőle kiszedni.
Én ahány fájlt létre akarnék hozni, annyi listát készítenék, raknám a listákba a megfelelő sorokat, és a végén minden listát kiírnék fájlba. A fájl beolvasásakor a sorokat már szétpakolnám, minek lássam egyben az egészet.

Vannak a fájlban EDI_DC40 -nel kezdődő sorok.
Ezek a sorok jelzik a különálló részeket.
Addig tart egy rész amíg nem találkozok még egy EDI_DC40-es sorral, de akkor az már a következő rész első sora lesz.

Az utolsó rész ugye EDI_DC40-el keződik és a null lesz a vége, amikor véget ér a fájl.

Ezzel küzdök már pár napja, de eddig csak részeredményeim vannak.

String listákat készítenél?
A readline() metódus megfelelő amivel próbálkozok?
Nem igazán vagyok tapasztalt programozó, de ezzel tudok tanulni legalább.

Köszi!

Attól függ mekkora az az állomány. :)

Én így csinálnám ha a memória nem akadály:


<?php
$darabok=preg_split('/(^|\n)EDI_DC40/',file_get_contents("file.txt"));
unset($darabok[0]); // az első EDI_DC40 előtti dolog nem érdekel
foreach ($darabok as $darab) echo "EDI_DC40".$darab."\n\n";

De nem programozóként dolgozom még mielőtt valaki beleköt (és tudom nem Java de gondolom ott is van hasonló). :P

A fenti valami ilyesmi lenne Java-ba:


import java.util.Scanner;
import java.io.File;

public class thing {
public static void main(String[] args)  throws Exception {
Scanner sc = new Scanner( new File("file.txt") ).useDelimiter("(^|\n)EDI_DC40");
while(sc.hasNext())  System.out.println("EDI_DC40"+sc.next());
};
};

Bár azt nem tudom, hogy lehetne kiszűrni, hogy az első EDI_DC40 előtti szöveget ne adja vissza eredményként (a PHP üres elemet ad vissza először akkor is ha az állomány EDI_DC40-el kezdődik, míg a Java valamiért nem)

ugyan bash de esetleg így is jó?

csplit nagyfile 'minta' {*} -ks


input megnyitása
output = null
for (;;) {
  sor olvasása inputból
  if (vége az inputnak) {
    ha output != null: output bezárás
    break
  }
  if (új rész kezdődik) {
    ha output != null: output bezárás
    új output megnyitása
  }
  sor írása outputba
}
input bezárás
profit

Vagy valami ilyesmi. Ennek méret nem akadály, extraként kezeli az üres fájlokat is. Ha a fájl nem a szekció kezdő sorral kezdődik, azon direkt elszáll NPE-vel a ciklus legvégén.

--


package valami.fajl.darabolo;

import java.io.*;

public class FajlDarabolo {

    private static final String SOURCE = "C:/Users/pXXXX/Desktop/O_XXXX1027_0XXX35";
    private static final String FP = "C:/Users/pXXXX/Desktop/O_XXXX1027_0XXX35-";
    private static final String SEP = "EDI_DC40";
    private static final String NL = System.getProperty("line.separator");

    public static void main(String[] args) throws IOException {
        int i = 1;
        BufferedWriter bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
        BufferedReader br = new BufferedReader(new FileReader(SOURCE));
        String line;
        while ((line = br.readLine()) != null) {
            if (line.startsWith(SEP)) {
                bw.close();
                bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
            }
            bw.write(line + NL);
        }
        bw.close();
        br.close();
    }
}

Köszönöm! Ez működik!! Én még azóta se tudtam megírni normálisra.

Egyedül csak annyi a baja, hogy mivel az első sor nekem rögtön EDI_DC40 -vel kezdődik a fájlban, az elején létrejön egy üres fájl, amiben csak egy sortörés van, így az i index is 1-gyel több, mint kéne neki.

Nem tudom, hogy ezt a végén kéne kitörölni, vagy már elején valahogy megtudnám neki adni, hogy ha az első sor rögtön EDI_DC40-nel kezdődik, akkor nyugodtan írjon tovább tovább a következő olyanig.

Kicsit belegányolva (nem próbáltam, nem vagyok benne biztos, hogy jó, sry):


int i = 1;
BufferedWriter bw = null;
BufferedReader br = new BufferedReader(new FileReader(SOURCE));
String line;
while ((line = br.readLine()) != null) {
    if (line.startsWith(SEP) && i != 1) {
        bw.close();
        bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
    } else {
        bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
    }
    bw.write(line + NL);
}

--
blogom

Továbbgányoltam (de én se próbáltam ki :)


int i = 1;
BufferedWriter bw = null;
BufferedReader br = new BufferedReader(new FileReader(SOURCE));
String line;
while ((line = br.readLine()) != null) {
    if (line.startsWith(SEP)) {
       if (i!=1) bw.close();
        bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
    } else if (i==1) continue;
    bw.write(line + NL);
}

Igen anélkül volt, csak azért került be mertha nem separatorral kezdődik a file akkor nullba írt volna (és tudom, hogy ronda, de hosszú volt a nap :))
De azt nem értem első fájlba így miért nem került bele a separator?
A tiedet is csak azért próbáltam átírni mert úgy tűnt, hogy a javított minden sort külön fájlba ír az else ág miatt, de lehet benéztem. :)

egyrészt jogos, az enyém minden sort külön fájlba ír - ú, de csúnyán benéztem. :-D
(OP: azt hiszem, ezt nem fogom megjavítani, mert csak még jobban beégek - de elméletileg az else után egy if-fel javítható :-D)

A tied, meg a SEP:
jogos, ezt is benéztem, belekerül a SEP. De ha nem SEP-pel kezdődik, akkor nem kerül bele semmi az első SEP-ig. Talán. De mostmár nem merek semmit mondani - tesztet kéne rá írni :-P

--
blogom


        int i = 1;
        BufferedReader br = new BufferedReader(new FileReader(SOURCE));
        String line = br.readLine();
        if (line == null || !line.startsWith(SEP)) {
            System.err.println("Nem " + SEP + " -el kezdodik!");
            return;
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
        bw.write(line + NL);
        while ((line = br.readLine()) != null) {
            if (line.startsWith(SEP)) {
                bw.close();
                bw = new BufferedWriter(new FileWriter(FP + i++ + ".txt"));
            }
            bw.write(line + NL);
        }
        bw.close();
        br.close();

Ez lehetett volna egy házi feladat, de most már mindegy :)


#!/usr/bin/python

import sys

fname=sys.argv[1]
i=1

f=open(fname+str(i),"w")
for sor in open(fname, "r"):
    if sor[:8] == "EDI_DC40":
        f.close()
        f=open(fname+str(i),"w")
        i+=1
        continue
    f.write(sor)
f.close()

Ha ki akarod írni az EDI_DC40 szót, mint szeparátor szót is, akkor ennek elhagyásával megteheted. Sőt ha marad a continue, akkor azt is megteheted, hogy például előtte sorban

...
f.write(sor[8:])
continue
...

amely hatására az EDI_DC40 szó lemarad, viszont a vele egy sorban levő többi tartalom mégis a text fájlba kerül. Tehát bármi a célod, innenntől kezdve ujjgyakorlat.

Érdekes, hogy mindenki jávázni meg pythonozni kezd, holott pont ilyesmire van kitalálva a klasszikus unix-os awk.


awk '/EDI_DC40/{ f="File"++i".txt"; } { print > f; }' input.txt

Természetesen a kezdő regexp-et ki lehet cserélni tetszőlegesre.

Know your tools!

PowerShell? (tudom gusztustalan első probálkozásom vele és a regex nem jó, nem tudom milyen formát szeretne :P)


Get-Content("File.txt") | Out-String | %{ 
   $j=1; 
   $x=[regex]::split($_,"EDI_DC40"); 
   Foreach($z in $x) { 
      $z="EDI_DC40"+$z; 
      Out-File -filepath $j -inputobject $z -Encoding default; $j++;
   } 
};

Unixon? Mert akkor hívd meg a split parancsot :-)

Nemrég ismerkedtem meg az Ammonite-tal:

Gondoltam hátha valakit érdekel, hogyan néz ki ebben:


val lines = read.lines! wd/"edi.txt"
val results = lines.foldLeft(List("")){ case (b :: tail, a) =>
  if (a.startsWith("EDI_DC40"))
    a :: b :: tail
  else
    ((b + "\r\n" + a) :: tail)
}
results.reverse.tail.zipWithIndex.foreach {
  case (content, idx) =>
    write(s"edi$idx.txt", content)
}

Powershelleshez hasonló megoldás:


val content = read! wd/"edi.txt"
val results = content.split("EDI_DC40")
results.tail.zipWithIndex.foreach {
  case (content, idx) =>
    write(s"edi$idx.txt", "EDI_DC40" + content)
}